News for hackers. Stuff that matters.
Re:Memory Management in Python by jakear on Sunday August 04, 2019 @11:40PM (#20611068)
I’ve found it’s easy to get much better performance in CPython by simply replacing their malloc with my own. Mine allocates a large block of memory on the stack, then pulls from it. Won’t work for large programs, but for smaller scripts it’s a good amount faster. I think this is because CPython makes something like 1000 malloc calls just to startup, so if those can be made ~instant you get a lot of benefit.
Re:Memory Management in Python by vvanders on Monday August 05, 2019 @01:00AM (#20611405)
We did this in gamedev all the time with arena allocators[1].

Generally per-level or at some other temporal division. That, in-place loading and fixed-size pools for things like effects covered 90% of the allocation tricks we did to get huge performance gains.

[1] https://developers.google.com/protocol-buffers/docs/referenc...

Re:Memory Management in Python by jakear on Sunday August 04, 2019 @11:43PM (#20611085)
The repo: https://github.com/JacksonKearl/cpython/blob/master/README.r...

My allocator isn’t included as it is part of a class project, but you can make your own malloc pretty easily.

Alternatively you can just do some LD preload magic, but I don’t know much about that (and this was needed to match the class spec)

Re:Memory Management in Python by codetrotter on Monday August 05, 2019 @11:18AM (#20614849)
> My allocator isn’t included as it is part of a class project, but you can make your own malloc pretty easily.

Was this a class that you took, or one that you TA or tutored?

Re:Memory Management in Python by jakear on Monday August 05, 2019 @12:25PM (#20615402)
I was a TA.
Re:Memory Management in Python by shakna on Monday August 05, 2019 @12:09AM (#20611205)
> I think this is because CPython makes something like 1000 malloc calls just to startup, so if those can be made ~instant you get a lot of benefit.

This suggests that Python's pool allocator is really bad at handling start up procedures, doesn't it?

It intentionally over allocates, but not by enough to handle the warm up procedure.

Re:Memory Management in Python by jakear on Monday August 05, 2019 @12:28AM (#20611291)
Yes, CPython has poor startup performance due in large part to the number of allocations it makes, and once can achieve at least 60% reductions in startup time by being smarter about those allocations.
Re:Memory Management in Python by shakna on Monday August 05, 2019 @08:14AM (#20613448)
This has had me thinking about the Python/malloc story for a little bit.

It does make sense CPython is tuned more towards runtime than startup time. One is a continual cost, one is paid once and doesn't matter for a large variety of workloads.

But if CPython really is make 1000+ allocations during startup, then it is probably going to fragment badly, which slow down everything, and into the future as well...

Seems that's not a crazy idea. [0] Zapier linked CPython to jemalloc which tends to fragment less and saw 40% memory gains.

I guess if you took the time to tune jemalloc to your workload you should be able to see significant performance improvements at startup as well as in the hot path.

[0] https://zapier.com/engineering/celery-python-jemalloc/

Re:Memory Management in Python by pferde on Monday August 05, 2019 @05:57AM (#20612726)
With it being a very popular python implementation, one wonders why such optimizations haven't been implemented yet. 60% sounds huge.
Re:Memory Management in Python by mikepurvis on Monday August 05, 2019 @08:03AM (#20613380)
Probably because overall Python startup time is still dominated by site.py/pkg_resources spidering the filesystem and importing half the world; as long as that exists for most users, it's hard to be motivated to make speedups anywhere else.

cf. https://github.com/pypa/setuptools/issues/510

The problem is so bad that it's one of the top quoted reasons that hg is considering a gradual rewrite to rust:

https://www.mercurial-scm.org/wiki/OxidationPlan

Re:Memory Management in Python by cozzyd on Monday August 05, 2019 @11:14AM (#20614815)
Hilariously, my pentadactyl shortcut for the oxidation plan was HG. I took that as a sign to read the article. Has hg ever considered a long-running "daemon-like" process instead? It could be instantiated automatically by the first call to hg and then it can die after it hasn't been used for a while. It would probably be racy and hard to support on multiple OS's though...
Re:Memory Management in Python by mikepurvis on Tuesday August 06, 2019 @10:09AM (#20625285)
They do kind of have this: https://www.mercurial-scm.org/wiki/CommandServer

Though it looks like it's more about supplying a way to embed hq in a proprietary (or non-Python) application via subprocess communication rather than directly importing the GPL modules or having to string-parse responses. There doesn't seem to be provision for interacting with the server directly from the command line, which is odd, since this pattern is well established from Java land (bazel, for example).

Re:Memory Management in Python by icebraining on Monday August 05, 2019 @10:06AM (#20614301)
The pkg_resources problem is specific for programs that use entry points (and it can be avoided), not a general CPython issue, and AFAICT is not related to Mercurial's plan to include Rust.
Re:Memory Management in Python by mikepurvis on Tuesday August 06, 2019 @10:04AM (#20625243)
Interesting; I hadn't realised this, thanks for the clarification.

I'm aware of yapsy as a lightweight plugin system, but entry_points really is the gold standard in terms of Python extensibility. It's a shame it can't be made more performant.

Re:Memory Management in Python by pferde on Monday August 05, 2019 @08:54AM (#20613758)
Thanks for this, it makes for an interesting read, especially for someone who only dips his toe in python programming lightly once in a while.
Re:Memory Management in Python by mehrdadn on Monday August 05, 2019 @12:05PM (#20615205)
Confused, how do you replace malloc with memory pulled from the stack? Wouldn't it get trampled?
Re:Memory Management in Python by jakear on Monday August 05, 2019 @12:20PM (#20615347)
Reserve a fixed amount and pull from it. That’s why I say it won’t work for larger programs. Though, you could resort to normal malloc after your stack memory runs out. This would get you the improved startup performance and runtime performance for smaller programs (those that use less memory than you initially reserve), without sacrificing anything on larger programs.

Edit: to be clear, I’m pretty sure that initial block could be reserved on the heap. The benefit comes from the large initial allocation, not from the memory being on the stack.

Re:Memory Management in Python by mehrdadn on Monday August 05, 2019 @12:29PM (#20615443)
Do you mean you're compiling the interpreter from scratch with C/C++ code that performs this initial allocation? It's really confusing trying to decipher what you're doing, since it doesn't sound like something that you could do to an existing CPython interpreter without corrupting memory...
Re:Memory Management in Python by jakear on Monday August 05, 2019 @12:41PM (#20615568)
Yep! Building from the C source. If you check out the demo I linked in another comment, it’s just a couple additional files in the CPython repo.