[poppler] [PATCH] ~10% speedup for loading/parsing a PDF file through simple GooString optimization

Krzysztof Kowalczyk kkowalczyk at gmail.com
Sun Aug 13 21:03:33 PDT 2006


On 8/12/06, Jeff Muizelaar <jeff at infidigm.net> wrote:
> On Mon, Aug 07, 2006 at 11:08:19PM -0700, Krzysztof Kowalczyk wrote:
> It would be interesting to see where the majority of the allocations are
> happening as well as what we are actually doing with the strings. It
> might be worth adding an immutable string type that is always a single
> allocation regardless of it's length.

Looking at the profile data, it looks like a lot of allocations are
due to copying between instances of Object that are obtained from
Lexer::getObj(). The best solution would probably be to rework
Lexer::getObj() and its callers to not do copying.

However, the code is very undisciplined about how it copies data
(sometimes it's the expensive, deep copy, sometimes it's a shallow
copy that just copies data like Object obj = *objOrig). Given that
it's hard to make a change without breaking stuff. My attempt at a
simple change like making Object::string an embedded value instead of
a pointer failed and I don't even understand why.

What makes it even harder is that Object is a polymorphic type and
copying obj1 of type objCmd into obj2 of type objString, requires
freeing the string data and copying the string for cmd.

So there isn't a simple change that I can see that would help.

My next step is to try a custom memory allocator that speeds up
allocation of small objects. This is not ideal solution (it's best to
eliminate unnecessary work instead of trying to make unnecessary work
go faster) but should reduce the number of malloc()/free() calls
without changing a lot of code.

Reference counting of Object (plus a lot of changes) would probably
help as well. Going even further, dynamic languages (like lisp,
smalltalk etc.) spent a lot of time trying to optimize the problem of
efficient implementation of polymorphic objects so borrowing some
ideas (like e.g. tagged pointers) could lead to even more speed
improvements.

Another big area of improvement would be Stream implementation.
Currently e.g. Lexer::getChar() is at the top of the profile while the
time spent actually reading the file doesn't even register. Those
layered virtual calls hurt a lot.

-- kjk | http://blog.kowalczyk.info


More information about the poppler mailing list