Skip to content

Commit 32a747e

Browse files
committed
Blah
Summary: Test Plan: Reviewers: Subscribers: Tasks: Tags:
1 parent f07fbc5 commit 32a747e

File tree

2 files changed

+83
-5
lines changed

2 files changed

+83
-5
lines changed

Include/internal/pycore_typeobject.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ struct type_cache {
7676
// Type attribute lookup cache which is type-specific. Only used
7777
// for heap types where we store a small additional cache in free-threaded
7878
// builds which can be accessed without any locking.
79-
#define LOCAL_TYPE_CACHE_SIZE 32
80-
#define LOCAL_TYPE_CACHE_MAX_ENTRIES 24
81-
#define LOCAL_TYPE_CACHE_PROBE 3
79+
#define LOCAL_TYPE_CACHE_SIZE 61
80+
#define LOCAL_TYPE_CACHE_MAX_ENTRIES 48
81+
#define LOCAL_TYPE_CACHE_PROBE 7
8282

8383
struct local_type_cache_entry {
8484
PyObject *name; // reference to exactly a str or NULL
@@ -89,6 +89,9 @@ struct local_type_cache {
8989
unsigned int tp_version_tag;
9090
unsigned int cache_count;
9191
struct local_type_cache_entry entries[LOCAL_TYPE_CACHE_SIZE];
92+
#if 0
93+
int hits[LOCAL_TYPE_CACHE_SIZE], probes[LOCAL_TYPE_CACHE_SIZE], miss[LOCAL_TYPE_CACHE_SIZE];
94+
#endif
9295
};
9396

9497
#endif

Objects/typeobject.c

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5627,7 +5627,7 @@ get_local_type_cache(PyTypeObject *type, unsigned int assigned_version)
56275627

56285628
#define HASH_NAME(name) (((Py_ssize_t)(name)) >> 6)
56295629

5630-
static bool
5630+
static inline bool
56315631
try_local_cache_lookup(PyTypeObject *type, PyObject *name, PyObject **value, unsigned int *version)
56325632
{
56335633
if (!can_cache_locally(type, name)) {
@@ -5641,7 +5641,13 @@ try_local_cache_lookup(PyTypeObject *type, PyObject *name, PyObject **value, uns
56415641

56425642
Py_ssize_t index = HASH_NAME(name) % LOCAL_TYPE_CACHE_SIZE;
56435643
Py_ssize_t cur = index;
5644+
#if 0
5645+
static int probe, count;
5646+
#endif
56445647
do {
5648+
#if 0
5649+
local_cache->probes[cur]++;
5650+
#endif
56455651
struct local_type_cache_entry *entry = &local_cache->entries[cur];
56465652
PyObject *entry_name = _Py_atomic_load_ptr_acquire(&entry->name);
56475653
if (entry_name == name) {
@@ -5656,18 +5662,86 @@ try_local_cache_lookup(PyTypeObject *type, PyObject *name, PyObject **value, uns
56565662
if (version) {
56575663
*version = local_cache->tp_version_tag;
56585664
}
5665+
5666+
#if 0
5667+
if(hits[cur] - probes[cur] < -50000) {
5668+
count ++;
5669+
if(count < 50) {
5670+
printf("misfire: %s %s(%p) %ld %s(%p) %ld %d\n",
5671+
type->tp_name,
5672+
5673+
PyUnicode_AsUTF8(name),
5674+
name,
5675+
cur,
5676+
5677+
PyUnicode_AsUTF8(local_cache->entries[index].name),
5678+
local_cache->entries[index].name,
5679+
index,
5680+
5681+
local_cache->cache_count);
5682+
5683+
static int foo[LOCAL_TYPE_CACHE_SIZE + 1];
5684+
for(int j = 2; j<LOCAL_TYPE_CACHE_SIZE + 1; j++) {
5685+
for(int i = 0; i<LOCAL_TYPE_CACHE_SIZE + 1; i++) {
5686+
foo[i] = 0;
5687+
}
5688+
for(int i = 0; i<LOCAL_TYPE_CACHE_SIZE; i++) {
5689+
PyObject *name = local_cache->entries[i].name;
5690+
if (name != NULL) {
5691+
Py_ssize_t idx = ((Py_ssize_t)(name)) % j;
5692+
foo[idx] += 1;
5693+
if(name != NULL) {
5694+
//printf("%d %s %p\n", i, PyUnicode_AsUTF8(name), name);
5695+
}
5696+
}
5697+
}
5698+
int collisions = 0;
5699+
for(int i = 0; i<LOCAL_TYPE_CACHE_SIZE + 1; i++) {
5700+
if(foo[i] > 1) {
5701+
collisions += foo[i];
5702+
}
5703+
}
5704+
printf("Good match at %d %d\n", j, collisions);
5705+
}
5706+
}
5707+
}
5708+
local_cache->hits[cur]++;
5709+
static int hit_count;
5710+
hit_count++;
5711+
5712+
if((hit_count % 500000) == 0) {
5713+
printf("Avg %d %d\n", hit_count/LOCAL_TYPE_CACHE_SIZE, probe);
5714+
for(int i = 0 ;i<LOCAL_TYPE_CACHE_SIZE; i++) {
5715+
PyObject *name = local_cache->entries[i].name;
5716+
printf("%02x hits: %6d probes: %6d delta: %6d missed: %d %p %s %lx\n",
5717+
i,
5718+
local_cache->hits[i],
5719+
local_cache->probes[i], local_cache->probes[i] - local_cache->hits[i], local_cache->miss[i],
5720+
name,
5721+
name != NULL ? PyUnicode_AsUTF8(name) : "<NULL>",
5722+
name != NULL ? (HASH_NAME(name) % LOCAL_TYPE_CACHE_SIZE) : 0);
5723+
}
5724+
}
5725+
#endif
56595726

56605727
return true;
56615728
}
56625729
else if (entry_name == NULL) {
56635730
break;
56645731
}
5732+
#if 0
5733+
probe++;
5734+
#endif
56655735
cur = (cur + LOCAL_TYPE_CACHE_PROBE) % LOCAL_TYPE_CACHE_SIZE;
56665736
} while (cur != index);
5737+
#if 0
5738+
local_cache->miss[index]++;
5739+
#endif
56675740
return false;
56685741
}
56695742

5670-
static bool
5743+
5744+
static inline bool
56715745
cache_local_type_lookup(PyTypeObject *type, PyObject *name,
56725746
PyObject *res, unsigned int assigned_version)
56735747
{
@@ -5692,6 +5766,7 @@ cache_local_type_lookup(PyTypeObject *type, PyObject *name,
56925766
// Reads from other threads can proceed lock-free.
56935767
_PyObject_SetMaybeWeakref(res);
56945768
}
5769+
// printf("Caching %p %lx\n", name, HASH_NAME(name) % LOCAL_TYPE_CACHE_SIZE);
56955770

56965771
// Value is written first, then name, so when name is read the
56975772
// value is always present.

0 commit comments

Comments
 (0)