开发者

Howto make image generation scalable on Java?

I'm trying to improve performance of captcha image rendering in web app running on Linux. Looking at what is currently used, I found that the bottleneck is in the usage of Java2D and specifically Graphics2D class.

The problem is not much with the speed of execution, but more with scalability. Basically it doesn't scale. Drawing of captcha images in 1 thread or 2 threads doesn't make any improvement in terms of execution time.

As an example, you can have a look at following class which is creating background for captcha images. The problem appears on calls to Graphics2D::setColor() and Graphics2D::drawLine():

http://www.docjar.com/html/api/com/octo/captcha/component/image/backgroundgenerator/FunkyBackgroundGenerator.java.html

After some googling and I found topic which says that Java2d is not particularly well with multi-threading (sorry, not allowed to give more than one link :) but, you can easily find that to开发者_JS百科pic if google for 'java2d multithreading', it will be the first result)

I believe that there must be some library which provides drawing capabilities withtout using Java2d, but failed to find it :( Or Java2d, probably, can be switched to some mode, which doesn't block on access to graphics object (btw, headless mode doesn't help).

I will appreciate any suggestions. Beforehand, thanks for answers.


There's not going to be a fast way to share a Graphics2D that works predictably because, unless you had a way to sync and reorder on each pixel, it'd be a massive race condition.

Anyway, your Graphics2D is backed by a BufferedImage so that's probably what's slowing you down. It's a non-accelerated surface so drawing is always going to be really slow. If your rendering server has the graphics hardware for it (it really should for an application like this) you can use a VolatileImage which is about an order of magnitude or two faster than a BufferedImage across the board in my experience.

Otherwise, you'll have to slice up your background generation into a grid, AffineTransform them so it all lines up, make the "randomness" common across all the grid elements by seeding it, stitch them back together afterwords and hope that the copyArea(...) method is fast enough to net you an improvement. I would almost say this is a kludge and hardware accelerated is the way to go.

You should also consider pre-rendering a large number of them offline and just serving them up as needed. That way the performance is more or less a non-issue unless you can't get in front of demand during the servers idle time (in which case you need new hardware either way and should just make a hardware accelerated rendering box).


Some optimisation ideas based on a brief look at your code:

  • You're creating a new BufferedImage for every captcha. I think you are better off keeping one BufferedImage and Graphics2D per thread in ThreadLocal variables and drawing over the previous captcha whenever you create a new one
  • You are doing a big loop over every pixel with a lot of computation for each pixel. You want to absolutely minimise the calculation done in the middle of this loop, e.g. do the constant calculations of "colorRightDown.getRed() / 255.0f" etc. outside the loop
  • Consider converting all the floating point calculations to equivalent fixed-point integer maths. This is usually slightly faster providing you can make everything fit in ints.
  • Use BufferedImage.setRGB() with integer colour values rather than Graphics2D.setColor with a new Color - it will be much faster and save you a lot of GC pressure
  • See if you can reduce the number of random number calls per pixel, I count 7 per pixel.... can you get away with less than that? You may be better creating a random integer and testing subsets of the bits.
  • Use width rather than getImageWidth() in your inner (i) loop, otherwise you are calling getImageWidth unnecessarily for every pixel. Same for the (j) loop, although it matters much less.

My guess is that the above combined will gain you far more than throwing extra processors at the problem..... :-)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜