I think it may come from the code used to benchmark, which may over allocate, since it’s something that happens easily with, for instance, the ubiquitous Vec (given the poor usability of stack arrays, but that’s another topic).
I’ve heard the memory problem may come from closures and their allocating a custom stack, but if I’ve understood them correctly (which I definitely may not), closures are just sugar for an environment struct made of the captured variables + a call method / trait with the behavior/code of the closure.
The memory usage of a solution was gathered using the time tool, available in Unix-based systems. This tool runs a program given as an argument, and summarizes the system resources used by that program, which includes the peak of memory usage.
Every language implementation has a different allocation strategy. Maybe Go’s is slightly more tuned for lower usage while Rust’s is slightly more tuned for speed. Another thing to take into account is that memory usage as measured by time may be larger than the amount of memory ever actually used by your program. For example, freeing an object does not necessarily release memory used by that object back to the OS, so time won’t show usage go down, even though the allocator could give it back at any time.
In order to obtain a comparable, representative and extensive set of programs written in many of the most popular and most widely used programming languages we have explored The Computer Language Benchmarks Game[.]
CLBG asks on its main page, “Which programs are faster?” (emphasis mine). While there are rules about which algorithm a program has to use, and programs are supposed to be “idiomatic”, the nature of the benchmarks game emphasizes speed. Where a programmer can trade increased memory usage for better speed, they probably will.
Another thing I just noticed: the graphs in the paper do not appear to broadly agree with the numbers published by the site itself. For example, the paper shows binary-trees as using about the same amount of memory in both Rust and Go, but the Benchmarks Game has Go using nearly 3 times as much as Rust. Whether this discrepancy stems from hardware differences or language/library/benchmark updates is hard to say, but you’d certainly want to track it down before taking either result seriously.
Your understanding is essentially correct. Closures use the same stack as everybody else. There’s no extra allocation involved with making or calling a closure (in Rust) as compared to a regular function.