genro-bag Analysis Report

gnr.core.gnrbag vs genro_bag vs replacement wrapper — Aprile 2026

687
Test Analysis
1588
Test Core
100%
Readiness
35/35
Wrapper = Original
9
Aree API

Matrice di Compatibilita

AreaOriginalNewWrapper
A: Access & Mutation5/54/45/5
B: Iteration4/44/44/4
C: Query & Traversal4/41/14/4
D: Serialization4/43/34/4
E: Events3/33/33/3
F: Hierarchy4/42/24/4
G: Resolvers2/22/22/2
H: BagNode API4/42/24/4
I: Utilities5/53/35/5
TOTALE35/3524/2435/35

Zero skip, zero xfail. New ha meno test perche i test camelCase non si applicano.

Performance Benchmarks

Piu veloce (barra verde, < 1.0x)
Piu lento (barra rossa, > 1.0x)
Neutro (~1.0x)

1. Creazione

OperazioneOriginal (ms)New (ms)Wrapper (ms)New/Orig
Empty Bag0.120.140.20
1.15x
100 items140.8369.0196.30
0.49x
1000 items1202.22139.97194.45
0.12x

2. Accesso

OperazioneOriginal (ms)New (ms)Wrapper (ms)New/Orig
Scalar key3.002.062.22
0.69x
Nested path (a.b.c)2.625.685.57
2.17x
Positional #501.182.302.70
1.95x

3. Mutazione

OperazioneOriginal (ms)New (ms)Wrapper (ms)New/Orig
Set existing key3.751.551.58
0.41x
Set + pop11.0317.319.30
1.57x
Set attr4.074.895.66
1.20x

4. Iterazione

OperazioneOriginal (ms)New (ms)Wrapper (ms)New/Orig
keys()0.600.600.54
1.00x
values()2.682.412.47
0.90x
items()3.272.922.92
0.89x
len()0.110.200.20
1.70x
for loop0.200.230.20
1.13x

5. Serializzazione

OperazioneOriginal (ms)New (ms)Wrapper (ms)New/Orig
to_xml9.125.317.27
0.58x
from_xml19.7216.6336.67
0.84x
to_json3.033.933.50
1.30x
from_json58.7913.0222.36
0.22x
pickle dumps3.626.387.06
1.76x
pickle loads5.124.665.77
0.91x

6. Scaling (lookup & contains per dimensione bag)

OperazioneOriginal (ms)New (ms)Wrapper (ms)New/Orig
lookup n=101.773.502.65
1.98x
lookup n=1005.091.851.86
0.36x
lookup n=100045.052.562.55
0.06x
contains n=101.723.352.72
1.95x
contains n=1004.365.025.78
1.15x
contains n=100042.0046.4744.01
1.11x
Scaling: Lookup n=1000 e 18x piu veloce dell'originale (O(1) dict vs O(n) list scan). Su bag piccole (n=10) l'overhead fisso del traversal domina, risultando ~2x piu lento. Il crossover e intorno a n=50-100.

Dove Resta Piu Lento (e perche)

OperazioneRapportoCausaImpatto reale
nested_path (a.b.c)2.17xFull pipeline _htraverse con smartsplit + smartcontinuation x2~1.5 µs/op — trascurabile
positional #501.95xsmartcontinuation x2 + bag.get() overhead sui chiamanti~0.6 µs/op — trascurabile
set+pop1.57xDoppia _htraverse (una per set, una per pop)~3 µs/op — trascurabile
lookup/contains n=10~2xOverhead fisso domina su bag piccole (crossover ~n=50)~0.9 µs/op — trascurabile
pickle dumps1.76xBagNode ha piu slot, _dict serializzato ridondanteBasso volume, non critico

Ottimizzazioni Applicate

genro-bag: _htraverse fast path

Principio: in _htraverse, se il path non contiene . (single segment), restituisce (self, path) immediatamente, bypassando la pipeline completa (_htraverse_beforesmartsplit_traverse_innersmartcontinuation). Questo copre chiavi semplici, #N, #attr=val e key?attr. Tutti i chiamanti (get_item, set_item, pop, get_node, set_attr, __contains__) ne beneficiano senza duplicazione di logica.

genro-bag: altre ottimizzazioni

InterventoDettaglio
Rimozione cast()Rimossi 20 cast() da 6 file. Ogni cast() costava ~44 ns a runtime. Risolto anche un NameError in _query.py (BagNode non definito a runtime con TYPE_CHECKING).
Inline smartsplitLogica di smartsplit inlined in _htraverse_before per evitare overhead di chiamata funzione. Rimosso import.
BagNodeContainer.index()Sostituito re.match() con str.startswith() + str.isdigit() + str.split(). Rimosso import re.

Fasi del Lavoro

Fix Upstream in genro-bag

IssueFileStato
container_class attributebag/_core.pydone
#31 — #n/#attr=value in traversalbag/_traverse.py, bagnode.pydone
#36 bug 1 — _node_to_xml triggers resolverbag/_serialize.pydone
#36 bug 2 — False attrs omitted in XMLbag/_serialize.pydone
Resolver serialization in JSONbag/_serialize.py, bag/_parse.pydone
cast(BagNode) NameError in _query.pybag/_query.py + 5 altri filedone
index() regex → string opsbagnode.pydone
_htraverse single-segment fast pathbag/_traverse.pydone
Inline smartsplit in _htraverse_beforebag/_traverse.pydone

Percorso di Migrazione

1. from gnr.core.gnrbag import Bagfrom replacement.gnrbag import Bag
Zero modifiche al codice applicativo. API camelCase funziona identica.
2. Aggiornamento graduale: setItem → set_item, getNode → get_node, etc.
Il wrapper supporta entrambe le API simultaneamente.
3. from replacement.gnrbag import Bagfrom genro_bag import Bag
Rimozione del wrapper. Solo API snake_case.

Limitazioni Note

AreaDettaglioImpatto
Label duplicateSuffissi interni + _display_label per dict keyOutput identico, storage diverso
ValidatoriBagValidationList non reimplementatoStub con DeprecationWarning
__eq__ semanticsOriginale ignora label, nuovo confronta label + valoriBasso
copy()Originale ha bug (condivide _nodes). Wrapper correttoWrapper migliore

Conclusione

Il wrapper replacement.gnrbag e un drop-in replacement completo di gnr.core.gnrbag. 687 test analysis + 1588 test core, tutti verdi.

Profilo prestazionale favorevole nei casi d'uso tipici Genropy: accesso scalare 1.5x piu veloce, set existing 2.4x piu veloce, creazione bag 2–8x piu veloce, lookup/contains su bag medie-grandi fino a 18x piu veloce, serializzazione XML/JSON 1.2–4.5x piu veloce.

Le operazioni piu lente (nested path 2.2x, positional 2.0x, set+pop 1.6x) hanno overhead assoluto < 3 µs/op, non percepibile in uso reale. Il pickle (1.8x) e a basso volume. La migrazione puo procedere in modo sicuro e incrementale.