Hi All:

I've created a simple program to make sure I wasn't lying to you all ;->

Here it is:

for (ii = 0; ii < 100; ii++)
        {
            Py_Initialize();

            if ((code = Py_CompileString(p, "foo", Py_file_input)) == NULL)
                printf("PyRun_SimpleString() failed\n");
            else
            {
                if (PyRun_SimpleString(p) == -1)
                    printf("PyRun_SimpleString() failed\n");

                Py_CLEAR(code);
            }

            Py_Finalize();
        }

This sequence causes about 10k growth per iteration and after many cycles, there's no indication that any pooling logic is helping. Our "useful" example is slightly more complex, and therefore may explain why I was seeing about 16k per iteration.

Unless I've done something obviously wrong, I tend to believe Benjamin's claim that this issue is well known.

Suggestion: I have had great success with similar problems in the past by using a pools implementation sitting on top of what I call a "block memory allocator". The bottom (block) allocator grabs large blocks from the heap and then doles them out to the pools layer, which in turn doles them out to the requester. When client memory is freed -- it is NOT -- rather it's added to the pool which contains like-sized blocks -- call it an "organized free list". This is a very, very fast way to handle high allocation frequency patterns. Finally, during shutdown, the pool simply vaporizes and the block allocator returns a the (fewer) large blocks back to the heap. This avoids thrashing the heap, forcing it to coalesce inefficiently and also avoids heap fragmentation, which can cause unwanted growth as well...

Note that this would be a "hard-reset" of all allocated memory, and any global data in the text segment would also have to be cleared, but it would provide a fast, clean way to ensure that each invocation was 100% clean.

I don't claim to understand all the intricacies of the many way python can be embedded, but as I said, this strategy has worked very well for me in the past building servers written in C that have to stay up for months at a time.

Happy to discuss further, if anyone has any interest.

Best,

Matt




On 1/14/2016 4:45 AM, Nick Coghlan wrote:
On 14 January 2016 at 15:42, Benjamin Peterson <benja...@python.org> wrote:
This is a "well-known" issue. Parts of the interpreter (and especially,
extension modules) cheerfully stash objects in global variables with no
way to clean them up. Fixing this is a large project, which probably
involves implementing PEP 489.
The actual multi-phase extension module import system from 489 was
implemented for 3.5, but indeed, the modules with stashed global state
haven't been converted yet.

I didn't think we loaded any of those by default, though...

Cheers,
Nick.


--
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to