Run miner threads at priority `SCHED_IDLE` (see `sched(7)`)
This way miners can fully utilize all spare CPU power without affecting performance of the rest of the system.
This commit is contained in:
parent
0a1eaf26f9
commit
2cc49b3877
|
@ -83,6 +83,7 @@ using namespace epee;
|
|||
|
||||
#include "miner.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "thread.h"
|
||||
|
||||
|
||||
extern "C" void slow_hash_allocate_state();
|
||||
|
@ -95,6 +96,7 @@ namespace cryptonote
|
|||
const command_line::arg_descriptor<std::string> arg_extra_messages = {"extra-messages-file", "Specify file for extra messages to include into coinbase transactions", "", true};
|
||||
const command_line::arg_descriptor<std::string> arg_start_mining = {"start-mining", "Specify wallet address to mining for", "", true};
|
||||
const command_line::arg_descriptor<uint32_t> arg_mining_threads = {"mining-threads", "Specify mining threads count", 0, true};
|
||||
const command_line::arg_descriptor<bool> arg_mining_threads_idle = {"mining-threads-idle", "Run mining threads at the idle/lowest possible system priority. This is an alternative to the background mining feature.", false, true};
|
||||
const command_line::arg_descriptor<bool> arg_bg_mining_enable = {"bg-mining-enable", "enable background mining", true, true};
|
||||
const command_line::arg_descriptor<bool> arg_bg_mining_ignore_battery = {"bg-mining-ignore-battery", "if true, assumes plugged in when unable to query system power status", false, true};
|
||||
const command_line::arg_descriptor<uint64_t> arg_bg_mining_min_idle_interval_seconds = {"bg-mining-min-idle-interval", "Specify min lookback interval in seconds for determining idle state", miner::BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS, true};
|
||||
|
@ -120,6 +122,7 @@ namespace cryptonote
|
|||
m_total_hashes(0),
|
||||
m_do_print_hashrate(false),
|
||||
m_do_mining(false),
|
||||
m_threads_idle(false),
|
||||
m_current_hash_rate(0),
|
||||
m_is_background_mining_enabled(false),
|
||||
m_min_idle_seconds(BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS),
|
||||
|
@ -287,6 +290,7 @@ namespace cryptonote
|
|||
command_line::add_arg(desc, arg_extra_messages);
|
||||
command_line::add_arg(desc, arg_start_mining);
|
||||
command_line::add_arg(desc, arg_mining_threads);
|
||||
command_line::add_arg(desc, arg_mining_threads_idle);
|
||||
command_line::add_arg(desc, arg_bg_mining_enable);
|
||||
command_line::add_arg(desc, arg_bg_mining_ignore_battery);
|
||||
command_line::add_arg(desc, arg_bg_mining_min_idle_interval_seconds);
|
||||
|
@ -350,6 +354,11 @@ namespace cryptonote
|
|||
if(command_line::has_arg(vm, arg_bg_mining_miner_target_percentage))
|
||||
set_mining_target( command_line::get_arg(vm, arg_bg_mining_miner_target_percentage) );
|
||||
|
||||
if(command_line::has_arg(vm, arg_mining_threads_idle))
|
||||
{
|
||||
m_threads_idle = command_line::get_arg(vm, arg_mining_threads_idle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
|
@ -367,7 +376,7 @@ namespace cryptonote
|
|||
return m_threads_total;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
bool miner::start(const account_public_address& adr, size_t threads_count, bool do_background, bool ignore_battery)
|
||||
bool miner::start(const account_public_address& adr, size_t threads_count, bool threads_idle, bool do_background, bool ignore_battery)
|
||||
{
|
||||
m_block_reward = 0;
|
||||
m_mine_address = adr;
|
||||
|
@ -401,7 +410,13 @@ namespace cryptonote
|
|||
|
||||
for(size_t i = 0; i != m_threads_total; i++)
|
||||
{
|
||||
m_threads.push_back(boost::thread(m_attrs, boost::bind(&miner::worker_thread, this)));
|
||||
if (threads_idle) {
|
||||
m_threads.push_back(create_background_thread(m_attrs, boost::bind(
|
||||
&miner::worker_thread, this)));
|
||||
} else {
|
||||
m_threads.push_back(boost::thread(m_attrs, boost::bind(
|
||||
&miner::worker_thread, this)));
|
||||
}
|
||||
}
|
||||
|
||||
if (threads_count == 0)
|
||||
|
@ -411,6 +426,9 @@ namespace cryptonote
|
|||
|
||||
if( get_is_background_mining_enabled() )
|
||||
{
|
||||
if (threads_idle) {
|
||||
MERROR("Feature --mining-threads-idle is an alternative to background mining and doesn't make sense to be used together.");
|
||||
}
|
||||
m_background_mining_thread = boost::thread(m_attrs, boost::bind(&miner::background_worker_thread, this));
|
||||
LOG_PRINT_L0("Background mining controller thread started" );
|
||||
}
|
||||
|
@ -493,7 +511,7 @@ namespace cryptonote
|
|||
{
|
||||
if(m_do_mining)
|
||||
{
|
||||
start(m_mine_address, m_threads_total, get_is_background_mining_enabled(), get_ignore_battery());
|
||||
start(m_mine_address, m_threads_total, m_threads_idle, get_is_background_mining_enabled(), get_ignore_battery());
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace cryptonote
|
|||
static void init_options(boost::program_options::options_description& desc);
|
||||
bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height, uint64_t block_reward);
|
||||
bool on_block_chain_update();
|
||||
bool start(const account_public_address& adr, size_t threads_count, bool do_background = false, bool ignore_battery = false);
|
||||
bool start(const account_public_address& adr, size_t threads_count, bool threads_idle, bool do_background = false, bool ignore_battery = false);
|
||||
uint64_t get_speed() const;
|
||||
uint32_t get_threads_count() const;
|
||||
void send_stop_signal();
|
||||
|
@ -150,6 +150,7 @@ namespace cryptonote
|
|||
std::list<uint64_t> m_last_hash_rates;
|
||||
bool m_do_print_hashrate;
|
||||
bool m_do_mining;
|
||||
bool m_threads_idle;
|
||||
std::vector<std::pair<uint64_t, uint64_t>> m_threads_autodetect;
|
||||
boost::thread::attributes m_attrs;
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
// Copyright (c) 2014-2022, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#endif // _WIN32
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
|
||||
// Creates and returns a thread running at an idle priority (if possible).
|
||||
template<typename Callable>
|
||||
boost::thread create_background_thread(boost::thread::attributes& attrs, Callable func);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
template<typename Callable>
|
||||
boost::thread create_background_thread(boost::thread::attributes& attrs, Callable func) {
|
||||
return boost::thread(attrs, [func = std::move(func)]() mutable {
|
||||
auto handle = GetCurrentThread();
|
||||
if (!SetThreadPriority(handle, THREAD_MODE_BACKGROUND_BEGIN)) {
|
||||
if (!SetThreadPriority(handle, THREAD_PRIORITY_LOWEST)) {
|
||||
MWARNING("Can't set a background thread priority: "
|
||||
<< std::error_code(GetLastError(), std::system_category()));
|
||||
|
||||
}
|
||||
}
|
||||
std::move(func)();
|
||||
});
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<typename Callable>
|
||||
boost::thread create_background_thread(boost::thread::attributes& attrs, Callable func) {
|
||||
auto thread = boost::thread(attrs, std::move(func));
|
||||
auto handle = thread.native_handle();
|
||||
int policy;
|
||||
struct sched_param param;
|
||||
int error;
|
||||
if ((error = pthread_getschedparam(handle, &policy, ¶m)) != 0) {
|
||||
MWARNING("Can't set a background thread priority: pthread_getschedparam "
|
||||
"failed: " << std::strerror(error));
|
||||
return thread;
|
||||
}
|
||||
#ifdef SCHED_IDLE
|
||||
policy = SCHED_IDLE;
|
||||
// In particular MacOS doesn't support `SCHED_IDLE`. In the future we might
|
||||
// consider using https://developer.apple.com/documentation/dispatch
|
||||
// instead.
|
||||
#else
|
||||
#warning SCHED_IDLE policy not available, falling back to minimum priority
|
||||
param.sched_priority = sched_get_priority_min(policy);
|
||||
#endif
|
||||
if ((error = pthread_setschedparam(handle, policy, ¶m)) != 0) {
|
||||
MWARNING("Can't set a background thread priority: pthread_setschedparam "
|
||||
"to SCHED_IDLE failed: " << std::strerror(error));
|
||||
}
|
||||
return thread;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace cryptonote
|
Loading…
Reference in New Issue