/run/printProgress effectively leaks memory

Punchline: Running a simulation with /run/printProgress 1000, 100k events per run, very short time per event (~milliseconds), and a few hundred runs in a row leads to massive memory consumption and can crash the program and my computer. The memory consumption is on order tens of MB/second. This is not so good.

System details

  • OS Debian 13 kernel 6.12.105
  • Geant4 v11.4.2
  • Compiler gcc 14.2.0
  • CMake 3.31.6

I’m running a simulation based on this Geant4 project: impish/geant.

I stumbled upon this behavior doing simulations of X-rays through hundreds of G4Box slabs of air. But, the behavior is reproduced with just a single G4Box geometry preset in the world volume. The point is there are lots of events generated.

Running them with no debug printing gives a flat memory consumption of max ~1 GB even for a long-running program. Running with /run/printProgress 1000 leads to huge memory consumptions and crashes.

I looked into e.g. G4Allocator, leaks in my own code, etc. The diagnostic tool that was most helpful is called heaptrack which seems to work a lot faster than Valgrind for this sort of thing (?)

I talked with ChatGPT about this to not bother everyone on the forum beforehand: https://chatgpt.com/share/6a925126-7bf4-83ea-a962-304f480f2efd.

Best
William

It’d be better if you could provide a minimum reproducible example here.

Ok, I’ll work on it.

@bmorgan You can reproduce the behavior by launching example Basic B1 in Qt mode, disabling visualization /vis/disable, and then running loop.mac:

# inner.mac
/control/echo starting run {idx}
/run/printProgress 1000
/run/beamOn 100000
# loop.mac
/control/verbose 0
/run/verbose 0
/event/verbose 0
/tracking/verbose 0

/gun/particle gamma
/gun/energy 30 keV

/run/printProgress 1000
/control/loop inner.mac idx 0 8 1

More investigation

Looking at the heaptrack results for my project, it looks like most of the memory is leaking out of G4coutDestination::ReceiveG4cout_ via the Qt interface.

Running example Basic B1 doesn’t forward G4cout to any Qt interfaces in non-interactive mode, so that might be part of why the runs don’t leak.

Reproducing leak in example Basic B1

Running basic B1 with the Qt GUI enabled, the behavior is reproduced. Memory consumption steadily climbs.

I guess this isn’t really a leak, then, just that the Qt GUI is accumulating a very large print buffer. That makes sense.

Here’s the heaptrack from Basic B1

Resolution

  • Set a limit on the # of lines stored by the Qt console ?
  • Do not instantiate a Qt session for noninteractive runs in my project.I am not sure why the Qt interface is used at all during the noninteractive runs. I probably have a bug. I was instantiating the UIExecutive for every run, not just the interactive ones.

I guess this still leaves the question: is this “leak” expected behavior?

Can you confirm this is not seen when running in batch mode with exampleB1? e.g. with

exampleB1 ./exampleB1.in

with the provided macro, or with your updated one?

Correct, the behavior is not reproduced running exampleB1.in or my updated code