gf2121 commented on PR #15970:
URL: https://github.com/apache/lucene/pull/15970#issuecomment-4294651061

   Thanks for opening this PR and looking into this! I apologize for not having 
optimized the TrieBuilder for better memory efficiency earlier. As the TODO in 
the JavaDoc points out, we definitely need to make it a much more 
memory-efficient structure.
   
   Overall, I am fine with the idea of introducing a SaveFrame to shave off 
those 16 bytes (an 8-byte object reference + an 8-byte long fp) from each Node. 
However, I am a bit skeptical about whether this will resolve the OOM issues 
you are seeing with long fields like URLs. Even with this reduction, the sheer 
volume of Node object headers and structural references will still consume a 
massive amount of heap memory in those worst-case scenarios.
   
   A couple of relatively straightforward optimization ideas come to mind that 
might yield more substantial memory savings:
   
   1. Path Compression (Radix Tree approach): Instead of storing a single int 
label for every single character, we could store a byte[] labels per Node. This 
would compress long, unbranched chains of single-child nodes into a single 
edge, which would drastically reduce the total number of allocated Node 
objects—especially for long, repetitive strings like URLs or UUIDs.
   
   2. Similar to how the FSTCompiler worked, we could potentially keep the 
structures serialized. When merging, we could append the already-serialized 
data term-by-term into a brand new TrieBuilder (or compiler). This would trade 
off some CPU overhead during merges for a significant reduction in peak heap 
memory usage, as we wouldn't need to keep the entire object graph resident in 
memory at once.
   
   FWIW the original code with FST:
   ```
   final ByteSequenceOutputs outputs = ByteSequenceOutputs.getSingleton();
   final FSTCompiler<BytesRef> fstCompiler =
       new FSTCompiler.Builder<>(FST.INPUT_TYPE.BYTE1, outputs)
           .suffixRAMLimitMB(0d)
           .bytesPageBits(pageBits)
           .build();
   
   final byte[] bytes = scratchBytes.toArrayCopy();
       assert bytes.length > 0;
       fstCompiler.add(Util.toIntsRef(prefix, scratchIntsRef), new 
BytesRef(bytes, 0, bytes.length));
       scratchBytes.reset();
   
       for (PendingBlock block : blocks) {
     if (block.subIndices != null) {
       for (FST<BytesRef> subIndex : block.subIndices) {
         append(fstCompiler, subIndex, scratchIntsRef);
       }
       block.subIndices = null;
     }
   }
   
   index = fstCompiler.compile();
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to