Yes Samuel, Thanks for the response.
I completely agree, Once I saw this behavior and diagnosed it I switched form
something like this.
for(int nY=0; nY < 10; ++nY){
for(int nX=0 nX < 10; ++nX){
image.setPixel(nX,nY,color);
}
}
To something like this
uchar* pBits = image.bits();
int nBytesPerLine = image.bytesPerLine();
for(int nY=0; nY < 10; ++nY){
for(int nX=0 nX < 10; ++nX){
uchar * scanLine = pBits+nY*nBytesPerLine;
((uint *)scanLine)[nX] = color;
}
}
And saw an 800x improvement. Even though this is still not optimal, it was well
within the performance profile I required.
I tried to avoid the QImage::scanLine() method since it too contains a detach()
call. (see my discussion of the double detach in setPixel())
The other thing not to miss is that when I was monitoring the
qt_gl_clean_cache() call, I would see it called by Qt as part of their internal
Backing Store machinery. A simple switching of tabs on a tab widget in my
application invoked 1800 calls to this (very expensive) method. And just
dragging your mouse across widgets causes this to be called a tremendous amount
too.
If you don't mind me asking. What is the exact purpose of this Texture Cache ?
Heath.
-----Original Message-----
From: Samuel Rødal [mailto:[EMAIL PROTECTED]
Sent: Wednesday, June 25, 2008 12:57 AM
To: Heath Feather
Cc: [email protected]
Subject: Re: [Qt4-preview-feedback] QImage::setPixel() Huge performance problem
caused by detach() and qgl.cpp::qt_gl_clean_cache()
Heath Feather wrote:
>
>
> Massive perfomance hit in Qt's reference counting system caused by
> qgl.cpp:qt_gl_clean_cache().
>
>
>
> I was recently using the QImage::setPixel() function to populate a
> QImage , and discovered that it seemd to be extremely slow. Upon further
> inspection I found that it called the detach() function, which in turn
> eventually called a very strange qgl.cpp:qt_gl_clean_cache() function.
>
>
>
> When just one OpenGL texture is bound the performance of setPixel()
> drops from its already pretty poor performance , to about 100x slower.
> In fact any Qt operations which make use of the detach() method suffer
> this indignity. The more textures that are bound the more the
> performance hit increase.
>
>
>
> My little million QImage::setpixel() calls take 0.04 seconds when no
> OpenGL textures are bound and 9 seconds when 5 textures are bound.
>
>
>
> If you take a look at the OpenGL Texture Cache architecture and the
> qt_gl_clean_cache() function in particular , you will note that it
> unrolls a QCache, creates a QList , depends on sprintf based Qstring
> keys , and then linearly runs through it doing substring comparisons.
> This seems like a function that was never expected to go into
> production, since it is extremely sub optimal, and all sorts of areas of
> Qt are ultimately suffering because of it.
>
>
>
> 1 million QImage::setPixel() calls .042 sec, with 5 OpenGL textures
> 8.8 sec (209x slower)
>
> 1 million QImage::setPixel() calls .042 sec, with 10 OpenGL textures
> 12.4 sec (295x slower)
>
> 1 million QImage::setPixel() calls .042 sec, with 50 OpenGL textures
> 26.5 sec (630x slower)
>
>
>
> I have attached a small program which exhibits the issue.
>
>
>
>
>
> List of Issues
>
> ==============
>
> QImage::SetPixel() calls detach() twice , once within itself, and ones
> via scanLine(); the second call via scanLine should be removed. Maybe an
> internal scanLine() method without the detach, such as the existing
> const version.
>
>
>
> qt_gl_clean_cache() maintains a QString based Hash, which is then
> decomposed into a list traversed linearly. This needs to be changed, the
> string based key is expensive to create , and then the linear traversal
> and QList is both odd and tremendously expensive.
>
>
>
>
>
> Qt4.4 Linux X86-64, also in earlier versions such as Qt4.3.3
>
>
>
> Thanks,
>
>
>
> Heath Feather
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Qt4-preview-feedback mailing list
> [email protected]
> http://lists.trolltech.com/mailman/listinfo/qt4-preview-feedback
Hello Heath,
indeed, setPixel() seems to be unnecessary slow, and we will look into
ways of optimizing the qt_gl_clean_cache() function to avoid this huge
additional cost when textures are bound. However, setPixel is arguably
not the best choice when doing pixel manipulation both due to the extra
function call and the repeated work that needs to be done there. If
performance is a concern I would recommend you to use the scanLine() or
bits() function to reduce the number of function calls to once per row
of pixels or once for all the rows.
Regards,
Samuel Rødal
_______________________________________________
Qt4-preview-feedback mailing list
[email protected]
http://lists.trolltech.com/mailman/listinfo/qt4-preview-feedback