Dominik Seichter wrote:

> Regarding the pool memory which has to be free'd explicitly with
> boost::singleton_pool<boost::fast_pool_allocator_tag, 
> sizeof(TRefCountedBuffer)>::release_memory(). Maybe it is time to add 
> podofo_library_init() and podofo_library_free() method (or something similar) 
> which can be used by applications to clear any allocated memory in pools from 
> PoDoFo.

I tend to agree with that. I need to look into whether it's safe to then 
continue using the singleton allocators (say, after another 
podofo_library_init()) though, or whether that closes things down for 
the life of the process.

> I just played a bit with ParserTest and callgrind. For the PDFReference I get 

A side note: Are you familiar with the `massif' tool of Valgrind? Very 
impressive. It generates a mapping of memory allocation hotspots and a 
nice graph showing proportionally how much memory was allocated in the 
various places.

> 3 647 953 calls to new from PdfVariant::operator=
> 1363133   calls to new from   __gnu_cxx_new_allocator<PdfObject)::allocate
> 2285072   calls to new from   std::string::_Rep_S_create
> 1453340   calls to new from   
> __gnu_cxx_new_allocator<std::_Rb_tree_node<std::pair<PdfName,PdfObject*>>::allocate
>  
> (i.e. PdfDictionary::AddKey)
> 893477    calls to new from PdfDictionary::operator=
> 
> new is the function called most after malloc and free, but I guess this is 
> because new uses malloc internally.

Well, and because PoDoFo uses malloc directly in a quite a lot of places.

BTW, while I haven't confirmed this in detail the libstdc++ docs say 
that it actually caches memory internally, so not every call to operator 
new() necessarily results in an underlying memory allocation from the C 
library. If that's the case, it might well explain why we're not seeing 
much of a benefit from the Boost memory pools - though I'd expect them 
to at least be faster (by virtue of their specialization) than the 
method new() is using. libstdc++'s allocation behavior has changed many 
times though, so who knows how up to date the docs are.

> I see that this is a very special test and very different from creating a 
> PdfFile or working with streams. But I think we coulg gain more from a 
> PdfVariant and PdfObject allocator. Maybe also from a pool for 
> std::_Rb_tree_nodes.

One of the very nice things about the boost pool library is how easy 
that is to do.

If you have:

std::map<K,V>

you can write:

#if defined(HAVE_BOOST)
typedef boost::fast_pool_alloc<std::map<K,V>::value_type> MapAllocator;
#else
typedef std::allocator<std::map<k,V>::value_type> MapAllocator;
#endif
std::map<K,V,MapAllocator>

This works, for example, in PdfDictionary.

It's even easier for single value containers (like PdfArray). All that 
changes for bulk-allocating containers is that you use pool_alloc rather 
than fast_pool_alloc, and nothing at all changes for individually 
allocating containers like std::list .

I suspect, though, that gcc's libstdc++ is doing such a good job with 
the existing allocator functions that we're not going to see as much 
benefit as I initially thought.

I'm particularly confused about the lack of benefit for the two 
*incredibly* common classes TRefCountedBuffer and PdfReference. 
Especially PdfReference, which is tiny and allocated in huge numbers, 
should benefit from using the pool allocator - yet in tests I see little 
change.

I need to do some testing on Windows, too, but that's harder due to the 
fact that I don't have the same sort of tools available.

--
Craig Ringer

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Podofo-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/podofo-users

Reply via email to