Thread
-
Its not my fault. Its SEG's FAULT!
David Gould <dg@illustra.com> — 1998-04-02T08:44:48Z
> Maurice: > Sorry to bring bad news but it seems that the postgresql daemon is leaking > memory when building indices. > (When using electric fence it takes long enough to notice -:)) > > Anybody want to recommend a good freeware tool which helps to find memory > leaks? > Bruce: > Yea, as I reported earlier, it is probably all from the same place. I > used a pginterface C file do show it. I think we need Purify. > Vadim: > Chris Albertson wrote: > > > > This is just one example. ++Every time++ I do a SELECT where > > the expected result is a large number of rows I get a > > failure of some type. > > > > testdb=> select count(*) from tassm16 > > testdb-> where 15.5 < b_mag::float4 - (0.375 * (b_mag - > > r_mag)::float4); > > FATAL 1: palloc failure: memory exhausted > > testdb=> > > > > I can make Postgresql 6.3 fail every time. Just do a SELECT > > where the number of rows returned is > a few million. The > > 0.375 above is float8 and so server uses two float8 funcs to > calculate right op of '<' ==> 2 * palloc(8) for each row. > palloc(8) eats more than 8 bytes of memmory (~ 24): 2 * 24 = 48, > 48 * 1_million_of_rows = 48 Mb. > > This is problem of all data types passed by ref !!! > And this is old problem. I have been doing some thought about memory allocation in postgresql so the above messages are very timely (at least to me). I would like to discuss the idea of replacing the current scheme of explicit memory allocation and and deallocation from separate "MemoryDuration" pools with a conservative garbage collector. For more information about garbage collection in general and about the specific collector I am proposing see these urls: GC FAQ and links http://www.iecc.com/gclist/GC-faq.html Boehm-Weiser Collector http://reality.sgi.com/employees/boehm_mti/gc.html Rationale: >From my experience, I think that this is a stone cold win for postgresql. I have of course, no before and afternumbers (yet) to back this up, but the following are I think true: - MemoryDuration is really "poor mans garbage collection" anyway. The idea being that it is either a) hard, or b) impossible to arrange to free your memory at the right time. Some objects need to last for a session, some for a transaction, some for a statement, some for a function, and some for other indeterminate durations. The duration mechanism is meant to help free things at the right time. Arguably it almost but not quite works. - MemoryDuration adds complexity to the code. A quick skim of the code base will show that duration gets switched all over the place often for not very obvious reasons. An example is a function allocateing working memory (per function duration) and returning an allocated result (per statement duration). This makes writing both server code and extension code much harder than need be. - MemoryDuration is very costly in terms of space: a) A function returning an allocated object returns memory that cannot be freed until the end of the statement. But as observed, often this memory is really needed only "per row". When millions of rows are involved, this gets pretty piggy (they just don't make swap partitions big enough...). b) Each chunk of allocated memory has overhead of 8 to 16 bytes of bookkeeping overhead to link it to the MemoryContext structure that controls the duration. This is in addition to whatever overhead (often 8 bytes) imposed by the underlying malloc() for boundary tags or size and arena information. Each allocation then has 16 to 24 bytes of overhead. The statistics I have seen for a derivative of postgres say that 86% of all allocations are 64 bytes or less. 75% are 32 bytes or less, and 43% are less than 16 bytes. This suggests that allocator overhead about doubles the storage needed. c) But it is really quite a lot worse than this. As noted above, memory is not freed for reuse in a timely way but accumulated until the end of the memory duration (ie statement or transaction). This is the usual reason for running out of memory in a large query. Additionaly, the division of memory into separate pools creates extra fragmentation which can only make matters even worse. - MemoryDuration is very costly in terms of speed: a) Some profiling (with Quantify) I have done on a derivative of postgres show that for even simple queries return only one row like "select * from table where key = <unique_value>;" spend about 25% to 30% of their total execution time in malloc(), free(), or one of the MemoryContext routines. This probably understates the case since it is based on instruction counting, not actual time and the "chase a big list of pointers" operation in MemoryContextDestroy() is almost guaranteed to have nasty cache behavior. b) There is quite a bit of bookeeping code all over the system (to support releaseing memory after an error etc). This is in heavily trafficced paths. Since is so widely distributed it is very hard to measure the slowdown, but there certainly is some. This could all be removed if we had garbage collection (although this in itself would be a big job). - MemoryDuration is very costly in terms of correctness and stability: I am not going to say much here except to point out the number of freed pointer errors and memory leaks that have been found in the code to date. And that there are new ones in every release. And that I have spent a good part of the last three years chasing leaks out of a similar system, and no, I am not done yet. The very existance of companies and products like Purify should be a tipoff. There is no practical way to write large C programs with dynamic storage without significant storage management problems. - MemoryDuration is very costly in terms of development cost: First, there are huge testing and debugging costs associated with manual storage management. This is basically all waste motion and a royal pain. Even more importantly, code written knowing that there is garbage collection tends to have about substantially fewer source statements. A typical case is a routine that allocates several things and operates on them and checks for failures: /* non garbage collected example */ dothing(...) { if ((p1 = malloc(...)) == NULL) return ERR; ... if ((p2 = malloc(...)) == NULL) { free(p1); return ERR; } ... if ((p3 = malloc(...)) == NULL) { free(p2); free(p1); return ERR; } ... if ((p4 = malloc(...)) == NULL) { free(p3); free(p2); free(p1); return ERR; } if ((info = do_the_wild_thing(p1, p2,p3, p4)) == ERR) { free(p4) free(p3); free(p2); free(p1); return ERR; } ... free(info) free(p4) free(p3); free(p2); free(p1); return OK; } /* same example only this time with garbage collection */ dothing(...) { if ((p1 = malloc(...)) == NULL) return ERR; ... if ((p2 = malloc(...)) == NULL) return ERR; ... if ((p3 = malloc(...)) == NULL) return ERR; ... if ((p4 = malloc(...)) == NULL) return ERR; ... if ((info = do_the_wild_thing(p1, p2,p3, p4)) == ERR) return ERR; ... return OK; } I know which one I would rather write! And it is fairly obvious which one is more likely to work. This is probably to long for one post, so I will stop now. I would very much like comments and suggestions on this topic, especially if this is something you have thought about or have experience with. Unsupported assertions to the effect "GC is too slow ... only works with lisp ..." etc are ok too, but will be eligible to win valuable prizes. -dg David Gould dg@illustra.com 510.628.3783 or 510.305.9468 Informix Software (No, really) 300 Lakeside Drive Oakland, CA 94612 "A week of coding can sometimes save an hour of thought." -
Re: [HACKERS] Its not my fault. Its SEG's FAULT!
Tom Ivar Helbekkmo <tih@hamartun.priv.no> — 1998-04-02T18:01:30Z
dg@illustra.com (David Gould) writes: > I would like to discuss the idea of replacing the current scheme of > explicit memory allocation and and deallocation from separate > "MemoryDuration" pools with a conservative garbage collector. Yes! This is a great idea! [scrambles, grinning, to finally get to work on porting the Boehm-Weiser collector properly to NetBSD/* 1.3] It seems, from recent discussion, reasonable to assume that this will kill a number of bugs, reduce the memory footprint of the backend and quite possibly even (judging by the profiling data you quote) give a welcome performance boost. Will you be doing some trial runs with Boehm-Weiser simply linked in as a malloc/free replacement? Is it a big project to actually rip out the MemoryDuration allocator's guts to get rid of some of that overhead? > I know which one I would rather write! And it is fairly obvious > which one is more likely to work. Of course, this one [he said, grinning]: (define (do-thing) (with-handler my-handler (do-the-wild-thing))) > Unsupported assertions to the effect "GC is too slow ... only works > with lisp ..." etc are ok too, but will be eligible to win valuable > prizes. ...like a guide to documents on the net debunking these and other favorite misconceptions about garbage collection? You're hardly likely to get too many of those assertions, though: by now, I would assume that it's gotten through to most programmers that the handling of memory in a large system can be done more reliably _and_ more efficiently by a good garbage collector than by a C programmer. The fact that the Java designers got this right (no surprise, of course, with Steele at the core), should by itself have convinced many. Off-topic: as for Java, we now just have to wait for the byte-code engine and entire run-time support system to be rewritten in Java, so that we can get a stable deployment platform for Java on the web that won't crash the user's browser every other time she loads an applet! -tih -- Popularity is the hallmark of mediocrity. --Niles Crane, "Frasier" -
Re: [HACKERS] Its not my fault. Its SEG's FAULT!
David Gould <dg@illustra.com> — 1998-04-03T07:25:16Z
Tom Ivar Helbekkmo writes: > dg@illustra.com (David Gould) writes: > > > I would like to discuss the idea of replacing the current scheme of > > explicit memory allocation and and deallocation from separate > > "MemoryDuration" pools with a conservative garbage collector. > > Yes! This is a great idea! [scrambles, grinning, to finally get to > work on porting the Boehm-Weiser collector properly to NetBSD/* 1.3] This is exactly the kind of thoughtful response I was looking for ;-) > It seems, from recent discussion, reasonable to assume that this will > kill a number of bugs, reduce the memory footprint of the backend and > quite possibly even (judging by the profiling data you quote) give a > welcome performance boost. Will you be doing some trial runs with > Boehm-Weiser simply linked in as a malloc/free replacement? Is it a > big project to actually rip out the MemoryDuration allocator's guts to > get rid of some of that overhead? Not too big, just redefine palloc and make the Context calls into no-ops. A bit more trouble to track down all the 'malloc()' calls that shouldn't have ever been there (but there are quite a few). > Of course, this one [he said, grinning]: > > (define (do-thing) > (with-handler my-handler > (do-the-wild-thing))) Sure, but right now we have some few hundred thousand lines of C... > > Unsupported assertions to the effect "GC is too slow ... only works > > with lisp ..." etc are ok too, but will be eligible to win valuable > > prizes. > > ...like a guide to documents on the net debunking these and other > favorite misconceptions about garbage collection? You're hardly I had meant to say "not be eligible" but I like your idea better. Both urls I posted have a bunch of very fine links to a lot of really good information. > likely to get too many of those assertions, though: by now, I would > assume that it's gotten through to most programmers that the handling > of memory in a large system can be done more reliably _and_ more > efficiently by a good garbage collector than by a C programmer. The It is surprising, but this simple fact has not yet penetrated into popular thought. I have seen large organizations full of very bright people spend hundreds of man years chasing leaks without ever wondering if there might be an alternative. For some reason people cling to the belief that if they were just careful enough and only let really good programmers touch the code and carried a lucky rabbits foot that somehow they could write leak free software. All this in the face of the observation that no-one ever actually _writes_ leak free software. Personally, I don't know anyone who can write leak free software of any size, certainly not in a finite time. -dg > David Gould dg@illustra.com 510.628.3783 or 510.305.9468 Informix Software (No, really) 300 Lakeside Drive Oakland, CA 94612 "A week of coding can sometimes save an hour of thought."