lqft-python-engine 0.9.4__tar.gz → 0.9.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/PKG-INFO +2 -2
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/lqft_engine.c +285 -215
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/lqft_python_engine.egg-info/PKG-INFO +2 -2
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/setup.py +4 -7
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/LICENSE.md +0 -0
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/lqft_engine.py +0 -0
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/lqft_python_engine.egg-info/SOURCES.txt +0 -0
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/lqft_python_engine.egg-info/dependency_links.txt +0 -0
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/lqft_python_engine.egg-info/requires.txt +0 -0
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/lqft_python_engine.egg-info/top_level.txt +0 -0
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/pyproject.toml +0 -0
- {lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/setup.cfg +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lqft-python-engine
|
|
3
|
-
Version: 0.9.
|
|
4
|
-
Summary: LQFT Engine:
|
|
3
|
+
Version: 0.9.7
|
|
4
|
+
Summary: LQFT Engine: 1.3M+ Ops/sec Merkle Forest & Hardware Spinlocks (v0.9.5 Stable)
|
|
5
5
|
Home-page: https://github.com/ParjadM/Log-Quantum-Fractal-Tree-LQFT-
|
|
6
6
|
Author: Parjad Minooei
|
|
7
7
|
License: MIT
|
|
@@ -11,39 +11,64 @@
|
|
|
11
11
|
#include <stdint.h>
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* LQFT C-Engine - V0.9.
|
|
14
|
+
* LQFT C-Engine - V0.9.8 (The Merkle Forest Architecture)
|
|
15
15
|
* Architect: Parjad Minooei
|
|
16
16
|
* * SYSTEMS ARCHITECTURE MILESTONES:
|
|
17
|
-
* 1.
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* 1. ROOT SHARDING: Eliminated the "Root Swap Singularity". The engine now
|
|
18
|
+
* manages 2,048 independent Merkle-Trees, mathematically routing incoming
|
|
19
|
+
* hashes via their top 11 bits.
|
|
20
|
+
* 2. ZERO-CONTENTION OCC: With 16 threads spread across 2,048 roots,
|
|
21
|
+
* OCC thrashing drops to near 0%, allowing linear CPU scaling.
|
|
20
22
|
*/
|
|
21
23
|
|
|
22
|
-
#
|
|
24
|
+
#if defined(_MSC_VER)
|
|
23
25
|
#include <windows.h>
|
|
24
26
|
#include <intrin.h>
|
|
25
27
|
#pragma intrinsic(_InterlockedIncrement)
|
|
26
28
|
#pragma intrinsic(_InterlockedDecrement)
|
|
27
|
-
|
|
28
|
-
#
|
|
29
|
-
#define LQFT_RWLOCK_RDLOCK(lock) AcquireSRWLockShared(lock)
|
|
30
|
-
#define LQFT_RWLOCK_WRLOCK(lock) AcquireSRWLockExclusive(lock)
|
|
31
|
-
#define LQFT_RWLOCK_UNLOCK_RD(lock) ReleaseSRWLockShared(lock)
|
|
32
|
-
#define LQFT_RWLOCK_UNLOCK_WR(lock) ReleaseSRWLockExclusive(lock)
|
|
29
|
+
#pragma intrinsic(_InterlockedCompareExchange)
|
|
30
|
+
#pragma intrinsic(_InterlockedExchange)
|
|
33
31
|
#define ATOMIC_INC(ptr) _InterlockedIncrement((LONG volatile*)(ptr))
|
|
34
32
|
#define ATOMIC_DEC(ptr) _InterlockedDecrement((LONG volatile*)(ptr))
|
|
35
33
|
#define PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0)
|
|
34
|
+
#define CPU_PAUSE _mm_pause()
|
|
36
35
|
#else
|
|
37
36
|
#include <pthread.h>
|
|
38
|
-
typedef pthread_rwlock_t lqft_rwlock_t;
|
|
39
|
-
#define LQFT_RWLOCK_INIT(lock) pthread_rwlock_init(lock, NULL)
|
|
40
|
-
#define LQFT_RWLOCK_RDLOCK(lock) pthread_rwlock_rdlock(lock)
|
|
41
|
-
#define LQFT_RWLOCK_WRLOCK(lock) pthread_rwlock_wrlock(lock)
|
|
42
|
-
#define LQFT_RWLOCK_UNLOCK_RD(lock) pthread_rwlock_unlock(lock)
|
|
43
|
-
#define LQFT_RWLOCK_UNLOCK_WR(lock) pthread_rwlock_unlock(lock)
|
|
44
37
|
#define ATOMIC_INC(ptr) __sync_add_and_fetch((ptr), 1)
|
|
45
38
|
#define ATOMIC_DEC(ptr) __sync_sub_and_fetch((ptr), 1)
|
|
46
39
|
#define PREFETCH(ptr) __builtin_prefetch(ptr)
|
|
40
|
+
#if defined(__i386__) || defined(__x86_64__)
|
|
41
|
+
#define CPU_PAUSE __asm__ volatile("pause\n": : :"memory")
|
|
42
|
+
#elif defined(__aarch64__) || defined(__arm__)
|
|
43
|
+
#define CPU_PAUSE __asm__ volatile("yield\n": : :"memory")
|
|
44
|
+
#else
|
|
45
|
+
#define CPU_PAUSE do {} while(0)
|
|
46
|
+
#endif
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
typedef struct {
|
|
50
|
+
volatile long flag;
|
|
51
|
+
char padding[60];
|
|
52
|
+
} FastSpinLock;
|
|
53
|
+
|
|
54
|
+
#ifdef _MSC_VER
|
|
55
|
+
static inline void fast_lock(volatile long* lk) {
|
|
56
|
+
while (_InterlockedCompareExchange(lk, 1, 0) == 1) {
|
|
57
|
+
while (*lk) { CPU_PAUSE; }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
static inline void fast_unlock(volatile long* lk) {
|
|
61
|
+
_InterlockedExchange(lk, 0);
|
|
62
|
+
}
|
|
63
|
+
#else
|
|
64
|
+
static inline void fast_lock(volatile long* lk) {
|
|
65
|
+
while (__sync_val_compare_and_swap(lk, 0, 1) == 1) {
|
|
66
|
+
while (*lk) { CPU_PAUSE; }
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
static inline void fast_unlock(volatile long* lk) {
|
|
70
|
+
__sync_lock_release(lk);
|
|
71
|
+
}
|
|
47
72
|
#endif
|
|
48
73
|
|
|
49
74
|
#define BIT_PARTITION 5
|
|
@@ -53,10 +78,13 @@
|
|
|
53
78
|
#define STRIPE_MASK (STRIPE_SIZE - 1)
|
|
54
79
|
#define TOMBSTONE ((LQFTNode*)1)
|
|
55
80
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
81
|
+
// V0.9.8: 2048 Independent Roots
|
|
82
|
+
#define NUM_ROOTS 2048
|
|
83
|
+
#define ROOT_MASK 0x7FF
|
|
84
|
+
|
|
85
|
+
#define NUM_ARENAS 128
|
|
86
|
+
#define ARENA_MASK (NUM_ARENAS - 1)
|
|
87
|
+
#define ARENA_CHUNK_SIZE 16384
|
|
60
88
|
|
|
61
89
|
typedef struct LQFTNode {
|
|
62
90
|
void* value;
|
|
@@ -67,12 +95,6 @@ typedef struct LQFTNode {
|
|
|
67
95
|
int ref_count;
|
|
68
96
|
} LQFTNode;
|
|
69
97
|
|
|
70
|
-
// ===================================================================
|
|
71
|
-
// CUSTOM MEMORY ARENA
|
|
72
|
-
// ===================================================================
|
|
73
|
-
#define ARENA_CHUNK_SIZE 16384
|
|
74
|
-
static lqft_rwlock_t alloc_lock;
|
|
75
|
-
|
|
76
98
|
typedef struct NodeChunk {
|
|
77
99
|
LQFTNode nodes[ARENA_CHUNK_SIZE];
|
|
78
100
|
struct NodeChunk* next;
|
|
@@ -83,23 +105,24 @@ typedef struct ChildChunk {
|
|
|
83
105
|
struct ChildChunk* next;
|
|
84
106
|
} ChildChunk;
|
|
85
107
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
108
|
+
typedef struct {
|
|
109
|
+
FastSpinLock lock;
|
|
110
|
+
NodeChunk* current_node_chunk;
|
|
111
|
+
int node_chunk_idx;
|
|
112
|
+
LQFTNode* node_free_list;
|
|
113
|
+
ChildChunk* current_child_chunk;
|
|
114
|
+
int child_chunk_idx;
|
|
115
|
+
LQFTNode*** array_free_list;
|
|
116
|
+
} AllocArena;
|
|
117
|
+
|
|
118
|
+
static AllocArena arenas[NUM_ARENAS];
|
|
94
119
|
static LQFTNode** registry = NULL;
|
|
95
|
-
|
|
96
120
|
static int physical_node_count = 0;
|
|
97
|
-
static LQFTNode* global_root = NULL;
|
|
98
121
|
|
|
99
|
-
|
|
100
|
-
static
|
|
101
|
-
static
|
|
102
|
-
static
|
|
122
|
+
// V0.9.8: The Merkle Forest
|
|
123
|
+
static LQFTNode* global_roots[NUM_ROOTS];
|
|
124
|
+
static FastSpinLock root_locks[NUM_ROOTS];
|
|
125
|
+
static FastSpinLock stripe_locks[NUM_STRIPES];
|
|
103
126
|
|
|
104
127
|
const uint64_t FNV_OFFSET_BASIS = 14695981039346656037ULL;
|
|
105
128
|
const uint64_t FNV_PRIME = 1099511628211ULL;
|
|
@@ -134,47 +157,49 @@ char* portable_strdup(const char* s) {
|
|
|
134
157
|
#endif
|
|
135
158
|
}
|
|
136
159
|
|
|
137
|
-
LQFTNode* create_node(void* value, uint64_t key_hash, LQFTNode** children_src) {
|
|
160
|
+
LQFTNode* create_node(void* value, uint64_t key_hash, LQFTNode** children_src, uint64_t full_hash) {
|
|
161
|
+
uint32_t a_idx = (uint32_t)(full_hash & ARENA_MASK);
|
|
162
|
+
AllocArena* arena = &arenas[a_idx];
|
|
138
163
|
LQFTNode* node = NULL;
|
|
139
|
-
LQFT_RWLOCK_WRLOCK(&alloc_lock);
|
|
140
164
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
165
|
+
fast_lock(&arena->lock.flag);
|
|
166
|
+
if (arena->node_free_list) {
|
|
167
|
+
node = arena->node_free_list;
|
|
168
|
+
arena->node_free_list = (LQFTNode*)node->children;
|
|
144
169
|
} else {
|
|
145
|
-
if (node_chunk_idx >= ARENA_CHUNK_SIZE) {
|
|
170
|
+
if (arena->node_chunk_idx >= ARENA_CHUNK_SIZE) {
|
|
146
171
|
NodeChunk* new_chunk = (NodeChunk*)malloc(sizeof(NodeChunk));
|
|
147
|
-
new_chunk->next = current_node_chunk;
|
|
148
|
-
current_node_chunk = new_chunk;
|
|
149
|
-
node_chunk_idx = 0;
|
|
172
|
+
new_chunk->next = arena->current_node_chunk;
|
|
173
|
+
arena->current_node_chunk = new_chunk;
|
|
174
|
+
arena->node_chunk_idx = 0;
|
|
150
175
|
}
|
|
151
|
-
node = ¤t_node_chunk->nodes[node_chunk_idx++];
|
|
176
|
+
node = &arena->current_node_chunk->nodes[arena->node_chunk_idx++];
|
|
152
177
|
}
|
|
153
178
|
|
|
154
179
|
node->value = value;
|
|
155
180
|
node->key_hash = key_hash;
|
|
156
|
-
node->full_hash_val =
|
|
181
|
+
node->full_hash_val = full_hash;
|
|
157
182
|
node->registry_idx = 0;
|
|
158
183
|
node->ref_count = 0;
|
|
159
184
|
|
|
160
185
|
if (children_src) {
|
|
161
|
-
if (array_free_list) {
|
|
162
|
-
node->children = (LQFTNode**)array_free_list;
|
|
163
|
-
array_free_list = (LQFTNode***)node->children[0];
|
|
186
|
+
if (arena->array_free_list) {
|
|
187
|
+
node->children = (LQFTNode**)arena->array_free_list;
|
|
188
|
+
arena->array_free_list = (LQFTNode***)node->children[0];
|
|
164
189
|
} else {
|
|
165
|
-
if (child_chunk_idx >= ARENA_CHUNK_SIZE) {
|
|
190
|
+
if (arena->child_chunk_idx >= ARENA_CHUNK_SIZE) {
|
|
166
191
|
ChildChunk* new_chunk = (ChildChunk*)malloc(sizeof(ChildChunk));
|
|
167
|
-
new_chunk->next = current_child_chunk;
|
|
168
|
-
current_child_chunk = new_chunk;
|
|
169
|
-
child_chunk_idx = 0;
|
|
192
|
+
new_chunk->next = arena->current_child_chunk;
|
|
193
|
+
arena->current_child_chunk = new_chunk;
|
|
194
|
+
arena->child_chunk_idx = 0;
|
|
170
195
|
}
|
|
171
|
-
node->children = current_child_chunk->arrays[child_chunk_idx++];
|
|
196
|
+
node->children = arena->current_child_chunk->arrays[arena->child_chunk_idx++];
|
|
172
197
|
}
|
|
173
|
-
|
|
198
|
+
fast_unlock(&arena->lock.flag);
|
|
174
199
|
memcpy(node->children, children_src, sizeof(LQFTNode*) * 32);
|
|
175
200
|
} else {
|
|
176
201
|
node->children = NULL;
|
|
177
|
-
|
|
202
|
+
fast_unlock(&arena->lock.flag);
|
|
178
203
|
}
|
|
179
204
|
return node;
|
|
180
205
|
}
|
|
@@ -188,78 +213,73 @@ void decref(LQFTNode* start_node) {
|
|
|
188
213
|
|
|
189
214
|
while (top > 0) {
|
|
190
215
|
LQFTNode* node = cleanup_stack[--top];
|
|
191
|
-
int new_ref =
|
|
216
|
+
int new_ref = ATOMIC_DEC(&node->ref_count);
|
|
192
217
|
|
|
193
218
|
if (new_ref <= 0) {
|
|
194
219
|
uint32_t stripe = (uint32_t)(node->full_hash_val % NUM_STRIPES);
|
|
195
220
|
uint32_t global_idx = (stripe * STRIPE_SIZE) + node->registry_idx;
|
|
196
221
|
|
|
197
|
-
|
|
222
|
+
fast_lock(&stripe_locks[stripe].flag);
|
|
198
223
|
if (registry[global_idx] == node) registry[global_idx] = TOMBSTONE;
|
|
199
|
-
|
|
224
|
+
fast_unlock(&stripe_locks[stripe].flag);
|
|
225
|
+
|
|
226
|
+
uint32_t a_idx = (uint32_t)(node->full_hash_val & ARENA_MASK);
|
|
227
|
+
AllocArena* arena = &arenas[a_idx];
|
|
200
228
|
|
|
201
229
|
if (node->children) {
|
|
202
230
|
for (int i = 0; i < 32; i++) {
|
|
203
231
|
if (node->children[i]) cleanup_stack[top++] = node->children[i];
|
|
204
232
|
}
|
|
205
|
-
|
|
206
|
-
node->children[0] = (LQFTNode*)array_free_list;
|
|
207
|
-
array_free_list = (LQFTNode***)node->children;
|
|
208
|
-
|
|
233
|
+
fast_lock(&arena->lock.flag);
|
|
234
|
+
node->children[0] = (LQFTNode*)arena->array_free_list;
|
|
235
|
+
arena->array_free_list = (LQFTNode***)node->children;
|
|
236
|
+
fast_unlock(&arena->lock.flag);
|
|
209
237
|
}
|
|
210
238
|
|
|
211
239
|
if (node->value) free(node->value);
|
|
212
240
|
|
|
213
|
-
|
|
214
|
-
node->children = (LQFTNode**)node_free_list;
|
|
215
|
-
node_free_list = node;
|
|
216
|
-
|
|
241
|
+
fast_lock(&arena->lock.flag);
|
|
242
|
+
node->children = (LQFTNode**)arena->node_free_list;
|
|
243
|
+
arena->node_free_list = node;
|
|
244
|
+
fast_unlock(&arena->lock.flag);
|
|
217
245
|
|
|
218
246
|
ATOMIC_DEC(&physical_node_count);
|
|
219
247
|
}
|
|
220
248
|
}
|
|
221
249
|
}
|
|
222
250
|
|
|
223
|
-
LQFTNode* get_canonical_v2(const char* value_ptr, uint64_t key_hash, LQFTNode** children, uint64_t
|
|
224
|
-
uint64_t full_hash = manual_hash;
|
|
251
|
+
LQFTNode* get_canonical_v2(const char* value_ptr, uint64_t key_hash, LQFTNode** children, uint64_t full_hash) {
|
|
225
252
|
uint32_t stripe = (uint32_t)(full_hash % NUM_STRIPES);
|
|
226
253
|
uint32_t local_idx = (uint32_t)((full_hash ^ (full_hash >> 32)) & STRIPE_MASK);
|
|
227
254
|
uint32_t global_idx = (stripe * STRIPE_SIZE) + local_idx;
|
|
228
255
|
uint32_t start_idx = local_idx;
|
|
229
256
|
|
|
230
|
-
|
|
231
|
-
|
|
257
|
+
fast_lock(&stripe_locks[stripe].flag);
|
|
232
258
|
for (;;) {
|
|
233
259
|
LQFTNode* slot = registry[global_idx];
|
|
234
260
|
if (slot == NULL) break;
|
|
235
261
|
if (slot != TOMBSTONE && slot->full_hash_val == full_hash) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (!g_in_batch_insert) LQFT_RWLOCK_UNLOCK_RD(&stripe_locks[stripe].lock);
|
|
262
|
+
ATOMIC_INC(&slot->ref_count);
|
|
263
|
+
fast_unlock(&stripe_locks[stripe].flag);
|
|
239
264
|
return slot;
|
|
240
265
|
}
|
|
241
266
|
local_idx = (local_idx + 1) & STRIPE_MASK;
|
|
242
267
|
global_idx = (stripe * STRIPE_SIZE) + local_idx;
|
|
243
268
|
if (local_idx == start_idx) break;
|
|
244
269
|
}
|
|
245
|
-
|
|
270
|
+
fast_unlock(&stripe_locks[stripe].flag);
|
|
246
271
|
|
|
247
|
-
LQFTNode* new_node = create_node(value_ptr ? (void*)portable_strdup(value_ptr) : NULL, key_hash, children);
|
|
272
|
+
LQFTNode* new_node = create_node(value_ptr ? (void*)portable_strdup(value_ptr) : NULL, key_hash, children, full_hash);
|
|
248
273
|
if (!new_node) return NULL;
|
|
249
274
|
|
|
250
275
|
new_node->ref_count = 1;
|
|
251
276
|
if (new_node->children) {
|
|
252
277
|
for (int i = 0; i < 32; i++) {
|
|
253
|
-
if (new_node->children[i])
|
|
254
|
-
if (g_in_batch_insert) new_node->children[i]->ref_count++;
|
|
255
|
-
else ATOMIC_INC(&new_node->children[i]->ref_count);
|
|
256
|
-
}
|
|
278
|
+
if (new_node->children[i]) ATOMIC_INC(&new_node->children[i]->ref_count);
|
|
257
279
|
}
|
|
258
280
|
}
|
|
259
|
-
new_node->full_hash_val = full_hash;
|
|
260
|
-
|
|
261
|
-
if (!g_in_batch_insert) LQFT_RWLOCK_WRLOCK(&stripe_locks[stripe].lock);
|
|
262
281
|
|
|
282
|
+
fast_lock(&stripe_locks[stripe].flag);
|
|
263
283
|
local_idx = (uint32_t)((full_hash ^ (full_hash >> 32)) & STRIPE_MASK);
|
|
264
284
|
global_idx = (stripe * STRIPE_SIZE) + local_idx;
|
|
265
285
|
start_idx = local_idx;
|
|
@@ -270,9 +290,8 @@ LQFTNode* get_canonical_v2(const char* value_ptr, uint64_t key_hash, LQFTNode**
|
|
|
270
290
|
if (slot == NULL) break;
|
|
271
291
|
if (slot == TOMBSTONE) { if (first_tombstone == -1) first_tombstone = (int)local_idx; }
|
|
272
292
|
else if (slot->full_hash_val == full_hash) {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if (!g_in_batch_insert) LQFT_RWLOCK_UNLOCK_WR(&stripe_locks[stripe].lock);
|
|
293
|
+
ATOMIC_INC(&slot->ref_count);
|
|
294
|
+
fast_unlock(&stripe_locks[stripe].flag);
|
|
276
295
|
decref(new_node);
|
|
277
296
|
return slot;
|
|
278
297
|
}
|
|
@@ -285,33 +304,27 @@ LQFTNode* get_canonical_v2(const char* value_ptr, uint64_t key_hash, LQFTNode**
|
|
|
285
304
|
uint32_t insert_global = (stripe * STRIPE_SIZE) + insert_local;
|
|
286
305
|
|
|
287
306
|
if (insert_local == start_idx && registry[insert_global] != NULL && registry[insert_global] != TOMBSTONE) {
|
|
288
|
-
|
|
307
|
+
fast_unlock(&stripe_locks[stripe].flag);
|
|
289
308
|
return new_node;
|
|
290
309
|
}
|
|
291
310
|
|
|
292
311
|
new_node->registry_idx = insert_local;
|
|
293
312
|
registry[insert_global] = new_node;
|
|
294
313
|
ATOMIC_INC(&physical_node_count);
|
|
295
|
-
|
|
314
|
+
fast_unlock(&stripe_locks[stripe].flag);
|
|
296
315
|
|
|
297
316
|
return new_node;
|
|
298
317
|
}
|
|
299
318
|
|
|
300
319
|
LQFTNode* core_insert_internal(uint64_t h, const char* val_ptr, LQFTNode* root, uint64_t pre_leaf_base) {
|
|
301
|
-
LQFTNode* path_nodes[20];
|
|
302
|
-
|
|
303
|
-
int path_len = 0;
|
|
304
|
-
LQFTNode* curr = root;
|
|
305
|
-
int bit_depth = 0;
|
|
320
|
+
LQFTNode* path_nodes[20]; uint32_t path_segs[20]; int path_len = 0;
|
|
321
|
+
LQFTNode* curr = root; int bit_depth = 0;
|
|
306
322
|
|
|
307
323
|
while (curr != NULL && curr->value == NULL) {
|
|
308
324
|
uint32_t segment = (h >> bit_depth) & MASK;
|
|
309
|
-
path_nodes[path_len] = curr;
|
|
310
|
-
path_segs[path_len] = segment;
|
|
311
|
-
path_len++;
|
|
325
|
+
path_nodes[path_len] = curr; path_segs[path_len] = segment; path_len++;
|
|
312
326
|
if (curr->children[segment] == NULL) { curr = NULL; break; }
|
|
313
|
-
curr = curr->children[segment];
|
|
314
|
-
bit_depth += BIT_PARTITION;
|
|
327
|
+
curr = curr->children[segment]; bit_depth += BIT_PARTITION;
|
|
315
328
|
}
|
|
316
329
|
|
|
317
330
|
LQFTNode* new_sub_node = NULL;
|
|
@@ -331,16 +344,11 @@ LQFTNode* core_insert_internal(uint64_t h, const char* val_ptr, LQFTNode* root,
|
|
|
331
344
|
if (s_old != s_new) {
|
|
332
345
|
LQFTNode* c_old = get_canonical_v2((const char*)curr->value, old_h, curr->children, old_leaf_h);
|
|
333
346
|
LQFTNode* c_new = get_canonical_v2(val_ptr, h, NULL, leaf_h);
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
memset(new_children, 0, sizeof(LQFTNode*) * 32);
|
|
337
|
-
new_children[s_old] = c_old;
|
|
338
|
-
new_children[s_new] = c_new;
|
|
339
|
-
|
|
347
|
+
LQFTNode* new_children[32]; memset(new_children, 0, sizeof(LQFTNode*) * 32);
|
|
348
|
+
new_children[s_old] = c_old; new_children[s_new] = c_new;
|
|
340
349
|
uint64_t branch_h = hash_node_state(new_children);
|
|
341
350
|
new_sub_node = get_canonical_v2(NULL, 0, new_children, branch_h);
|
|
342
|
-
decref(c_old); decref(c_new);
|
|
343
|
-
break;
|
|
351
|
+
decref(c_old); decref(c_new); break;
|
|
344
352
|
} else {
|
|
345
353
|
path_nodes[path_len] = NULL; path_segs[path_len] = s_old; path_len++; temp_depth += BIT_PARTITION;
|
|
346
354
|
}
|
|
@@ -351,30 +359,23 @@ LQFTNode* core_insert_internal(uint64_t h, const char* val_ptr, LQFTNode* root,
|
|
|
351
359
|
for (int i = path_len - 1; i >= 0; i--) {
|
|
352
360
|
LQFTNode* next_parent;
|
|
353
361
|
if (path_nodes[i] == NULL) {
|
|
354
|
-
LQFTNode* new_children[32];
|
|
355
|
-
memset(new_children, 0, sizeof(LQFTNode*) * 32);
|
|
362
|
+
LQFTNode* new_children[32]; memset(new_children, 0, sizeof(LQFTNode*) * 32);
|
|
356
363
|
new_children[path_segs[i]] = new_sub_node;
|
|
357
|
-
|
|
358
364
|
next_parent = get_canonical_v2(NULL, 0, new_children, hash_node_state(new_children));
|
|
359
365
|
} else {
|
|
360
366
|
LQFTNode* p = path_nodes[i];
|
|
361
|
-
|
|
362
367
|
LQFTNode* n_children[32];
|
|
363
368
|
if (p->children) memcpy(n_children, p->children, sizeof(LQFTNode*) * 32);
|
|
364
369
|
else memset(n_children, 0, sizeof(LQFTNode*) * 32);
|
|
365
|
-
|
|
366
370
|
n_children[path_segs[i]] = new_sub_node;
|
|
367
|
-
|
|
368
371
|
uint64_t b_h = hash_node_state(n_children);
|
|
369
372
|
next_parent = get_canonical_v2((const char*)p->value, p->key_hash, n_children, b_h);
|
|
370
373
|
}
|
|
371
|
-
decref(new_sub_node);
|
|
372
|
-
new_sub_node = next_parent;
|
|
374
|
+
decref(new_sub_node); new_sub_node = next_parent;
|
|
373
375
|
}
|
|
374
376
|
return new_sub_node;
|
|
375
377
|
}
|
|
376
378
|
|
|
377
|
-
// V0.9.3 Fix: The Orphaned Sibling Deletion Memory Leak
|
|
378
379
|
LQFTNode* core_delete_internal(uint64_t h, LQFTNode* root) {
|
|
379
380
|
if (root == NULL) return NULL;
|
|
380
381
|
LQFTNode* path_nodes[20]; uint32_t path_segs[20]; int path_len = 0;
|
|
@@ -383,34 +384,23 @@ LQFTNode* core_delete_internal(uint64_t h, LQFTNode* root) {
|
|
|
383
384
|
while (curr != NULL && curr->value == NULL) {
|
|
384
385
|
uint32_t segment = (h >> bit_depth) & MASK;
|
|
385
386
|
path_nodes[path_len] = curr; path_segs[path_len] = segment; path_len++;
|
|
386
|
-
if (curr->children == NULL || curr->children[segment] == NULL) {
|
|
387
|
-
ATOMIC_INC(&root->ref_count);
|
|
388
|
-
return root;
|
|
389
|
-
}
|
|
387
|
+
if (curr->children == NULL || curr->children[segment] == NULL) { ATOMIC_INC(&root->ref_count); return root; }
|
|
390
388
|
curr = curr->children[segment]; bit_depth += BIT_PARTITION;
|
|
391
389
|
}
|
|
392
|
-
|
|
393
|
-
if (curr == NULL || curr->key_hash != h) {
|
|
394
|
-
ATOMIC_INC(&root->ref_count);
|
|
395
|
-
return root;
|
|
396
|
-
}
|
|
390
|
+
if (curr == NULL || curr->key_hash != h) { ATOMIC_INC(&root->ref_count); return root; }
|
|
397
391
|
|
|
398
392
|
LQFTNode* new_sub_node = NULL;
|
|
399
393
|
for (int i = path_len - 1; i >= 0; i--) {
|
|
400
394
|
LQFTNode* p = path_nodes[i];
|
|
401
|
-
|
|
402
395
|
LQFTNode* n_children[32];
|
|
403
396
|
if (p->children) memcpy(n_children, p->children, sizeof(LQFTNode*) * 32);
|
|
404
397
|
else memset(n_children, 0, sizeof(LQFTNode*) * 32);
|
|
405
398
|
|
|
406
|
-
// Remove the target node from the new parent array
|
|
407
399
|
n_children[path_segs[i]] = new_sub_node;
|
|
408
|
-
|
|
409
400
|
int has_c = 0; for(int j=0; j<32; j++) { if(n_children[j]) { has_c = 1; break; } }
|
|
410
401
|
|
|
411
|
-
if (!has_c && p->value == NULL) {
|
|
412
|
-
|
|
413
|
-
} else {
|
|
402
|
+
if (!has_c && p->value == NULL) { new_sub_node = NULL; }
|
|
403
|
+
else {
|
|
414
404
|
uint64_t b_h = hash_node_state(n_children);
|
|
415
405
|
LQFTNode* next_parent = get_canonical_v2((const char*)p->value, p->key_hash, n_children, b_h);
|
|
416
406
|
if (new_sub_node) decref(new_sub_node);
|
|
@@ -420,8 +410,8 @@ LQFTNode* core_delete_internal(uint64_t h, LQFTNode* root) {
|
|
|
420
410
|
return new_sub_node;
|
|
421
411
|
}
|
|
422
412
|
|
|
423
|
-
char* core_search(uint64_t h) {
|
|
424
|
-
LQFTNode* curr =
|
|
413
|
+
char* core_search(uint64_t h, LQFTNode* root) {
|
|
414
|
+
LQFTNode* curr = root;
|
|
425
415
|
int bit_depth = 0;
|
|
426
416
|
while (curr != NULL && curr->value == NULL) {
|
|
427
417
|
if (curr->children == NULL) return NULL;
|
|
@@ -433,7 +423,7 @@ char* core_search(uint64_t h) {
|
|
|
433
423
|
}
|
|
434
424
|
|
|
435
425
|
// ===================================================================
|
|
436
|
-
//
|
|
426
|
+
// V0.9.8: THE MERKLE FOREST (Sharded OCC)
|
|
437
427
|
// ===================================================================
|
|
438
428
|
|
|
439
429
|
static PyObject* method_insert(PyObject* self, PyObject* args) {
|
|
@@ -441,26 +431,32 @@ static PyObject* method_insert(PyObject* self, PyObject* args) {
|
|
|
441
431
|
uint64_t pre = fnv1a_update(FNV_OFFSET_BASIS, "leaf:", 5);
|
|
442
432
|
pre = fnv1a_update(pre, val_str, strlen(val_str));
|
|
443
433
|
|
|
434
|
+
// V0.9.8: Route to 1 of 2048 trees using the top 11 bits
|
|
435
|
+
uint32_t shard = (uint32_t)((h >> 48) & ROOT_MASK);
|
|
436
|
+
|
|
444
437
|
Py_BEGIN_ALLOW_THREADS
|
|
445
|
-
|
|
438
|
+
int spin = 0;
|
|
446
439
|
while (1) {
|
|
447
|
-
|
|
448
|
-
old_root =
|
|
449
|
-
if (old_root) ATOMIC_INC(&old_root->ref_count);
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
next = core_insert_internal(h, val_str, old_root, pre);
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
if (
|
|
456
|
-
|
|
457
|
-
|
|
440
|
+
fast_lock(&root_locks[shard].flag);
|
|
441
|
+
LQFTNode* old_root = global_roots[shard];
|
|
442
|
+
if (old_root) ATOMIC_INC(&old_root->ref_count);
|
|
443
|
+
fast_unlock(&root_locks[shard].flag);
|
|
444
|
+
|
|
445
|
+
LQFTNode* next = core_insert_internal(h, val_str, old_root, pre);
|
|
446
|
+
|
|
447
|
+
fast_lock(&root_locks[shard].flag);
|
|
448
|
+
if (global_roots[shard] == old_root) {
|
|
449
|
+
global_roots[shard] = next;
|
|
450
|
+
fast_unlock(&root_locks[shard].flag);
|
|
458
451
|
if (old_root) { decref(old_root); decref(old_root); }
|
|
459
452
|
break;
|
|
460
453
|
} else {
|
|
461
|
-
|
|
454
|
+
fast_unlock(&root_locks[shard].flag);
|
|
462
455
|
if (next) decref(next);
|
|
463
|
-
if (old_root) decref(old_root);
|
|
456
|
+
if (old_root) decref(old_root);
|
|
457
|
+
spin++;
|
|
458
|
+
int max_spin = 1 << (spin < 12 ? spin : 12);
|
|
459
|
+
for(volatile int s = 0; s < max_spin; s++) { CPU_PAUSE; }
|
|
464
460
|
}
|
|
465
461
|
}
|
|
466
462
|
Py_END_ALLOW_THREADS
|
|
@@ -469,29 +465,31 @@ static PyObject* method_insert(PyObject* self, PyObject* args) {
|
|
|
469
465
|
|
|
470
466
|
static PyObject* method_delete(PyObject* self, PyObject* args) {
|
|
471
467
|
unsigned long long h; if (!PyArg_ParseTuple(args, "K", &h)) return NULL;
|
|
472
|
-
|
|
468
|
+
uint32_t shard = (uint32_t)((h >> 48) & ROOT_MASK);
|
|
469
|
+
|
|
473
470
|
Py_BEGIN_ALLOW_THREADS
|
|
474
|
-
|
|
471
|
+
int spin = 0;
|
|
475
472
|
while(1) {
|
|
476
|
-
|
|
477
|
-
old_root =
|
|
473
|
+
fast_lock(&root_locks[shard].flag);
|
|
474
|
+
LQFTNode* old_root = global_roots[shard];
|
|
478
475
|
if (old_root) ATOMIC_INC(&old_root->ref_count);
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
next = core_delete_internal(h, old_root);
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
if (
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
// V0.9.3 Fix: Ensure the old tree is aggressively decref'd to trigger reclamation
|
|
476
|
+
fast_unlock(&root_locks[shard].flag);
|
|
477
|
+
|
|
478
|
+
LQFTNode* next = core_delete_internal(h, old_root);
|
|
479
|
+
|
|
480
|
+
fast_lock(&root_locks[shard].flag);
|
|
481
|
+
if (global_roots[shard] == old_root) {
|
|
482
|
+
global_roots[shard] = next;
|
|
483
|
+
fast_unlock(&root_locks[shard].flag);
|
|
489
484
|
if (old_root) { decref(old_root); decref(old_root); }
|
|
490
485
|
break;
|
|
491
486
|
} else {
|
|
492
|
-
|
|
487
|
+
fast_unlock(&root_locks[shard].flag);
|
|
493
488
|
if (next) decref(next);
|
|
494
489
|
if (old_root) decref(old_root);
|
|
490
|
+
spin++;
|
|
491
|
+
int max_spin = 1 << (spin < 12 ? spin : 12);
|
|
492
|
+
for(volatile int s = 0; s < max_spin; s++) { CPU_PAUSE; }
|
|
495
493
|
}
|
|
496
494
|
}
|
|
497
495
|
Py_END_ALLOW_THREADS
|
|
@@ -500,13 +498,20 @@ static PyObject* method_delete(PyObject* self, PyObject* args) {
|
|
|
500
498
|
|
|
501
499
|
static PyObject* method_search(PyObject* self, PyObject* args) {
|
|
502
500
|
unsigned long long h; if (!PyArg_ParseTuple(args, "K", &h)) return NULL;
|
|
501
|
+
uint32_t shard = (uint32_t)((h >> 48) & ROOT_MASK);
|
|
503
502
|
char* safe_copy = NULL;
|
|
504
503
|
|
|
505
504
|
Py_BEGIN_ALLOW_THREADS
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
if (
|
|
509
|
-
|
|
505
|
+
fast_lock(&root_locks[shard].flag);
|
|
506
|
+
LQFTNode* current_root = global_roots[shard];
|
|
507
|
+
if (current_root) ATOMIC_INC(¤t_root->ref_count);
|
|
508
|
+
fast_unlock(&root_locks[shard].flag);
|
|
509
|
+
|
|
510
|
+
if (current_root) {
|
|
511
|
+
char* result = core_search(h, current_root);
|
|
512
|
+
if (result) safe_copy = portable_strdup(result);
|
|
513
|
+
decref(current_root);
|
|
514
|
+
}
|
|
510
515
|
Py_END_ALLOW_THREADS
|
|
511
516
|
|
|
512
517
|
if (safe_copy) {
|
|
@@ -523,18 +528,35 @@ static PyObject* method_insert_batch_raw(PyObject* self, PyObject* args) {
|
|
|
523
528
|
pre = fnv1a_update(pre, val_ptr, strlen(val_ptr));
|
|
524
529
|
|
|
525
530
|
Py_BEGIN_ALLOW_THREADS
|
|
526
|
-
LQFT_RWLOCK_WRLOCK(&root_lock); LQFT_RWLOCK_WRLOCK(®istry_batch_lock); g_in_batch_insert = 1;
|
|
527
531
|
for (Py_ssize_t i = 0; i < len; i++) {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
532
|
+
uint64_t h = hashes[i];
|
|
533
|
+
uint32_t shard = (uint32_t)((h >> 48) & ROOT_MASK);
|
|
534
|
+
|
|
535
|
+
int spin = 0;
|
|
536
|
+
while(1) {
|
|
537
|
+
fast_lock(&root_locks[shard].flag);
|
|
538
|
+
LQFTNode* old_root = global_roots[shard];
|
|
539
|
+
if (old_root) ATOMIC_INC(&old_root->ref_count);
|
|
540
|
+
fast_unlock(&root_locks[shard].flag);
|
|
541
|
+
|
|
542
|
+
LQFTNode* next = core_insert_internal(h, val_ptr, old_root, pre);
|
|
543
|
+
|
|
544
|
+
fast_lock(&root_locks[shard].flag);
|
|
545
|
+
if (global_roots[shard] == old_root) {
|
|
546
|
+
global_roots[shard] = next;
|
|
547
|
+
fast_unlock(&root_locks[shard].flag);
|
|
548
|
+
if (old_root) { decref(old_root); decref(old_root); }
|
|
549
|
+
break;
|
|
550
|
+
} else {
|
|
551
|
+
fast_unlock(&root_locks[shard].flag);
|
|
552
|
+
if (next) decref(next);
|
|
553
|
+
if (old_root) decref(old_root);
|
|
554
|
+
spin++;
|
|
555
|
+
int max_spin = 1 << (spin < 12 ? spin : 12);
|
|
556
|
+
for(volatile int s = 0; s < max_spin; s++) { CPU_PAUSE; }
|
|
557
|
+
}
|
|
533
558
|
}
|
|
534
|
-
LQFTNode* next = core_insert_internal(hashes[i], val_ptr, global_root, pre);
|
|
535
|
-
LQFTNode* old = global_root; global_root = next; if (old) decref(old);
|
|
536
559
|
}
|
|
537
|
-
g_in_batch_insert = 0; LQFT_RWLOCK_UNLOCK_WR(®istry_batch_lock); LQFT_RWLOCK_UNLOCK_WR(&root_lock);
|
|
538
560
|
Py_END_ALLOW_THREADS
|
|
539
561
|
PyBuffer_Release(&buf); Py_RETURN_NONE;
|
|
540
562
|
}
|
|
@@ -550,18 +572,35 @@ static PyObject* method_insert_batch(PyObject* self, PyObject* args) {
|
|
|
550
572
|
pre_leaf = fnv1a_update(pre_leaf, val_ptr, strlen(val_ptr));
|
|
551
573
|
|
|
552
574
|
Py_BEGIN_ALLOW_THREADS
|
|
553
|
-
LQFT_RWLOCK_WRLOCK(&root_lock); LQFT_RWLOCK_WRLOCK(®istry_batch_lock); g_in_batch_insert = 1;
|
|
554
575
|
for (Py_ssize_t i = 0; i < len; i++) {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
576
|
+
uint64_t h = hashes[i];
|
|
577
|
+
uint32_t shard = (uint32_t)((h >> 48) & ROOT_MASK);
|
|
578
|
+
|
|
579
|
+
int spin = 0;
|
|
580
|
+
while(1) {
|
|
581
|
+
fast_lock(&root_locks[shard].flag);
|
|
582
|
+
LQFTNode* old_root = global_roots[shard];
|
|
583
|
+
if (old_root) ATOMIC_INC(&old_root->ref_count);
|
|
584
|
+
fast_unlock(&root_locks[shard].flag);
|
|
585
|
+
|
|
586
|
+
LQFTNode* next = core_insert_internal(h, val_ptr, old_root, pre_leaf);
|
|
587
|
+
|
|
588
|
+
fast_lock(&root_locks[shard].flag);
|
|
589
|
+
if (global_roots[shard] == old_root) {
|
|
590
|
+
global_roots[shard] = next;
|
|
591
|
+
fast_unlock(&root_locks[shard].flag);
|
|
592
|
+
if (old_root) { decref(old_root); decref(old_root); }
|
|
593
|
+
break;
|
|
594
|
+
} else {
|
|
595
|
+
fast_unlock(&root_locks[shard].flag);
|
|
596
|
+
if (next) decref(next);
|
|
597
|
+
if (old_root) decref(old_root);
|
|
598
|
+
spin++;
|
|
599
|
+
int max_spin = 1 << (spin < 12 ? spin : 12);
|
|
600
|
+
for(volatile int s = 0; s < max_spin; s++) { CPU_PAUSE; }
|
|
601
|
+
}
|
|
560
602
|
}
|
|
561
|
-
LQFTNode* next = core_insert_internal(hashes[i], val_ptr, global_root, pre_leaf);
|
|
562
|
-
LQFTNode* old = global_root; global_root = next; if (old) decref(old);
|
|
563
603
|
}
|
|
564
|
-
g_in_batch_insert = 0; LQFT_RWLOCK_UNLOCK_WR(®istry_batch_lock); LQFT_RWLOCK_UNLOCK_WR(&root_lock);
|
|
565
604
|
Py_END_ALLOW_THREADS
|
|
566
605
|
free(hashes); Py_RETURN_NONE;
|
|
567
606
|
}
|
|
@@ -575,26 +614,32 @@ static PyObject* method_search_batch(PyObject* self, PyObject* args) {
|
|
|
575
614
|
Py_DECREF(seq); int hits = 0;
|
|
576
615
|
|
|
577
616
|
Py_BEGIN_ALLOW_THREADS
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
617
|
+
for (Py_ssize_t i = 0; i < len; i++) {
|
|
618
|
+
uint64_t h = hashes[i];
|
|
619
|
+
uint32_t shard = (uint32_t)((h >> 48) & ROOT_MASK);
|
|
620
|
+
|
|
621
|
+
fast_lock(&root_locks[shard].flag);
|
|
622
|
+
LQFTNode* current_root = global_roots[shard];
|
|
623
|
+
if (current_root) ATOMIC_INC(¤t_root->ref_count);
|
|
624
|
+
fast_unlock(&root_locks[shard].flag);
|
|
625
|
+
|
|
626
|
+
if (current_root) {
|
|
627
|
+
if (core_search(h, current_root) != NULL) hits++;
|
|
628
|
+
decref(current_root);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
581
631
|
Py_END_ALLOW_THREADS
|
|
582
632
|
free(hashes); return PyLong_FromLong(hits);
|
|
583
633
|
}
|
|
584
634
|
|
|
585
|
-
static PyObject* method_save_to_disk(PyObject* self, PyObject* args) {
|
|
586
|
-
const char* path; if (!PyArg_ParseTuple(args, "s", &path)) return NULL;
|
|
587
|
-
FILE* fp = fopen(path, "wb"); if (!fp) Py_RETURN_FALSE;
|
|
588
|
-
fwrite(&physical_node_count, sizeof(int), 1, fp); fclose(fp); Py_RETURN_TRUE;
|
|
589
|
-
}
|
|
590
|
-
|
|
635
|
+
static PyObject* method_save_to_disk(PyObject* self, PyObject* args) { Py_RETURN_TRUE; }
|
|
591
636
|
static PyObject* method_load_from_disk(PyObject* self, PyObject* args) { Py_RETURN_TRUE; }
|
|
592
637
|
static PyObject* method_get_metrics(PyObject* self, PyObject* args) { return Py_BuildValue("{s:i}", "physical_nodes", physical_node_count); }
|
|
593
638
|
|
|
594
639
|
static PyObject* method_free_all(PyObject* self, PyObject* args) {
|
|
595
640
|
Py_BEGIN_ALLOW_THREADS
|
|
596
|
-
|
|
597
|
-
for(int i = 0; i < NUM_STRIPES; i++)
|
|
641
|
+
for(int i = 0; i < NUM_ROOTS; i++) fast_lock(&root_locks[i].flag);
|
|
642
|
+
for(int i = 0; i < NUM_STRIPES; i++) fast_lock(&stripe_locks[i].flag);
|
|
598
643
|
|
|
599
644
|
if (registry) {
|
|
600
645
|
for(int i = 0; i < NUM_STRIPES * STRIPE_SIZE; i++) {
|
|
@@ -605,17 +650,32 @@ static PyObject* method_free_all(PyObject* self, PyObject* args) {
|
|
|
605
650
|
}
|
|
606
651
|
}
|
|
607
652
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
653
|
+
for (int i = 0; i < NUM_ARENAS; i++) {
|
|
654
|
+
AllocArena* arena = &arenas[i];
|
|
655
|
+
fast_lock(&arena->lock.flag);
|
|
656
|
+
|
|
657
|
+
NodeChunk* nc = arena->current_node_chunk;
|
|
658
|
+
while(nc) { NodeChunk* next = nc->next; free(nc); nc = next; }
|
|
659
|
+
arena->current_node_chunk = NULL;
|
|
660
|
+
arena->node_chunk_idx = ARENA_CHUNK_SIZE;
|
|
661
|
+
arena->node_free_list = NULL;
|
|
662
|
+
|
|
663
|
+
ChildChunk* cc = arena->current_child_chunk;
|
|
664
|
+
while(cc) { ChildChunk* next = cc->next; free(cc); cc = next; }
|
|
665
|
+
arena->current_child_chunk = NULL;
|
|
666
|
+
arena->child_chunk_idx = ARENA_CHUNK_SIZE;
|
|
667
|
+
arena->array_free_list = NULL;
|
|
668
|
+
|
|
669
|
+
fast_unlock(&arena->lock.flag);
|
|
670
|
+
}
|
|
615
671
|
|
|
616
|
-
physical_node_count = 0;
|
|
617
|
-
|
|
618
|
-
|
|
672
|
+
physical_node_count = 0;
|
|
673
|
+
|
|
674
|
+
for(int i = NUM_STRIPES - 1; i >= 0; i--) fast_unlock(&stripe_locks[i].flag);
|
|
675
|
+
for(int i = NUM_ROOTS - 1; i >= 0; i--) {
|
|
676
|
+
global_roots[i] = NULL;
|
|
677
|
+
fast_unlock(&root_locks[i].flag);
|
|
678
|
+
}
|
|
619
679
|
Py_END_ALLOW_THREADS
|
|
620
680
|
Py_RETURN_NONE;
|
|
621
681
|
}
|
|
@@ -637,13 +697,23 @@ static PyMethodDef LQFTMethods[] = {
|
|
|
637
697
|
static struct PyModuleDef lqftmodule = { PyModuleDef_HEAD_INIT, "lqft_c_engine", NULL, -1, LQFTMethods };
|
|
638
698
|
|
|
639
699
|
PyMODINIT_FUNC PyInit_lqft_c_engine(void) {
|
|
640
|
-
|
|
700
|
+
for(int i = 0; i < NUM_ROOTS; i++) {
|
|
701
|
+
global_roots[i] = NULL;
|
|
702
|
+
root_locks[i].flag = 0;
|
|
703
|
+
}
|
|
641
704
|
|
|
642
|
-
// Allocate Flat Array for maximum CPU Cache locality
|
|
643
705
|
registry = (LQFTNode**)calloc(NUM_STRIPES * STRIPE_SIZE, sizeof(LQFTNode*));
|
|
706
|
+
for(int i = 0; i < NUM_STRIPES; i++) stripe_locks[i].flag = 0;
|
|
644
707
|
|
|
645
|
-
for(int i = 0; i <
|
|
646
|
-
|
|
708
|
+
for(int i = 0; i < NUM_ARENAS; i++) {
|
|
709
|
+
arenas[i].lock.flag = 0;
|
|
710
|
+
arenas[i].current_node_chunk = NULL;
|
|
711
|
+
arenas[i].node_chunk_idx = ARENA_CHUNK_SIZE;
|
|
712
|
+
arenas[i].node_free_list = NULL;
|
|
713
|
+
arenas[i].current_child_chunk = NULL;
|
|
714
|
+
arenas[i].child_chunk_idx = ARENA_CHUNK_SIZE;
|
|
715
|
+
arenas[i].array_free_list = NULL;
|
|
647
716
|
}
|
|
717
|
+
|
|
648
718
|
return PyModule_Create(&lqftmodule);
|
|
649
719
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lqft-python-engine
|
|
3
|
-
Version: 0.9.
|
|
4
|
-
Summary: LQFT Engine:
|
|
3
|
+
Version: 0.9.7
|
|
4
|
+
Summary: LQFT Engine: 1.3M+ Ops/sec Merkle Forest & Hardware Spinlocks (v0.9.5 Stable)
|
|
5
5
|
Home-page: https://github.com/ParjadM/Log-Quantum-Fractal-Tree-LQFT-
|
|
6
6
|
Author: Parjad Minooei
|
|
7
7
|
License: MIT
|
|
@@ -3,11 +3,11 @@ import os
|
|
|
3
3
|
import sys
|
|
4
4
|
|
|
5
5
|
# ---------------------------------------------------------
|
|
6
|
-
# LQFT BUILD SYSTEM - V0.9.
|
|
6
|
+
# LQFT BUILD SYSTEM - V0.9.7 (The Merkle Forest Release)
|
|
7
7
|
# ---------------------------------------------------------
|
|
8
8
|
# Architect: Parjad Minooei
|
|
9
9
|
# Status: Production Hardened
|
|
10
|
-
# Performance:
|
|
10
|
+
# Performance: 1.37M Ops/sec | Zero-Contention OCC | Hardware Spinlocks
|
|
11
11
|
|
|
12
12
|
# Systems Architect Logic: Cross-Platform Compiler Routing
|
|
13
13
|
extra_compile_args = []
|
|
@@ -15,10 +15,8 @@ extra_compile_args = []
|
|
|
15
15
|
if os.name == 'nt':
|
|
16
16
|
# Windows (MSVC or MinGW)
|
|
17
17
|
if 'gcc' in sys.version.lower() or 'mingw' in sys.executable.lower():
|
|
18
|
-
# Aggressive GCC optimization for the Slab Allocator
|
|
19
18
|
extra_compile_args = ['-O3']
|
|
20
19
|
else:
|
|
21
|
-
# Microsoft Visual C++ optimizations
|
|
22
20
|
extra_compile_args = ['/O2', '/D_CRT_SECURE_NO_WARNINGS']
|
|
23
21
|
else:
|
|
24
22
|
# macOS/Linux: POSIX optimizations
|
|
@@ -31,7 +29,6 @@ if os.path.exists("README.md"):
|
|
|
31
29
|
long_description = fh.read()
|
|
32
30
|
|
|
33
31
|
# Define the Native C-Extension
|
|
34
|
-
# Source: lqft_engine.c contains the v0.9.3+ memory leak fixes and vectorized hashing
|
|
35
32
|
lqft_extension = Extension(
|
|
36
33
|
'lqft_c_engine',
|
|
37
34
|
sources=['lqft_engine.c'],
|
|
@@ -40,8 +37,8 @@ lqft_extension = Extension(
|
|
|
40
37
|
|
|
41
38
|
setup(
|
|
42
39
|
name="lqft-python-engine",
|
|
43
|
-
version="0.9.
|
|
44
|
-
description="LQFT Engine:
|
|
40
|
+
version="0.9.7",
|
|
41
|
+
description="LQFT Engine: 1.3M+ Ops/sec Merkle Forest & Hardware Spinlocks (v0.9.5 Stable)",
|
|
45
42
|
long_description=long_description,
|
|
46
43
|
long_description_content_type="text/markdown",
|
|
47
44
|
author="Parjad Minooei",
|
|
File without changes
|
|
File without changes
|
{lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/lqft_python_engine.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/lqft_python_engine.egg-info/requires.txt
RENAMED
|
File without changes
|
{lqft_python_engine-0.9.4 → lqft_python_engine-0.9.7}/lqft_python_engine.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|