QString: Allocating more than needed?

Stefan Heimers kde-optimize@mail.kde.org
Sun, 26 Jan 2003 13:23:15 +0100


Am Sonntag, 26. Januar 2003 11.27 schrieb David Faure:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On Sunday 26 January 2003 11:20, Stefan Heimers wrote:
> > - Is there a way to create qstrings with a fixed length, which
> > won't waste memory in case you know they will never grow?
>
> Yes, setLength().


I just had a look at the sources of Qt 3.1.1. It's in tools/qstring.cpp.

setLength() is not what I am looking for, but what I am complaining 
about. It allocates much more than needed, just in case the string 
might grow.

So memory is wasted on strings you know not to grow at all.

But the allocation has been made more modest since the discussion I 
quoted. SO the situation has improved, thanks to Trolltech!


Here is the function determining how much is allocated if you request a 
length of len with setLength();

static uint computeNewMax( uint len )
{
    uint newMax = 4;
    while ( newMax < len )
	newMax *= 2;  // here the next power of two is requested
    // try to save some memory
    if ( newMax >= 1024 * 1024 && len <= newMax - (newMax >> 2) )
	newMax -= newMax >> 2;
    return newMax;
}

What I would like to see is a function like setAbsLength() which would 
allocate exactly the number of characters you request.

In addition to allocating too much, the above function does waste quite 
a few cpu cycles.

The power of two approach is making allocation more efficient as long as 
you use less than one page of memory. If you have a large chunk of 
data, you just want to allocate a number of pages. The amount of memory 
doesn't need to be a power of two.

What about the following replacement for computeNewMax( uint len )? (not 
tested!)

static uint computeNewMax( uint len )
{
    uint newMax = 4;
    uint pages;

    if (len > (2*PAGE_SIZE) )
     {
      // for large data allocate the next larger number of memory
      // pages, no cpu intense iteration needed to find the
      // next power of two
      pages = len / PAGE_SIZE + 1;
      newMax = PAGE_SIZE * pages;
     }
    else
     {
       // small number, power of two makes sense, not many
       // iterations are needed, so let's go
       while ( newMax < len )
	 newMax *= 2;
      // or does someone know of a faster way to find the next
      // larger power of two?
     }
    return newMax;
}

PAGE_SIZE might be the real memory page size of the operating system, or 
any reasonable power of two, eg. 1024.

You could even do it more fancy by detecting memory installed and cpu 
speed, and then decide to optimize for memory usage (just allocate what 
is requested, not more) or cpu usage (allocate much, using a simple 
algorithm to determine needed size) 


Some pseudo-code:


if (mem < 40MB)
 only_allocate_whats_requested();
else if ( mem < 100MB && cpu > 100MHz)
 do_some_fancy_determining_of_optimal_overallocation();
else
 allocate_generousely();

Stefan