PDA

View Full Version : Graphics view with millions of items



JovianGhost
21st March 2010, 02:48
I'm writing an app that could potentially have to render MILLIONS of items. I did a quick test, drawing exactly 1,000,000 items, and the app REALLY slowed down, and ate up quite a bit of memory (500MB according to Task Manager.) This is very bad, since I may have to potentially load data with multiple millions of items.

The thing is, these items I'm rendering are extremely simple-- a small filled square, the dimensions of which can range from 1px up to 20px, possibly more-- basically just scaled pixels. So I don't know if I necessarily need the overhead of QGraphicsView and/or QGraphicsItem, (I assume these classes are eating up all the memory) since rendering these squares will be very easy.

I need the memory usage to be as low as possible, but the app has to be fast. I was thinking of writing the boxes to a separate device context then blitting the whole thing at once to the render area.

Would I be able to do this manually? I'm going to need the ability to scroll and zoom, but I notice that QAbstractScrollArea doesn't have any scaling ability-- I suppose I'd have to implement that myself.

Does anyone have any suggestions?

Lykurg
21st March 2010, 08:12
QraphicsView should be perfect for you. Search the forum for increasing the performance. (e.g caching, update mode...) An you can also have a look at 40000 Chips example.

JovianGhost
22nd March 2010, 01:50
QraphicsView should be perfect for you. Search the forum for increasing the performance. (e.g caching, update mode...) An you can also have a look at 40000 Chips example.

I looked around the forums but didn't find anything terribly useful. Not to mention that this is not just a performance issue but also a memory usage issue.

I've already taken a look at the 40,000 Chips example, but it too suffers from performance issues with large numbers of items. I tried boosting the number of items to add to the scene, and it choked when I went to 640,000 which is quite a bit less than what I hope to add in my program. Not to mention the memory usage is 315MB, which is way too high.

My goal is to write a replacement for a program that already exists. The program works decent except that it's very buggy, very slow and nobody is maintaining it-- also, it's written in MFC (yuck.)

So I tried loading in the same dataset into both programs, approximately 250,000 items. In my program, written with Qt using QGraphicsScene et al, the memory usage is ~132MB. Using the program I'm replacing, which appears to render each item to a background device context and then blit it into the screen, the usage is less than 12MB! That's pretty damned efficient.

This is why I'm thinking that I should forego the extra overhead required by Qt's built-in graphics classes, and try handling it myself. It sounds pretty painful, having to reinvent the wheel as I most likely will have to, but at this point I don't see much choice.

JovianGhost
22nd March 2010, 02:40
Ok, well here's what I tried so far, without any visible effect:

- Passing "-graphicssystem raster" and "-graphicssystem opengl" in the command-line
- Setting the cache mode on the GraphicsView to CacheBackground
- Setting the optimization flags on the GraphicsView
- Setting different render hints on the GraphicsView

None of these seemed to have any effect when operating on 250,000 items.

Any other suggestions?

JovianGhost
24th March 2010, 12:02
*bump*
Any suggestions?

JohannesMunk
24th March 2010, 12:17
Why do you need that much items? Can't you merge them into groups? Render an approximation for the group. And divide them only if necessary?

If your individual items are complex in design you could consider using openGL and displaylists for the basic shapes, which you then call as often as you have that item-type.
You won't be able to generate millions of displaylists though. So this only works if you have considerably less types, than items.

Can't you provide a screenshot of your working MFC application, so that we have more of an idea, of what you want to achieve?

Johannes

pherthyl
24th March 2010, 16:23
First of all, yes, you most likely don't need to create one QGraphicsItem for each item. It's not the fault of QGraphicsView, it's just a fundemental limitation of trying to create millions of any object. You will have a fixed overhead for each object, and if you multiply that fixed overhead (I don't know what it is, but you can imagine with each item holding a rectangle, a brush, a pen, etc that it is several dozen bytes at minimum) you get huge memory usage.

So if you are just visualizing the data, then the obvious solution is just to draw your items directly.

However, you might still be able to take advantage of the scrolling and zooming you get from the QGraphicsView.

Have a look at QGraphicsScene:: drawBackground()

You should paint your boxes there. You can use the CacheBackground flag to avoid unnecessary repaints.

pherthyl
24th March 2010, 16:48
sizeof(QGraphicsItemPrivate) returns 280, plus 8 for an QGraphicsRectItem. I'm probably missing some other parts, but basically a million items will take at least 267MB for the items alone.

JovianGhost
25th March 2010, 02:18
Thanks everyone, but I've decided to do the painting manually with QPainter and/or low-level WINAPI calls. There's just too much overhead involved in using Qt's built-in graphics management framework.

wysota
25th March 2010, 09:12
There's just too much overhead involved in using Qt's built-in graphics management framework.

Maybe you should first find the bottleneck instead of trying to fix random things? I've seen the chips demo running decently with 1 million items and it was in the "old days" when graphics view was not that much optimized yet.

After reading this thread I'm leaning towards an opinion that Graphics View is not for you (but rather because of the memory footprint, not the speed) but not because of the reasons you mentioned. It would help to make a decision if you showed us what the application is meant to be doing.

http://labs.trolltech.com/blogs/2006/08/30/4-million-items-is-it-really-possible/

JovianGhost
26th March 2010, 01:04
Maybe you should first find the bottleneck instead of trying to fix random things? I've seen the chips demo running decently with 1 million items and it was in the "old days" when graphics view was not that much optimized yet.

After reading this thread I'm leaning towards an opinion that Graphics View is not for you (but rather because of the memory footprint, not the speed) but not because of the reasons you mentioned. It would help to make a decision if you showed us what the application is meant to be doing.

http://labs.trolltech.com/blogs/2006/08/30/4-million-items-is-it-really-possible/

I'm not just fixing random things. I've been trying to find the bottlenecks and the only conclusion I can reach is that it's the graphics framework overhead. I've just implemented what I need to using bare-bones QPainter in the paintEvent function and it's very fast and uses very little memory compared to before.

Unfortunately I can't show what the app is doing, since it's IP of my company.

wysota
26th March 2010, 02:43
I'm not just fixing random things. I've been trying to find the bottlenecks and the only conclusion I can reach is that it's the graphics framework overhead.
If "fixing" didn't help then obviously that what you tried to fix wasn't a bottleneck.

JovianGhost
26th March 2010, 23:29
If "fixing" didn't help then obviously that what you tried to fix wasn't a bottleneck.

Exactly. There's no way to fix the bottleneck, because the bottleneck is the framework itself. There's no way to use the framework whilst maintaining low memory usage. The whole point of the framework is so that it's easy to work with and provides a simple interface to the developer. But all this comes at a price-- the overhead.

wysota
26th March 2010, 23:58
There's no way to fix the bottleneck, because the bottleneck is the framework itself.
And you base this statement on what exactly?