Re: Some regular-expression performance hacking
Tom Lane <tgl@sss.pgh.pa.us>
Attachments
- 0007-smarter-regex-allocation-2.patch (text/x-diff) patch 0007
I wrote: > However, in a different line of thought, I realized that the > memory allocation logic could use some polishing. It gives out > ten arcs per NFA state initially, and then adds ten more at a time. > However, that's not very bright when you look at the actual usage > patterns, because most states have only one or two out-arcs, > but some have lots and lots. Hold the phone ... after a bit I started to wonder why Spencer made arc allocation be per-state at all, rather than using one big pool of arcs. Maybe there's some locality-of-reference argument to be made for that, but I doubt he was worrying about that back in the 90s. Besides, the regex compiler spends a lot of time iterating over in-chains and color-chains, not just out-chains; it's hard to see why trying to privilege the latter case would help much. What I suspect, based on this old comment in regguts.h: * Having a "from" pointer within each arc may seem redundant, but it * saves a lot of hassle. is that Henry did it like this initially to save having a "from" pointer in each arc, and never re-thought the allocation mechanism after he gave up on that idea. So I rearranged things to allocate arcs out of a common pool, and for good measure made the state allocation code do the same thing. I was pretty much blown away by the results: not only is the average-case space usage about half what it is on HEAD, but the worst-case drops by well more than a factor of ten. I'd previously found, by raising REG_MAX_COMPILE_SPACE, that the regexes in the second corpus that trigger "regex too complex" errors all need 300 to 360 MB to compile with our HEAD code. With the new patch attached, they compile successfully in a dozen or so MB. (Yesterday's patch really did nothing at all for these worst-case regexes, BTW.) I also see about a 10% speedup overall, which I'm pretty sure is down to needing fewer interactions with malloc() (this is partially a function of having batched the state allocations, of course). So even if there is a locality-of-reference loss, it's swamped by fewer mallocs and less total space used. regards, tom lane
Commits
-
Suppress unnecessary regex subre nodes in a couple more cases.
- 4604f83fdfe0 14.0 landed
-
Improve memory management in regex compiler.
- 0fc1af174cf7 14.0 landed
-
Extend a test case a little
- b3a9e9897ec7 14.0 cited
-
Allow complemented character class escapes within regex brackets.
- 2a0af7fe460e 14.0 landed
-
Suppress compiler warning in new regex match-all detection code.
- 3db05e76f928 14.0 landed
-
Avoid generating extra subre tree nodes for capturing parentheses.
- ea1268f6301c 14.0 landed
-
Convert regex engine's subre tree from binary to N-ary style.
- 581043089472 14.0 landed
-
Fix regex engine to suppress useless concatenation sub-REs.
- cebc1d34e520 14.0 landed
-
Recognize "match-all" NFAs within the regex engine.
- 824bf71902db 14.0 landed
-
Invent "rainbow" arcs within the regex engine.
- 08c0d6ad65f7 14.0 landed
-
Make some minor improvements in the regex code.
- 4e703d67193d 14.0 landed
-
Display the time when the process started waiting for the lock, in pg_locks, take 2
- 46d6e5f56790 14.0 cited
-
README/C-comment: document GiST's NSN value
- 8facf1ea00b7 14.0 cited
-
doc: Mention NO DEPENDS ON EXTENSION in its supported ALTER commands
- 8063d0f6f56e 14.0 cited