Re: WIP: Faster Expression Processing v4
Andres Freund <andres@anarazel.de>
From: Andres Freund <andres@anarazel.de>
To: Douglas Doole <dougdoole@gmail.com>
Cc: Heikki Linnakangas <hlinnaka@iki.fi>, Tomas Vondra <tomas.vondra@2ndquadrant.com>, pgsql-hackers@postgresql.org
Date: 2017-03-14T22:16:48Z
Lists: pgsql-hackers
Hi, On 2017-03-14 22:03:45 +0000, Douglas Doole wrote: > I do have one observation based on my experiments with your first version > of the code. In my tests, I found that expression init becomes a lot more > expensive in this new model. (That's neither a surprise, nor a > concern.) I suspect that's to a good degree because back then it'd often end up trying the "new" stuff, but then fall back to the old machinery due to unsupported operations. Which isn't a concern anymore, because now there's full coverage. Otherwise the cost aren't, according to my measurements, higher than before, excepting that some stuff that happened at execution time is now happening during initialization. > In particular, the function ExprEvalPushStep() is quite hot. In my > code I made the following changes: > > * Declare ExprEvalPushStep() "inline". > * Remove the "if (es->steps_alloc == 0)" condition > from ExprEvalPushStep(). > * In ExecInitExpr(), add: > state->steps_alloc = 16; > state->steps = palloc(sizeof(ExprEvalStep) * es->steps_alloc); > > I found that this cut the cost of initializing the expression by about 20%. > (Of course, that was on version 1 of your code, so the benefit may well be > different now.) Hm. Right now ExprState's are allocated in several places - but we could easily move that to a central place. Have a bit of a hard time seing that that branch during *initialization* time is that expensive, especially given that previously we allocated a lot of memory separately too. > On Tue, Mar 14, 2017 at 11:51 AM Andres Freund <andres@anarazel.de> wrote: > > > > Hmm. Could we make the instructions variable size? It would allow packing > > > the small instructions even more tight, and we wouldn't need to obsess > > over > > > a particular maximum size for more complicated instructions. > > > > That makes jumps a lot more complicated. I'd experimented with it and > > given it up as "not worth it". > Back when I was at IBM, I spent a lot of time doing stuff like this. If you > want to commit with the fixed size arrays, I'm happy to volunteer to look > at packing it tighter as a follow-on piece of work. (It was already on my > list of things to try anyhow.) Yea, I think experimenting with that is a good idea. I just think this is complicated enough, and I don't want to add a whole lot more complexity for very debatable benefit. > > If we were to try to do so, we'd also > > not like storing the pointer and enum variants both, since it'd again > > would reduce the density. > From my experience, it's worth the small loss in density to carry around > both the pointer and the enum - it makes debugging so much easier. I found it annoying enough to print the instruction itself, due to the union - so printing the opcode using a function isn't too bad... Greetings, Andres Freund
Commits
-
Improve performance of ExecEvalWholeRowVar.
- 2f0903ea1965 10.0 landed
-
Remove unreachable code in expression evaluation.
- ad46a2aa79f9 10.0 landed
-
Faster expression evaluation and targetlist projection.
- b8d7f053c5c2 10.0 landed
-
Avoid syntax error on platforms that have neither LOCALE_T nor ICU.
- 457a44487328 10.0 cited
-
Add configure test to see if the C compiler has gcc-style computed gotos.
- bc18126a6bcb 10.0 landed
-
Improve regression test coverage for TID scanning.
- be6c3d19fd45 10.0 landed
-
Improve expression evaluation test coverage.
- ce38949ba23a 10.0 landed
-
Fix two errors with nested CASE/WHEN constructs.
- f0c7b789ab12 9.6.0 cited