optimizing performance in my application

Magick++ is an object-oriented C++ interface to ImageMagick. Use this forum to discuss, make suggestions about, or report bugs concerning Magick++.
Post Reply
tsftd
Posts: 28
Joined: 2012-01-14T11:46:55-07:00
Authentication code: 8675308

optimizing performance in my application

Post by tsftd »

Okay, so I have a working and nearly feature complete application. At this point, I'm beginning to work on optimization rather than just getting it to do what I want. FYI, I'm not a professional programmer, but have worked on and off with Magick++ for several years.

What the program does, in a nutshell, is batch-create images for use in education. Primarily flashcards, but it can also do things like convert said flashcards into smaller cards for use in games, or bingo sheets, or simple (e.g. Snakes & Ladders) boardgames. Basically, it reads an INI file (and optionally, commandline arguments) and makes the (overall image) canvas, then it will create an additional layer, stick text/images/draws onto that layer, and paste the layer onto the canvas. Rinse and repeat. So, for instance, to make the small cards, it will make a canvas, then draw a grid onto it (as a cutting aid and border for the cards), and then paste the images into the appropriate places between the guides.

I have internally threaded most operations, as I found that there were some things that Magick++ didn't thread. So just about everything runs in concurrence, only pausing for threads to end when syncing is required.

My main query is how to improve the performance of the Magick++ side of things. For instance, I'm using annotate to draw my text; is this the most efficient method for doing so, or would draw be faster? When I'm, for example, composeing a small layer onto a (relatively) small section of the main image, would it be faster to use the pixel cache, or would the overhead of initializing it outweigh any performance gains? Would converting the Image to a blob help (currently, I only use Images)?

The basic workflow is:
Image canvas(dimensions,background color);
Image layer;
while(layer deque.size()>0){
layer=Image(layer dimensions,layer background color);
for(loop=0;loop<elements deque.size();loop++){
if(elements deque[loop]=="Image")
//load that image from disk and trim and/or resize and/or rotate it, then compose it onto the layer
else if(elements deque[loop]=="text")
//annotate that text onto the layer
}
canvas.compose(layer);
layer deque.pop_front();
}
canvas.write("filename.png");

It's obviously more complicated than that (and threaded), but that's the idea.

Note that this is running on a powerful server (overclocked 6-core/12-logical i7, 16gb ddr4 -- soon to be upgraded to 32gb, 4 Samsung SSD raid 10), so I'm happy to make memory-for-speed tradeoffs, though disk access should be a minimal issue. When I go up to 32gb, I may well end up making a ramdisk to hold all of the input/output files (they don't need to be permanent, this is just the backend to a php frontend), in which case disk access will become a completely null point. And finally, while obviously the input images may be of any dimension (prior to resize), the output images are NOT extremely high resolution. These are intended for classroom use, e.g. printed onto a4/a3 paper, so 1260x1782 or so is typical. Not low resolution by any means, but not super-megapixel professional photographs by any means.

I'll also be compiling a customized magick++ (@q8), but that's the last step.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: optimizing performance in my application

Post by snibgo »

Even without a disk, reading and writing files takes CPU time, especially when there is compression, so thinking about this is probably worthwhile.

For example, writing graphics to PNG, I get a 5:1 ratio of slowest vs fastest, depending on compression method. See my "Outputs: speed and size" page, though my timings include disk.

If you need to write temporary results, mpc or miff is generally quicker than other formats.
snibgo's IM pages: im.snibgo.com
tsftd
Posts: 28
Joined: 2012-01-14T11:46:55-07:00
Authentication code: 8675308

Re: optimizing performance in my application

Post by tsftd »

Thanks, I write the pngs out with no compression (I use an external optimization program) -- and only write the image out once, when it is fully processed. That is to say, I can tell the program "make a flashcard for each image in folder X", and it will write as many images (flashcards) as are in folder X, but each output is written only pnce, when it is complete.

I assume that magick++ isn't disk writing without my knowledge? I seem to recall a cache setting, but I tgink that it defaults to a large enough number?
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: optimizing performance in my application

Post by snibgo »

If IM can't get enough memory for pixel caches, it will use disk instead, which is massively slower (of course). Users sometimes finds this happens unexpectedly, and it turns out their sysadmin has configured limits on memory per process or per user.
snibgo's IM pages: im.snibgo.com
tsftd
Posts: 28
Joined: 2012-01-14T11:46:55-07:00
Authentication code: 8675308

Re: optimizing performance in my application

Post by tsftd »

I don't explicitly use pixel caches, are they used implicitly as part of the internal functions? And if so, then cacheThreshold should let me set it high enough to eliminate paging? FYI, I'm on Win10x64 (my Linux server is not nearly as beefy), compiling as 64-bit, and have no limits on mem use.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: optimizing performance in my application

Post by snibgo »

Pixel caches are implicit. See http://www.imagemagick.org/script/architecture.php

I don't use Magick++ much, but I assume it's like the other interfaces: IM doesn't limit it's own use of memory unless you tell it to.
snibgo's IM pages: im.snibgo.com
Post Reply