Re: [HACKERS] new heap manager mmalloc - Mailing list pgsql-hackers
From | jwieck@debis.com (Jan Wieck) |
---|---|
Subject | Re: [HACKERS] new heap manager mmalloc |
Date | |
Msg-id | m106EV8-000EBPC@orion.SAPserv.Hamburg.dsh.de Whole thread Raw |
In response to | Re: [HACKERS] new heap manager mmalloc (Tom Lane <tgl@sss.pgh.pa.us>) |
Responses |
Re: [HACKERS] new heap manager mmalloc
Re: [HACKERS] new heap manager mmalloc |
List | pgsql-hackers |
Tom Lane wrote: > > Bruce Momjian <maillist@candle.pha.pa.us> writes: > > Actually, our problem is not malloc itself. Most Unix OS's have pretty > > good malloc's, tuned to their OS. The problem is the number of times we > > call it. > > [...] > > What we need to do is exploit the notion of pooled allocation > (contexts), wherein the memory management apparatus doesn't keep track > of each allocation individually, but just takes it from a pool of space > that will all be freed at the same time. End of statement, end of > transaction, etc, are good pool lifetimes for Postgres. > > We currently have the worst of both worlds: we pay malloc's overhead, > and we have a *separate* bookkeeping layer on top of malloc that links > allocated blocks together to allow everything to be freed at end-of- > context. We should be able to do this more cheaply than malloc, not > more expensively. Right right right! Pooled allocation will gain performance and the separate bookkeeping should be more useful. I did some little hacking and placed a silly pool into palloc() and friends. It simply uses bigger blocks of memory for small allocations and keeps only a refcount in the block to see when all allocations are pfree()'d. No chunks inside a block are reused, instead it waits until the entire block is free to throw it away (what doesn't happen as often as it should). The blocks are allocated in the same memory context the chunks should have been, so transaction ends AllocSetReset() cleans them out anyway. It is a poor, simple way to reduce the number of palloc()'d segments, so it saves calls to malloc()/free() and reduces the bookkeeping overhead in AllocSet...(). The performance win on the regression test is about 10%. So it demonstrates that it's a good place for optimization. For now, it noticably raises the memory consumption of the backend. I think there are many small palloc()'d chunks not free'd, that cause my entier blocks to stay in memory. And since there is no reuse in a block, this summarizes up. This kind of pool is useful for things that should stay until transaction end. But I can think of another thing that might help. A temporary allocation pool stack. The functions to manage it are: void tmppalloc_push(void); void tmppalloc_pop(void); void *tmppalloc(Size size); void *tmpuppalloc(Size size, int levels_up); The stack does also handle the allocations in bigger blocks. But no individual free's are necessary, because the closing pop will throw away the innermost memory context. And since there are no free and realloc functions, it must not remember any information about the individual chunks. Could be a much bigger win for all our little allocs (I've seen thousands of 2-16 byte allocations when hacking in the above - with the old palloc(), every such has an additional overhead of 16 bytes in the AllocSet). Well, it requires us to revise the entire backend code, module per module, to look which palloc()'s could be changed into temp ones. But we'll find MANY places where memory isn't pfree()'d that nobody wants until transaction end. Jan -- #======================================================================# # It's easier to get forgiveness for being wrong than for being right. # # Let's break this rule - forgive me. # #======================================== jwieck@debis.com (Jan Wieck) #
pgsql-hackers by date: