optimizing performance in my application
Posted: 2016-11-07T18:39:04-07:00
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.
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.