Autodetect the number of CPUs when possible if NumCPUs==0
This is needed for IOCP, since telling the IOCP backend about all your CPUs is a good idea. It'll also come in handy with asn's multithreaded crypto stuff, and for people who run servers without reading the manual.
This commit is contained in:
parent
c612ddee17
commit
73d93c033d
|
@ -0,0 +1,3 @@
|
|||
o Minor features
|
||||
- If you set the NumCPUs option to 0, Tor will try to detect how many
|
||||
CPUs you have. This is the new default behavior.
|
|
@ -226,7 +226,7 @@ dnl -------------------------------------------------------------------
|
|||
dnl Check for functions before libevent, since libevent-1.2 apparently
|
||||
dnl exports strlcpy without defining it in a header.
|
||||
|
||||
AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit strlcat strlcpy strtoull getaddrinfo localtime_r gmtime_r memmem strtok_r flock prctl vasprintf)
|
||||
AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit strlcat strlcpy strtoull getaddrinfo localtime_r gmtime_r memmem strtok_r flock prctl vasprintf sysconf)
|
||||
|
||||
using_custom_malloc=no
|
||||
if test x$enable_openbsd_malloc = xyes ; then
|
||||
|
|
|
@ -860,7 +860,9 @@ is non-zero):
|
|||
characters inclusive, and must contain only the characters [a-zA-Z0-9].
|
||||
|
||||
**NumCPUs** __num__::
|
||||
How many processes to use at once for decrypting onionskins. (Default: 1)
|
||||
How many processes to use at once for decrypting onionskins and other
|
||||
parallelizable operations. If this is set to 0, Tor will try to detect
|
||||
how many CPUs you have, defaulting to 1 if it can't tell. (Default: 0)
|
||||
|
||||
**ORPort** __PORT__::
|
||||
Advertise this port to listen for connections from Tor clients and servers.
|
||||
|
|
|
@ -1898,6 +1898,52 @@ spawn_exit(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
/** Implementation logic for compute_num_cpus(). */
|
||||
static int
|
||||
compute_num_cpus_impl(void)
|
||||
{
|
||||
#ifdef MS_WINDOWS
|
||||
SYSTEM_INFO info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
GetSystemInfo(&info);
|
||||
if (info.dwNumberOfProcessors >= 1 && info.dwNumberOfProcessors < INT_MAX)
|
||||
return (int)info.dwNumberOfProcessors;
|
||||
else
|
||||
return -1;
|
||||
#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
|
||||
long cpus = sysconf(_SC_NPROCESSORS_CONF);
|
||||
if (cpus >= 1 && cpus < INT_MAX)
|
||||
return (int)cpus;
|
||||
else
|
||||
return -1;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define MAX_DETECTABLE_CPUS 16
|
||||
|
||||
/** Return how many CPUs we are running with. We assume that nobody is
|
||||
* using hot-swappable CPUs, so we don't recompute this after the first
|
||||
* time. Return -1 if we don't know how to tell the number of CPUs on this
|
||||
* system.
|
||||
*/
|
||||
int
|
||||
compute_num_cpus(void)
|
||||
{
|
||||
static int num_cpus = -2;
|
||||
if (num_cpus == -2) {
|
||||
num_cpus = compute_num_cpus_impl();
|
||||
tor_assert(num_cpus != -2);
|
||||
if (num_cpus > MAX_DETECTABLE_CPUS)
|
||||
log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I "
|
||||
"will not autodetect any more than %d, though. If you "
|
||||
"want to configure more, set NumCPUs in your torrc",
|
||||
num_cpus, MAX_DETECTABLE_CPUS);
|
||||
}
|
||||
return num_cpus;
|
||||
}
|
||||
|
||||
/** Set *timeval to the current time of day. On error, log and terminate.
|
||||
* (Same as gettimeofday(timeval,NULL), but never returns -1.)
|
||||
*/
|
||||
|
|
|
@ -522,6 +522,8 @@ void spawn_exit(void) ATTR_NORETURN;
|
|||
#undef TOR_IS_MULTITHREADED
|
||||
#endif
|
||||
|
||||
int compute_num_cpus(void);
|
||||
|
||||
/* Because we use threads instead of processes on most platforms (Windows,
|
||||
* Linux, etc), we need locking for them. On platforms with poor thread
|
||||
* support or broken gethostbyname_r, these functions are no-ops. */
|
||||
|
|
|
@ -307,7 +307,7 @@ static config_var_t _option_vars[] = {
|
|||
V(WarnUnsafeSocks, BOOL, "1"),
|
||||
V(NoPublish, BOOL, "0"),
|
||||
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
|
||||
V(NumCpus, UINT, "1"),
|
||||
V(NumCpus, UINT, "0"),
|
||||
V(NumEntryGuards, UINT, "3"),
|
||||
V(ORListenAddress, LINELIST, NULL),
|
||||
V(ORPort, UINT, "0"),
|
||||
|
@ -4892,6 +4892,19 @@ config_parse_interval(const char *s, int *ok)
|
|||
return (int)r;
|
||||
}
|
||||
|
||||
/** Return the number of cpus configured in <b>options</b>. If we are
|
||||
* told to auto-detect the number of cpus, return the auto-detected number. */
|
||||
int
|
||||
get_num_cpus(const or_options_t *options)
|
||||
{
|
||||
if (options->NumCpus == 0) {
|
||||
int n = compute_num_cpus();
|
||||
return (n >= 1) ? n : 1;
|
||||
} else {
|
||||
return options->NumCpus;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the libevent library.
|
||||
*/
|
||||
|
@ -4913,7 +4926,7 @@ init_libevent(const or_options_t *options)
|
|||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.disable_iocp = options->DisableIOCP;
|
||||
cfg.num_cpus = options->NumCpus;
|
||||
cfg.num_cpus = get_num_cpus(options);
|
||||
|
||||
tor_libevent_initialize(&cfg);
|
||||
|
||||
|
|
|
@ -57,6 +57,8 @@ char *options_get_datadir_fname2_suffix(or_options_t *options,
|
|||
#define get_datadir_fname_suffix(sub1, suffix) \
|
||||
get_datadir_fname2_suffix((sub1), NULL, (suffix))
|
||||
|
||||
int get_num_cpus(const or_options_t *options);
|
||||
|
||||
or_state_t *get_or_state(void);
|
||||
int or_state_save(time_t now);
|
||||
|
||||
|
|
|
@ -366,7 +366,7 @@ spawn_cpuworker(void)
|
|||
static void
|
||||
spawn_enough_cpuworkers(void)
|
||||
{
|
||||
int num_cpuworkers_needed = get_options()->NumCpus;
|
||||
int num_cpuworkers_needed = get_num_cpus(get_options());
|
||||
|
||||
if (num_cpuworkers_needed < MIN_CPUWORKERS)
|
||||
num_cpuworkers_needed = MIN_CPUWORKERS;
|
||||
|
|
Loading…
Reference in New Issue