zexus 1.6.2
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.
- package/LICENSE +0 -0
- package/README.md +2513 -0
- package/bin/zexus +2 -0
- package/bin/zpics +2 -0
- package/bin/zpm +2 -0
- package/bin/zx +2 -0
- package/bin/zx-deploy +2 -0
- package/bin/zx-dev +2 -0
- package/bin/zx-run +2 -0
- package/package.json +66 -0
- package/scripts/README.md +24 -0
- package/scripts/postinstall.js +44 -0
- package/shared_config.json +24 -0
- package/src/README.md +1525 -0
- package/src/tests/run_zexus_tests.py +117 -0
- package/src/tests/test_all_phases.zx +346 -0
- package/src/tests/test_blockchain_features.zx +306 -0
- package/src/tests/test_complexity_features.zx +321 -0
- package/src/tests/test_core_integration.py +185 -0
- package/src/tests/test_phase10_ecosystem.zx +177 -0
- package/src/tests/test_phase1_modifiers.zx +87 -0
- package/src/tests/test_phase2_plugins.zx +80 -0
- package/src/tests/test_phase3_security.zx +97 -0
- package/src/tests/test_phase4_vfs.zx +116 -0
- package/src/tests/test_phase5_types.zx +117 -0
- package/src/tests/test_phase6_metaprogramming.zx +125 -0
- package/src/tests/test_phase7_optimization.zx +132 -0
- package/src/tests/test_phase9_advanced_types.zx +157 -0
- package/src/tests/test_security_features.py +419 -0
- package/src/tests/test_security_features.zx +276 -0
- package/src/tests/test_simple_zx.zx +1 -0
- package/src/tests/test_verification_simple.zx +69 -0
- package/src/zexus/__init__.py +28 -0
- package/src/zexus/__main__.py +5 -0
- package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/advanced_types.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/builtin_modules.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/complexity_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/concurrency_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/config.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/dependency_injection.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/ecosystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/hybrid_orchestrator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/metaprogramming.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/optimization.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/plugin_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/policy_engine.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/stdlib_integration.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/strategy_recovery.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/type_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/virtual_filesystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
- package/src/zexus/advanced_types.py +401 -0
- package/src/zexus/blockchain/__init__.py +40 -0
- package/src/zexus/blockchain/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/crypto.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/ledger.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/transaction.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/crypto.py +463 -0
- package/src/zexus/blockchain/ledger.py +255 -0
- package/src/zexus/blockchain/transaction.py +267 -0
- package/src/zexus/builtin_modules.py +284 -0
- package/src/zexus/builtin_plugins.py +317 -0
- package/src/zexus/capability_system.py +372 -0
- package/src/zexus/cli/__init__.py +2 -0
- package/src/zexus/cli/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
- package/src/zexus/cli/main.py +707 -0
- package/src/zexus/cli/zpm.py +203 -0
- package/src/zexus/compare_interpreter_compiler.py +146 -0
- package/src/zexus/compiler/__init__.py +169 -0
- package/src/zexus/compiler/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/compiler/bytecode.py +266 -0
- package/src/zexus/compiler/compat_runtime.py +277 -0
- package/src/zexus/compiler/lexer.py +257 -0
- package/src/zexus/compiler/parser.py +779 -0
- package/src/zexus/compiler/semantic.py +118 -0
- package/src/zexus/compiler/zexus_ast.py +454 -0
- package/src/zexus/complexity_system.py +575 -0
- package/src/zexus/concurrency_system.py +493 -0
- package/src/zexus/config.py +201 -0
- package/src/zexus/crypto_bridge.py +19 -0
- package/src/zexus/dependency_injection.py +423 -0
- package/src/zexus/ecosystem.py +434 -0
- package/src/zexus/environment.py +101 -0
- package/src/zexus/environment_manager.py +119 -0
- package/src/zexus/error_reporter.py +314 -0
- package/src/zexus/evaluator/__init__.py +12 -0
- package/src/zexus/evaluator/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/integration.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/bytecode_compiler.py +700 -0
- package/src/zexus/evaluator/core.py +891 -0
- package/src/zexus/evaluator/expressions.py +827 -0
- package/src/zexus/evaluator/functions.py +3989 -0
- package/src/zexus/evaluator/integration.py +396 -0
- package/src/zexus/evaluator/statements.py +4303 -0
- package/src/zexus/evaluator/utils.py +126 -0
- package/src/zexus/evaluator_original.py +2041 -0
- package/src/zexus/external_bridge.py +16 -0
- package/src/zexus/find_affected_imports.sh +155 -0
- package/src/zexus/hybrid_orchestrator.py +152 -0
- package/src/zexus/input_validation.py +259 -0
- package/src/zexus/lexer.py +571 -0
- package/src/zexus/logging.py +89 -0
- package/src/zexus/lsp/__init__.py +9 -0
- package/src/zexus/lsp/completion_provider.py +207 -0
- package/src/zexus/lsp/definition_provider.py +22 -0
- package/src/zexus/lsp/hover_provider.py +71 -0
- package/src/zexus/lsp/server.py +269 -0
- package/src/zexus/lsp/symbol_provider.py +31 -0
- package/src/zexus/metaprogramming.py +321 -0
- package/src/zexus/module_cache.py +89 -0
- package/src/zexus/module_manager.py +107 -0
- package/src/zexus/object.py +973 -0
- package/src/zexus/optimization.py +424 -0
- package/src/zexus/parser/__init__.py +31 -0
- package/src/zexus/parser/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
- package/src/zexus/parser/integration.py +86 -0
- package/src/zexus/parser/parser.py +3977 -0
- package/src/zexus/parser/strategy_context.py +7254 -0
- package/src/zexus/parser/strategy_structural.py +1033 -0
- package/src/zexus/persistence.py +391 -0
- package/src/zexus/plugin_system.py +290 -0
- package/src/zexus/policy_engine.py +365 -0
- package/src/zexus/profiler/__init__.py +5 -0
- package/src/zexus/profiler/profiler.py +233 -0
- package/src/zexus/purity_system.py +398 -0
- package/src/zexus/runtime/__init__.py +20 -0
- package/src/zexus/runtime/async_runtime.py +324 -0
- package/src/zexus/search_old_imports.sh +65 -0
- package/src/zexus/security.py +1407 -0
- package/src/zexus/stack_trace.py +233 -0
- package/src/zexus/stdlib/__init__.py +27 -0
- package/src/zexus/stdlib/blockchain.py +341 -0
- package/src/zexus/stdlib/compression.py +167 -0
- package/src/zexus/stdlib/crypto.py +124 -0
- package/src/zexus/stdlib/datetime.py +163 -0
- package/src/zexus/stdlib/db_mongo.py +199 -0
- package/src/zexus/stdlib/db_mysql.py +162 -0
- package/src/zexus/stdlib/db_postgres.py +163 -0
- package/src/zexus/stdlib/db_sqlite.py +133 -0
- package/src/zexus/stdlib/encoding.py +230 -0
- package/src/zexus/stdlib/fs.py +195 -0
- package/src/zexus/stdlib/http.py +219 -0
- package/src/zexus/stdlib/http_server.py +248 -0
- package/src/zexus/stdlib/json_module.py +61 -0
- package/src/zexus/stdlib/math.py +360 -0
- package/src/zexus/stdlib/os_module.py +265 -0
- package/src/zexus/stdlib/regex.py +148 -0
- package/src/zexus/stdlib/sockets.py +253 -0
- package/src/zexus/stdlib/test_framework.zx +208 -0
- package/src/zexus/stdlib/test_runner.zx +119 -0
- package/src/zexus/stdlib_integration.py +341 -0
- package/src/zexus/strategy_recovery.py +256 -0
- package/src/zexus/syntax_validator.py +356 -0
- package/src/zexus/testing/zpics.py +407 -0
- package/src/zexus/testing/zpics_runtime.py +369 -0
- package/src/zexus/type_system.py +374 -0
- package/src/zexus/validation_system.py +569 -0
- package/src/zexus/virtual_filesystem.py +355 -0
- package/src/zexus/vm/__init__.py +8 -0
- package/src/zexus/vm/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_manager.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_pool.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/peephole_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/profiler.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_allocator.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/ssa_converter.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/async_optimizer.py +420 -0
- package/src/zexus/vm/bytecode.py +428 -0
- package/src/zexus/vm/bytecode_converter.py +297 -0
- package/src/zexus/vm/cache.py +532 -0
- package/src/zexus/vm/jit.py +720 -0
- package/src/zexus/vm/memory_manager.py +520 -0
- package/src/zexus/vm/memory_pool.py +511 -0
- package/src/zexus/vm/optimizer.py +478 -0
- package/src/zexus/vm/parallel_vm.py +899 -0
- package/src/zexus/vm/peephole_optimizer.py +452 -0
- package/src/zexus/vm/profiler.py +527 -0
- package/src/zexus/vm/register_allocator.py +462 -0
- package/src/zexus/vm/register_vm.py +520 -0
- package/src/zexus/vm/ssa_converter.py +757 -0
- package/src/zexus/vm/vm.py +1392 -0
- package/src/zexus/zexus_ast.py +1782 -0
- package/src/zexus/zexus_token.py +253 -0
- package/src/zexus/zpm/__init__.py +15 -0
- package/src/zexus/zpm/installer.py +116 -0
- package/src/zexus/zpm/package_manager.py +208 -0
- package/src/zexus/zpm/publisher.py +98 -0
- package/src/zexus/zpm/registry.py +110 -0
- package/src/zexus.egg-info/PKG-INFO +2235 -0
- package/src/zexus.egg-info/SOURCES.txt +876 -0
- package/src/zexus.egg-info/dependency_links.txt +1 -0
- package/src/zexus.egg-info/entry_points.txt +3 -0
- package/src/zexus.egg-info/not-zip-safe +1 -0
- package/src/zexus.egg-info/requires.txt +14 -0
- package/src/zexus.egg-info/top_level.txt +2 -0
- package/zexus.json +14 -0
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Memory Pool Optimization for Zexus VM (Phase 8.2)
|
|
3
|
+
|
|
4
|
+
Provides object pooling to reduce allocation overhead and GC pressure:
|
|
5
|
+
- Integer pooling for common values (-128 to 256)
|
|
6
|
+
- String pooling for small strings (<64 chars)
|
|
7
|
+
- List pooling for small lists (<16 elements)
|
|
8
|
+
- Automatic pool statistics and monitoring
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import time
|
|
12
|
+
from typing import Any, Optional, List, Dict, Set
|
|
13
|
+
from dataclasses import dataclass, field
|
|
14
|
+
from collections import deque
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class PoolStats:
|
|
19
|
+
"""Statistics for an object pool"""
|
|
20
|
+
allocations: int = 0 # Total allocation requests
|
|
21
|
+
hits: int = 0 # Requests served from pool
|
|
22
|
+
misses: int = 0 # Requests that needed new objects
|
|
23
|
+
returns: int = 0 # Objects returned to pool
|
|
24
|
+
reuses: int = 0 # Objects reused from pool
|
|
25
|
+
current_size: int = 0 # Current pool size
|
|
26
|
+
max_size: int = 0 # Maximum pool size
|
|
27
|
+
total_created: int = 0 # Total objects created
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def hit_rate(self) -> float:
|
|
31
|
+
"""Calculate cache hit rate"""
|
|
32
|
+
total = self.hits + self.misses
|
|
33
|
+
return (self.hits / total * 100) if total > 0 else 0.0
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def reuse_rate(self) -> float:
|
|
37
|
+
"""Calculate object reuse rate"""
|
|
38
|
+
return (self.reuses / self.total_created * 100) if self.total_created > 0 else 0.0
|
|
39
|
+
|
|
40
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
41
|
+
"""Convert to dictionary"""
|
|
42
|
+
return {
|
|
43
|
+
'allocations': self.allocations,
|
|
44
|
+
'hits': self.hits,
|
|
45
|
+
'misses': self.misses,
|
|
46
|
+
'returns': self.returns,
|
|
47
|
+
'reuses': self.reuses,
|
|
48
|
+
'current_size': self.current_size,
|
|
49
|
+
'max_size': self.max_size,
|
|
50
|
+
'total_created': self.total_created,
|
|
51
|
+
'hit_rate': self.hit_rate,
|
|
52
|
+
'reuse_rate': self.reuse_rate
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class ObjectPool:
|
|
57
|
+
"""
|
|
58
|
+
Generic object pool with configurable size and factory
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(self, max_size: int = 1000, factory=None):
|
|
62
|
+
"""
|
|
63
|
+
Initialize object pool
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
max_size: Maximum number of objects to pool
|
|
67
|
+
factory: Optional factory function to create new objects
|
|
68
|
+
"""
|
|
69
|
+
self.max_size = max_size
|
|
70
|
+
self.factory = factory
|
|
71
|
+
self.pool: deque = deque(maxlen=max_size)
|
|
72
|
+
self.stats = PoolStats(max_size=max_size)
|
|
73
|
+
self.in_use: Set[int] = set() # Track objects in use
|
|
74
|
+
|
|
75
|
+
def acquire(self, default_value: Any = None) -> Any:
|
|
76
|
+
"""
|
|
77
|
+
Acquire an object from pool or create new one
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
default_value: Default value if pool is empty and no factory
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Object from pool or newly created
|
|
84
|
+
"""
|
|
85
|
+
self.stats.allocations += 1
|
|
86
|
+
|
|
87
|
+
if self.pool:
|
|
88
|
+
obj = self.pool.popleft()
|
|
89
|
+
self.stats.hits += 1
|
|
90
|
+
self.stats.reuses += 1
|
|
91
|
+
self.stats.current_size = len(self.pool)
|
|
92
|
+
obj_id = id(obj)
|
|
93
|
+
self.in_use.add(obj_id)
|
|
94
|
+
return obj
|
|
95
|
+
else:
|
|
96
|
+
self.stats.misses += 1
|
|
97
|
+
if self.factory:
|
|
98
|
+
obj = self.factory()
|
|
99
|
+
else:
|
|
100
|
+
obj = default_value
|
|
101
|
+
self.stats.total_created += 1
|
|
102
|
+
obj_id = id(obj)
|
|
103
|
+
self.in_use.add(obj_id)
|
|
104
|
+
return obj
|
|
105
|
+
|
|
106
|
+
def release(self, obj: Any) -> bool:
|
|
107
|
+
"""
|
|
108
|
+
Return an object to the pool
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
obj: Object to return
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
True if object was returned to pool, False if pool is full
|
|
115
|
+
"""
|
|
116
|
+
obj_id = id(obj)
|
|
117
|
+
if obj_id in self.in_use:
|
|
118
|
+
self.in_use.remove(obj_id)
|
|
119
|
+
|
|
120
|
+
if len(self.pool) < self.max_size:
|
|
121
|
+
self.pool.append(obj)
|
|
122
|
+
self.stats.returns += 1
|
|
123
|
+
self.stats.current_size = len(self.pool)
|
|
124
|
+
return True
|
|
125
|
+
return False
|
|
126
|
+
|
|
127
|
+
def clear(self):
|
|
128
|
+
"""Clear the pool"""
|
|
129
|
+
self.pool.clear()
|
|
130
|
+
self.in_use.clear()
|
|
131
|
+
self.stats.current_size = 0
|
|
132
|
+
|
|
133
|
+
def size(self) -> int:
|
|
134
|
+
"""Get current pool size"""
|
|
135
|
+
return len(self.pool)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class IntegerPool:
|
|
139
|
+
"""
|
|
140
|
+
Specialized pool for integer values
|
|
141
|
+
|
|
142
|
+
Uses a fixed pool for common integers (-128 to 256) and a dynamic
|
|
143
|
+
pool for other values.
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
# Pre-allocated integers for common range
|
|
147
|
+
SMALL_INT_MIN = -128
|
|
148
|
+
SMALL_INT_MAX = 256
|
|
149
|
+
|
|
150
|
+
def __init__(self, max_size: int = 1000):
|
|
151
|
+
"""Initialize integer pool"""
|
|
152
|
+
self.max_size = max_size
|
|
153
|
+
|
|
154
|
+
# Pre-allocated small integers (like Python's integer cache)
|
|
155
|
+
self.small_ints: Dict[int, int] = {
|
|
156
|
+
i: i for i in range(self.SMALL_INT_MIN, self.SMALL_INT_MAX + 1)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# Dynamic pool for other integers
|
|
160
|
+
self.pool: Dict[int, int] = {}
|
|
161
|
+
self.stats = PoolStats(max_size=max_size)
|
|
162
|
+
self.access_count: Dict[int, int] = {} # LRU tracking
|
|
163
|
+
|
|
164
|
+
def get(self, value: int) -> int:
|
|
165
|
+
"""
|
|
166
|
+
Get integer from pool
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
value: Integer value
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
Pooled integer instance
|
|
173
|
+
"""
|
|
174
|
+
self.stats.allocations += 1
|
|
175
|
+
|
|
176
|
+
# Check small int cache first
|
|
177
|
+
if self.SMALL_INT_MIN <= value <= self.SMALL_INT_MAX:
|
|
178
|
+
self.stats.hits += 1
|
|
179
|
+
return self.small_ints[value]
|
|
180
|
+
|
|
181
|
+
# Check dynamic pool
|
|
182
|
+
if value in self.pool:
|
|
183
|
+
self.stats.hits += 1
|
|
184
|
+
self.stats.reuses += 1
|
|
185
|
+
self.access_count[value] = self.access_count.get(value, 0) + 1
|
|
186
|
+
return self.pool[value]
|
|
187
|
+
|
|
188
|
+
# Create new integer
|
|
189
|
+
self.stats.misses += 1
|
|
190
|
+
self.stats.total_created += 1
|
|
191
|
+
|
|
192
|
+
# Add to pool if not full
|
|
193
|
+
if len(self.pool) < self.max_size:
|
|
194
|
+
self.pool[value] = value
|
|
195
|
+
self.access_count[value] = 1
|
|
196
|
+
self.stats.current_size = len(self.pool)
|
|
197
|
+
elif self.access_count:
|
|
198
|
+
# Evict least recently used
|
|
199
|
+
lru_value = min(self.access_count, key=self.access_count.get)
|
|
200
|
+
del self.pool[lru_value]
|
|
201
|
+
del self.access_count[lru_value]
|
|
202
|
+
self.pool[value] = value
|
|
203
|
+
self.access_count[value] = 1
|
|
204
|
+
|
|
205
|
+
return value
|
|
206
|
+
|
|
207
|
+
def clear(self):
|
|
208
|
+
"""Clear dynamic pool (keep small ints)"""
|
|
209
|
+
self.pool.clear()
|
|
210
|
+
self.access_count.clear()
|
|
211
|
+
self.stats.current_size = 0
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class StringPool:
|
|
215
|
+
"""
|
|
216
|
+
String interning pool for small strings
|
|
217
|
+
|
|
218
|
+
Pools strings up to 64 characters to reduce memory overhead
|
|
219
|
+
and improve comparison performance.
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
MAX_STRING_LENGTH = 64
|
|
223
|
+
|
|
224
|
+
def __init__(self, max_size: int = 10000):
|
|
225
|
+
"""Initialize string pool"""
|
|
226
|
+
self.max_size = max_size
|
|
227
|
+
self.pool: Dict[str, str] = {}
|
|
228
|
+
self.stats = PoolStats(max_size=max_size)
|
|
229
|
+
self.access_count: Dict[str, int] = {}
|
|
230
|
+
|
|
231
|
+
def get(self, value: str) -> str:
|
|
232
|
+
"""
|
|
233
|
+
Get string from pool (intern)
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
value: String value
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Pooled string instance
|
|
240
|
+
"""
|
|
241
|
+
self.stats.allocations += 1
|
|
242
|
+
|
|
243
|
+
# Don't pool long strings
|
|
244
|
+
if len(value) > self.MAX_STRING_LENGTH:
|
|
245
|
+
self.stats.misses += 1
|
|
246
|
+
return value
|
|
247
|
+
|
|
248
|
+
# Check if already pooled
|
|
249
|
+
if value in self.pool:
|
|
250
|
+
self.stats.hits += 1
|
|
251
|
+
self.stats.reuses += 1
|
|
252
|
+
self.access_count[value] = self.access_count.get(value, 0) + 1
|
|
253
|
+
return self.pool[value]
|
|
254
|
+
|
|
255
|
+
# Add to pool
|
|
256
|
+
self.stats.misses += 1
|
|
257
|
+
self.stats.total_created += 1
|
|
258
|
+
|
|
259
|
+
if len(self.pool) < self.max_size:
|
|
260
|
+
self.pool[value] = value
|
|
261
|
+
self.access_count[value] = 1
|
|
262
|
+
self.stats.current_size = len(self.pool)
|
|
263
|
+
elif self.access_count:
|
|
264
|
+
# Evict LRU
|
|
265
|
+
lru_str = min(self.access_count, key=self.access_count.get)
|
|
266
|
+
del self.pool[lru_str]
|
|
267
|
+
del self.access_count[lru_str]
|
|
268
|
+
self.pool[value] = value
|
|
269
|
+
self.access_count[value] = 1
|
|
270
|
+
|
|
271
|
+
return value
|
|
272
|
+
|
|
273
|
+
def clear(self):
|
|
274
|
+
"""Clear the pool"""
|
|
275
|
+
self.pool.clear()
|
|
276
|
+
self.access_count.clear()
|
|
277
|
+
self.stats.current_size = 0
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
class ListPool:
|
|
281
|
+
"""
|
|
282
|
+
Pool for small list objects
|
|
283
|
+
|
|
284
|
+
Pools empty lists and small lists (<16 elements) for reuse.
|
|
285
|
+
"""
|
|
286
|
+
|
|
287
|
+
MAX_LIST_SIZE = 16
|
|
288
|
+
|
|
289
|
+
def __init__(self, max_pool_size: int = 500):
|
|
290
|
+
"""Initialize list pool"""
|
|
291
|
+
self.max_pool_size = max_pool_size
|
|
292
|
+
self.MAX_LIST_SIZE = 16
|
|
293
|
+
# Separate pools by size
|
|
294
|
+
self.pools: Dict[int, ObjectPool] = {
|
|
295
|
+
i: ObjectPool(max_size=max_pool_size // 16, factory=list)
|
|
296
|
+
for i in range(self.MAX_LIST_SIZE + 1)
|
|
297
|
+
}
|
|
298
|
+
self.stats = PoolStats(max_size=max_pool_size)
|
|
299
|
+
|
|
300
|
+
def acquire(self, size: int = 0) -> List:
|
|
301
|
+
"""
|
|
302
|
+
Acquire a list from pool
|
|
303
|
+
|
|
304
|
+
Args:
|
|
305
|
+
size: Desired list size
|
|
306
|
+
|
|
307
|
+
Returns:
|
|
308
|
+
List from pool or newly created
|
|
309
|
+
"""
|
|
310
|
+
self.stats.allocations += 1
|
|
311
|
+
|
|
312
|
+
if size > self.MAX_LIST_SIZE:
|
|
313
|
+
self.stats.misses += 1
|
|
314
|
+
self.stats.total_created += 1
|
|
315
|
+
return [None] * size
|
|
316
|
+
|
|
317
|
+
pool = self.pools[size]
|
|
318
|
+
lst = pool.acquire([None] * size)
|
|
319
|
+
|
|
320
|
+
# Update aggregate stats
|
|
321
|
+
if pool.stats.hits > 0:
|
|
322
|
+
self.stats.hits += 1
|
|
323
|
+
self.stats.reuses += 1
|
|
324
|
+
else:
|
|
325
|
+
self.stats.misses += 1
|
|
326
|
+
self.stats.total_created += 1
|
|
327
|
+
|
|
328
|
+
# Ensure list is the right size and cleared
|
|
329
|
+
if len(lst) != size:
|
|
330
|
+
lst.clear()
|
|
331
|
+
lst.extend([None] * size)
|
|
332
|
+
|
|
333
|
+
return lst
|
|
334
|
+
|
|
335
|
+
def release(self, lst: List) -> bool:
|
|
336
|
+
"""
|
|
337
|
+
Return a list to the pool
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
lst: List to return
|
|
341
|
+
|
|
342
|
+
Returns:
|
|
343
|
+
True if returned to pool, False otherwise
|
|
344
|
+
"""
|
|
345
|
+
size = len(lst)
|
|
346
|
+
if size > self.MAX_LIST_SIZE:
|
|
347
|
+
return False
|
|
348
|
+
|
|
349
|
+
# Clear list before returning to pool
|
|
350
|
+
lst.clear()
|
|
351
|
+
|
|
352
|
+
pool = self.pools[size]
|
|
353
|
+
success = pool.release(lst)
|
|
354
|
+
|
|
355
|
+
if success:
|
|
356
|
+
self.stats.returns += 1
|
|
357
|
+
|
|
358
|
+
return success
|
|
359
|
+
|
|
360
|
+
def clear(self):
|
|
361
|
+
"""Clear all pools"""
|
|
362
|
+
for pool in self.pools.values():
|
|
363
|
+
pool.clear()
|
|
364
|
+
self.stats.current_size = 0
|
|
365
|
+
|
|
366
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
367
|
+
"""Get combined statistics"""
|
|
368
|
+
return {
|
|
369
|
+
'aggregate': self.stats.to_dict(),
|
|
370
|
+
'by_size': {
|
|
371
|
+
size: pool.stats.to_dict()
|
|
372
|
+
for size, pool in self.pools.items()
|
|
373
|
+
if pool.stats.allocations > 0
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
class MemoryPoolManager:
|
|
379
|
+
"""
|
|
380
|
+
Central manager for all memory pools
|
|
381
|
+
|
|
382
|
+
Coordinates integer, string, and list pools and provides
|
|
383
|
+
unified statistics and control.
|
|
384
|
+
"""
|
|
385
|
+
|
|
386
|
+
def __init__(
|
|
387
|
+
self,
|
|
388
|
+
enable_int_pool: bool = True,
|
|
389
|
+
enable_str_pool: bool = True,
|
|
390
|
+
enable_list_pool: bool = True,
|
|
391
|
+
int_pool_size: int = 1000,
|
|
392
|
+
str_pool_size: int = 10000,
|
|
393
|
+
list_pool_size: int = 500
|
|
394
|
+
):
|
|
395
|
+
"""
|
|
396
|
+
Initialize memory pool manager
|
|
397
|
+
|
|
398
|
+
Args:
|
|
399
|
+
enable_int_pool: Enable integer pooling
|
|
400
|
+
enable_str_pool: Enable string pooling
|
|
401
|
+
enable_list_pool: Enable list pooling
|
|
402
|
+
int_pool_size: Max integer pool size
|
|
403
|
+
str_pool_size: Max string pool size
|
|
404
|
+
list_pool_size: Max list pool size
|
|
405
|
+
"""
|
|
406
|
+
self.enable_int_pool = enable_int_pool
|
|
407
|
+
self.enable_str_pool = enable_str_pool
|
|
408
|
+
self.enable_list_pool = enable_list_pool
|
|
409
|
+
|
|
410
|
+
self.int_pool = IntegerPool(max_size=int_pool_size) if enable_int_pool else None
|
|
411
|
+
self.str_pool = StringPool(max_size=str_pool_size) if enable_str_pool else None
|
|
412
|
+
self.list_pool = ListPool(max_pool_size=list_pool_size) if enable_list_pool else None
|
|
413
|
+
|
|
414
|
+
self.start_time = time.time()
|
|
415
|
+
|
|
416
|
+
def get_int(self, value: int) -> int:
|
|
417
|
+
"""Get pooled integer"""
|
|
418
|
+
if self.int_pool:
|
|
419
|
+
return self.int_pool.get(value)
|
|
420
|
+
return value
|
|
421
|
+
|
|
422
|
+
def get_str(self, value: str) -> str:
|
|
423
|
+
"""Get pooled string"""
|
|
424
|
+
if self.str_pool:
|
|
425
|
+
return self.str_pool.get(value)
|
|
426
|
+
return value
|
|
427
|
+
|
|
428
|
+
def acquire_list(self, size: int = 0) -> List:
|
|
429
|
+
"""Acquire pooled list"""
|
|
430
|
+
if self.list_pool:
|
|
431
|
+
return self.list_pool.acquire(size)
|
|
432
|
+
return [None] * size
|
|
433
|
+
|
|
434
|
+
def release_list(self, lst: List) -> bool:
|
|
435
|
+
"""Release list back to pool"""
|
|
436
|
+
if self.list_pool:
|
|
437
|
+
return self.list_pool.release(lst)
|
|
438
|
+
return False
|
|
439
|
+
|
|
440
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
441
|
+
"""Get comprehensive statistics"""
|
|
442
|
+
stats = {
|
|
443
|
+
'enabled': {
|
|
444
|
+
'int_pool': self.enable_int_pool,
|
|
445
|
+
'str_pool': self.enable_str_pool,
|
|
446
|
+
'list_pool': self.enable_list_pool
|
|
447
|
+
},
|
|
448
|
+
'uptime_seconds': time.time() - self.start_time
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if self.int_pool:
|
|
452
|
+
stats['int_pool'] = self.int_pool.stats.to_dict()
|
|
453
|
+
|
|
454
|
+
if self.str_pool:
|
|
455
|
+
stats['str_pool'] = self.str_pool.stats.to_dict()
|
|
456
|
+
|
|
457
|
+
if self.list_pool:
|
|
458
|
+
stats['list_pool'] = self.list_pool.get_stats()
|
|
459
|
+
|
|
460
|
+
# Calculate aggregate savings
|
|
461
|
+
total_allocations = 0
|
|
462
|
+
total_hits = 0
|
|
463
|
+
|
|
464
|
+
if self.int_pool:
|
|
465
|
+
total_allocations += self.int_pool.stats.allocations
|
|
466
|
+
total_hits += self.int_pool.stats.hits
|
|
467
|
+
|
|
468
|
+
if self.str_pool:
|
|
469
|
+
total_allocations += self.str_pool.stats.allocations
|
|
470
|
+
total_hits += self.str_pool.stats.hits
|
|
471
|
+
|
|
472
|
+
if self.list_pool:
|
|
473
|
+
total_allocations += self.list_pool.stats.allocations
|
|
474
|
+
total_hits += self.list_pool.stats.hits
|
|
475
|
+
|
|
476
|
+
stats['aggregate'] = {
|
|
477
|
+
'total_allocations': total_allocations,
|
|
478
|
+
'total_hits': total_hits,
|
|
479
|
+
'overall_hit_rate': (total_hits / total_allocations * 100) if total_allocations > 0 else 0.0
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
return stats
|
|
483
|
+
|
|
484
|
+
def clear_all(self):
|
|
485
|
+
"""Clear all pools"""
|
|
486
|
+
if self.int_pool:
|
|
487
|
+
self.int_pool.clear()
|
|
488
|
+
if self.str_pool:
|
|
489
|
+
self.str_pool.clear()
|
|
490
|
+
if self.list_pool:
|
|
491
|
+
self.list_pool.clear()
|
|
492
|
+
|
|
493
|
+
def memory_usage_bytes(self) -> int:
|
|
494
|
+
"""Estimate memory usage of pools"""
|
|
495
|
+
import sys
|
|
496
|
+
total = 0
|
|
497
|
+
|
|
498
|
+
if self.int_pool:
|
|
499
|
+
total += sys.getsizeof(self.int_pool.pool)
|
|
500
|
+
total += sys.getsizeof(self.int_pool.small_ints)
|
|
501
|
+
|
|
502
|
+
if self.str_pool:
|
|
503
|
+
total += sys.getsizeof(self.str_pool.pool)
|
|
504
|
+
for s in self.str_pool.pool.values():
|
|
505
|
+
total += sys.getsizeof(s)
|
|
506
|
+
|
|
507
|
+
if self.list_pool:
|
|
508
|
+
for pool in self.list_pool.pools.values():
|
|
509
|
+
total += sys.getsizeof(pool.pool)
|
|
510
|
+
|
|
511
|
+
return total
|