mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Memoize summarize_protover_flags()
Our tests showed that this function is responsible for a huge number of our malloc/free() calls. It's a prime candidate for being memoized. Closes ticket 27225.
This commit is contained in:
parent
275e831cea
commit
6d93820499
5
changes/ticket27225
Normal file
5
changes/ticket27225
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
o Minor features (performance):
|
||||||
|
- Avoid parsing the same protocol-versions string over and over
|
||||||
|
in summarize_protover_flags(). This should save us a huge number
|
||||||
|
of malloc calls on startup, and may reduce memory fragmentation with
|
||||||
|
some allocators. Closes ticket 27225.
|
@ -33,6 +33,7 @@
|
|||||||
#include "core/or/relay.h"
|
#include "core/or/relay.h"
|
||||||
#include "core/or/scheduler.h"
|
#include "core/or/scheduler.h"
|
||||||
#include "core/or/status.h"
|
#include "core/or/status.h"
|
||||||
|
#include "core/or/versions.h"
|
||||||
#include "feature/api/tor_api.h"
|
#include "feature/api/tor_api.h"
|
||||||
#include "feature/api/tor_api_internal.h"
|
#include "feature/api/tor_api_internal.h"
|
||||||
#include "feature/client/addressmap.h"
|
#include "feature/client/addressmap.h"
|
||||||
@ -791,6 +792,7 @@ tor_free_all(int postfork)
|
|||||||
dos_free_all();
|
dos_free_all();
|
||||||
circuitmux_ewma_free_all();
|
circuitmux_ewma_free_all();
|
||||||
accounting_free_all();
|
accounting_free_all();
|
||||||
|
protover_summary_cache_free_all();
|
||||||
|
|
||||||
if (!postfork) {
|
if (!postfork) {
|
||||||
config_free_all();
|
config_free_all();
|
||||||
|
@ -377,6 +377,62 @@ sort_version_list(smartlist_t *versions, int remove_duplicates)
|
|||||||
smartlist_uniq(versions, compare_tor_version_str_ptr_, tor_free_);
|
smartlist_uniq(versions, compare_tor_version_str_ptr_, tor_free_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** If there are more than this many entries, we're probably under
|
||||||
|
* some kind of weird DoS. */
|
||||||
|
static const int MAX_PROTOVER_SUMMARY_MAP_LEN = 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map from protover string to protover_summary_flags_t.
|
||||||
|
*/
|
||||||
|
static strmap_t *protover_summary_map = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper. Given a non-NULL protover string <b>protocols</b>, set <b>out</b>
|
||||||
|
* to its summary, and memoize the result in <b>protover_summary_map</b>.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
memoize_protover_summary(protover_summary_flags_t *out,
|
||||||
|
const char *protocols)
|
||||||
|
{
|
||||||
|
if (!protover_summary_map)
|
||||||
|
protover_summary_map = strmap_new();
|
||||||
|
|
||||||
|
if (strmap_size(protover_summary_map) >= MAX_PROTOVER_SUMMARY_MAP_LEN) {
|
||||||
|
protover_summary_cache_free_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
const protover_summary_flags_t *cached =
|
||||||
|
strmap_get(protover_summary_map, protocols);
|
||||||
|
|
||||||
|
if (cached != NULL) {
|
||||||
|
/* We found a cached entry; no need to parse this one. */
|
||||||
|
memcpy(out, cached, sizeof(protover_summary_flags_t));
|
||||||
|
tor_assert(out->protocols_known);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(out, 0, sizeof(*out));
|
||||||
|
out->protocols_known = 1;
|
||||||
|
out->supports_extend2_cells =
|
||||||
|
protocol_list_supports_protocol(protocols, PRT_RELAY, 2);
|
||||||
|
out->supports_ed25519_link_handshake_compat =
|
||||||
|
protocol_list_supports_protocol(protocols, PRT_LINKAUTH, 3);
|
||||||
|
out->supports_ed25519_link_handshake_any =
|
||||||
|
protocol_list_supports_protocol_or_later(protocols, PRT_LINKAUTH, 3);
|
||||||
|
out->supports_ed25519_hs_intro =
|
||||||
|
protocol_list_supports_protocol(protocols, PRT_HSINTRO, 4);
|
||||||
|
out->supports_v3_hsdir =
|
||||||
|
protocol_list_supports_protocol(protocols, PRT_HSDIR,
|
||||||
|
PROTOVER_HSDIR_V3);
|
||||||
|
out->supports_v3_rendezvous_point =
|
||||||
|
protocol_list_supports_protocol(protocols, PRT_HSREND,
|
||||||
|
PROTOVER_HS_RENDEZVOUS_POINT_V3);
|
||||||
|
|
||||||
|
protover_summary_flags_t *new_cached = tor_memdup(out, sizeof(*out));
|
||||||
|
cached = strmap_set(protover_summary_map, protocols, new_cached);
|
||||||
|
tor_assert(!cached);
|
||||||
|
}
|
||||||
|
|
||||||
/** Summarize the protocols listed in <b>protocols</b> into <b>out</b>,
|
/** Summarize the protocols listed in <b>protocols</b> into <b>out</b>,
|
||||||
* falling back or correcting them based on <b>version</b> as appropriate.
|
* falling back or correcting them based on <b>version</b> as appropriate.
|
||||||
*/
|
*/
|
||||||
@ -388,21 +444,7 @@ summarize_protover_flags(protover_summary_flags_t *out,
|
|||||||
tor_assert(out);
|
tor_assert(out);
|
||||||
memset(out, 0, sizeof(*out));
|
memset(out, 0, sizeof(*out));
|
||||||
if (protocols) {
|
if (protocols) {
|
||||||
out->protocols_known = 1;
|
memoize_protover_summary(out, protocols);
|
||||||
out->supports_extend2_cells =
|
|
||||||
protocol_list_supports_protocol(protocols, PRT_RELAY, 2);
|
|
||||||
out->supports_ed25519_link_handshake_compat =
|
|
||||||
protocol_list_supports_protocol(protocols, PRT_LINKAUTH, 3);
|
|
||||||
out->supports_ed25519_link_handshake_any =
|
|
||||||
protocol_list_supports_protocol_or_later(protocols, PRT_LINKAUTH, 3);
|
|
||||||
out->supports_ed25519_hs_intro =
|
|
||||||
protocol_list_supports_protocol(protocols, PRT_HSINTRO, 4);
|
|
||||||
out->supports_v3_hsdir =
|
|
||||||
protocol_list_supports_protocol(protocols, PRT_HSDIR,
|
|
||||||
PROTOVER_HSDIR_V3);
|
|
||||||
out->supports_v3_rendezvous_point =
|
|
||||||
protocol_list_supports_protocol(protocols, PRT_HSREND,
|
|
||||||
PROTOVER_HS_RENDEZVOUS_POINT_V3);
|
|
||||||
}
|
}
|
||||||
if (version && !strcmpstart(version, "Tor ")) {
|
if (version && !strcmpstart(version, "Tor ")) {
|
||||||
if (!out->protocols_known) {
|
if (!out->protocols_known) {
|
||||||
@ -420,3 +462,13 @@ summarize_protover_flags(protover_summary_flags_t *out,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free all space held in the protover_summary_map.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
protover_summary_cache_free_all(void)
|
||||||
|
{
|
||||||
|
strmap_free(protover_summary_map, tor_free_);
|
||||||
|
protover_summary_map = NULL;
|
||||||
|
}
|
||||||
|
@ -41,4 +41,6 @@ void summarize_protover_flags(protover_summary_flags_t *out,
|
|||||||
const char *protocols,
|
const char *protocols,
|
||||||
const char *version);
|
const char *version);
|
||||||
|
|
||||||
|
void protover_summary_cache_free_all(void);
|
||||||
|
|
||||||
#endif /* !defined(TOR_VERSIONS_H) */
|
#endif /* !defined(TOR_VERSIONS_H) */
|
||||||
|
Loading…
Reference in New Issue
Block a user