Skip to content

Commit e449e73

Browse files
konardclaude
andcommitted
Optimize dump_object shape() by replacing string join with dictionary tree
Following the same pattern as the previous optimization of $mol_vary riches Map, replaced the string-based shape lookup in dump_object with a dictionary tree structure. **Before:** ```typescript const key = keys1.join('\0') // ['a', 'b'] → 'a\0b' const keys2 = shapes.get(key) ``` **After:** ```typescript // Traverse dictionary tree: shapes -> 'a' -> 'b' -> cached_keys_array let node: ShapeNode | any[] | undefined = shapes for (const key of keys1) { node = node?.get(key) } ``` **Benefits:** - No string concatenation overhead - Direct Map traversal instead of string operations - Shared prefixes in tree structure for better memory usage - Consistent with the riches Map optimization Addresses comment from nin-jin: "dump_object тоже обнови - шейпы POJO тоже должны быть оптимизированы" Related to #806 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 01353ef commit e449e73

File tree

1 file changed

+42
-5
lines changed

1 file changed

+42
-5
lines changed

vary/vary.ts

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,50 @@ namespace $ {
221221

222222
}
223223

224-
const shapes = new Map< string, any[] >()
224+
// Dictionary tree for POJO shapes (replaces string-based lookup)
225+
type ShapeNode = Map<string, ShapeNode | any[]>
226+
const shapes: ShapeNode = new Map()
225227
const shape = ( val: any )=> {
226228
const keys1 = Object.keys( val )
227-
const key = keys1.join('\0')
228-
const keys2 = shapes.get( key )
229-
if( keys2 ) return keys2
230-
shapes.set( key, keys1 )
229+
230+
// Handle empty object case
231+
if (keys1.length === 0) {
232+
const cached = shapes.get('') as any[] | undefined
233+
if (cached) return cached
234+
shapes.set('', keys1)
235+
return keys1
236+
}
237+
238+
// Traverse tree to find cached keys or create path
239+
let node: ShapeNode | any[] | undefined = shapes
240+
for (const key of keys1) {
241+
if (!node || Array.isArray(node)) break
242+
node = node.get(key)
243+
}
244+
245+
// If we found cached keys at the end of the path, return them
246+
if (node && Array.isArray(node)) return node
247+
248+
// Otherwise, build the tree path and store keys1 at the end
249+
let current = shapes
250+
for (let i = 0; i < keys1.length; i++) {
251+
const key = keys1[i]
252+
const isLast = i === keys1.length - 1
253+
254+
if (isLast) {
255+
// Store the keys array at the terminal node
256+
current.set(key, keys1)
257+
} else {
258+
// Get or create intermediate node
259+
let next = current.get(key)
260+
if (!next || Array.isArray(next)) {
261+
next = new Map()
262+
current.set(key, next)
263+
}
264+
current = next as ShapeNode
265+
}
266+
}
267+
231268
return keys1
232269
}
233270

0 commit comments

Comments
 (0)