mirror of
https://github.com/python/cpython.git
synced 2026-04-14 15:50:50 +00:00
gh-144888: JIT executor bloom filter wide-type optimization and function Inlining (GH-146114)
This commit is contained in:
parent
2c6afb935a
commit
6fe91a9e80
3 changed files with 92 additions and 89 deletions
|
|
@ -1601,91 +1601,6 @@ uop_optimize(
|
|||
* Executor management
|
||||
****************************************/
|
||||
|
||||
/* We use a bloomfilter with k = 6, m = 256
|
||||
* The choice of k and the following constants
|
||||
* could do with a more rigorous analysis,
|
||||
* but here is a simple analysis:
|
||||
*
|
||||
* We want to keep the false positive rate low.
|
||||
* For n = 5 (a trace depends on 5 objects),
|
||||
* we expect 30 bits set, giving a false positive
|
||||
* rate of (30/256)**6 == 2.5e-6 which is plenty
|
||||
* good enough.
|
||||
*
|
||||
* However with n = 10 we expect 60 bits set (worst case),
|
||||
* giving a false positive of (60/256)**6 == 0.0001
|
||||
*
|
||||
* We choose k = 6, rather than a higher number as
|
||||
* it means the false positive rate grows slower for high n.
|
||||
*
|
||||
* n = 5, k = 6 => fp = 2.6e-6
|
||||
* n = 5, k = 8 => fp = 3.5e-7
|
||||
* n = 10, k = 6 => fp = 1.6e-4
|
||||
* n = 10, k = 8 => fp = 0.9e-4
|
||||
* n = 15, k = 6 => fp = 0.18%
|
||||
* n = 15, k = 8 => fp = 0.23%
|
||||
* n = 20, k = 6 => fp = 1.1%
|
||||
* n = 20, k = 8 => fp = 2.3%
|
||||
*
|
||||
* The above analysis assumes perfect hash functions,
|
||||
* but those don't exist, so the real false positive
|
||||
* rates may be worse.
|
||||
*/
|
||||
|
||||
#define K 6
|
||||
|
||||
#define SEED 20221211
|
||||
|
||||
/* TO DO -- Use more modern hash functions with better distribution of bits */
|
||||
static uint64_t
|
||||
address_to_hash(void *ptr) {
|
||||
assert(ptr != NULL);
|
||||
uint64_t uhash = SEED;
|
||||
uintptr_t addr = (uintptr_t)ptr;
|
||||
for (int i = 0; i < SIZEOF_VOID_P; i++) {
|
||||
uhash ^= addr & 255;
|
||||
uhash *= (uint64_t)PyHASH_MULTIPLIER;
|
||||
addr >>= 8;
|
||||
}
|
||||
return uhash;
|
||||
}
|
||||
|
||||
void
|
||||
_Py_BloomFilter_Init(_PyBloomFilter *bloom)
|
||||
{
|
||||
for (int i = 0; i < _Py_BLOOM_FILTER_WORDS; i++) {
|
||||
bloom->bits[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* We want K hash functions that each set 1 bit.
|
||||
* A hash function that sets 1 bit in M bits can be trivially
|
||||
* derived from a log2(M) bit hash function.
|
||||
* So we extract 8 (log2(256)) bits at a time from
|
||||
* the 64bit hash. */
|
||||
void
|
||||
_Py_BloomFilter_Add(_PyBloomFilter *bloom, void *ptr)
|
||||
{
|
||||
uint64_t hash = address_to_hash(ptr);
|
||||
assert(K <= 8);
|
||||
for (int i = 0; i < K; i++) {
|
||||
uint8_t bits = hash & 255;
|
||||
bloom->bits[bits >> 5] |= (1 << (bits&31));
|
||||
hash >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
bloom_filter_may_contain(_PyBloomFilter *bloom, _PyBloomFilter *hashes)
|
||||
{
|
||||
for (int i = 0; i < _Py_BLOOM_FILTER_WORDS; i++) {
|
||||
if ((bloom->bits[i] & hashes->bits[i]) != hashes->bits[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
link_executor(_PyExecutorObject *executor, const _PyBloomFilter *bloom)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue