0

I am trying to modify the runtime to not use shared pointers and no locks. I did replace all of them to use new operator instead, so far so good, the runtime still operates correctly, but... there is a very large number of memory leaks (not surprising). What is the lifecycle of objects like ATNConfig? Where would be a safe place to delete them? Note, I also made the generated parser use non static ATN so I don't need the locks in multithread context.

Here is an example of a leak I get:

==4747== 54,736,648 (53,672,160 direct, 1,064,488 indirect) bytes in 1,118,170 blocks are definitely lost in loss record 1,519 of 1,519
==4747==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4747==    by 0xAE24F0: antlr4::atn::ParserATNSimulator::getEpsilonTarget(antlr4::atn::ATNConfig*, antlr4::atn::Transition*, bool, bool, bool, bool) (ParserATNSimulator.cpp:1050)
==4747==    by 0xAE1D01: antlr4::atn::ParserATNSimulator::closure_(antlr4::atn::ATNConfig*, antlr4::atn::ATNConfigSet*, std::unordered_set<antlr4::atn::ATNConfig*, antlr4::atn::ATNConfig::Hasher, antlr4::atn::ATNConfig::Comparer, std::allocator<antlr4::atn::ATNConfig*> >&, bool, bool, int, bool) (ParserATNSimulator.cpp:894)
Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56

1 Answers1

1

I thought intensely about a solution without smart pointers for the ANTLR4 C++ runtime, because they make processing slower, but couldn't find one. The DFA and particularly the ATNConfig instances are organized like a mesh, referencing each other. There's no central instance that manages them. They are (Java like) created and destroyed in many places during prediction.

What could help instead is to replace the shared pointers in function calls by raw pointers, in cases where that doesn't affect the lifetime of those pointers. But I doubt this will bring more than a few percent speed win.

Mike Lischke
  • 48,925
  • 16
  • 119
  • 181
  • Hi Mike, I agree, the local change to raw pointers is not going to be significant. – Alain Marcel Oct 18 '18 at 04:45
  • Keeping shared pointers but making dedicated pools of objects, specifically for the DFA and ATNConfig objects that seems to be the more dynamic ones, might be a venue. The pools would have to be per thread. std::allocate_shared seems to fit the bill. – Alain Marcel Oct 18 '18 at 04:56
  • @AlainMarcel I'd love to see a pull request once you found a better way of managing the memory in the ANTLR4 runtime. Currently everything is close to the Java reference implementation, but we can certainly apply some optimizations that better fit C++. – Mike Lischke Oct 18 '18 at 06:52
  • Would you be open to use something like this? It uses TBB: https://stackoverflow.com/questions/5161614/is-there-an-open-source-thread-safe-c-object-pool-implementation , if not, there are many object pools out there, we will need to find one that fits with the ANTLR licensing – Alain Marcel Oct 19 '18 at 04:47
  • Just throwing in an object pool won't cut it (but I thought about such an approach, of course). You would need to restructure how classes are managed in general. – Mike Lischke Oct 19 '18 at 06:50