0

I am designing/developing a web application that will ultimately deploy as a WAR to Tomcat. One of the features of this application will be the ability for users to upload images to our server and edit them (generate thumbnails, etc.). Under the hood we will be using ImageMagick and its Java adaptor library IM4Java.

Initial prototypes have shown that ImageMagick takes some time to "warm up" on our servers every time we re-deploy the application. This has prompted us to consider one of two possibilities, either:

  • Create an ImageService.war web service that deploys alongside the primary app and basically handles all calls to IM4Java under the hood (exposes, say, a RESTful service and just runs ImageMagick when it receives a request; the primary web app cann then find the edited file(s) on the same local file system); or
  • Just create a Thread subclass (i.e. ImageServiceThread), kick it off and run it at deploy-time, and make sure it gets shut down when Tomcat undeploys the app

These two prospects got me thinking about this problem in a more abstract sense: when should one simply delegate work out to a separate thread, and when is it appropriate to make a full-blown, separate app (in our case a WAR)?

Our primary app will be the only user of this "Image Service", which has me thinking a separate WAR is overkill and unnecessary. But I've never dealt with threading inside of Tomcat before and am not sure if it is possible to spawn and kill a thread so that its lifecycle coincides with that of the primary/main app thread.

What sort of factors should be considered as part of such a decision? Thanks in advance.

IAmYourFaja
  • 55,468
  • 181
  • 466
  • 756
  • How often do you expect to actually redeploy in production? Seems like a lot of maintenance hassle to save some irritation in development. – Affe Jun 15 '12 at 18:15
  • 4-week sprints so monthly production releases and usually 2 - 3 QA builds for each production release – IAmYourFaja Jun 15 '12 at 18:16
  • 1
    Just as a comment to your last part, it's quite easy to spawn a thread or similar and terminate it in a ContextListener - you almost always want to manage threads inside tomcat in a context listener (terminating it in the contextDestroyed and starting it in the contextInitialized methods). Finally, use an Executor in place of creating your own Threads. – nos Jun 15 '12 at 18:53
  • It's strange that IM "takes some time to 'warm up'" because IM4Java always launches separate processes for IM tasks, so the only reason I can think of for any delays would be the OS swapping memory. – Christopher Schultz Jun 15 '12 at 21:05
  • Thanks @Chris - can you elaborate further on the last comment about OS "swapping memory"? What do you mean by that? – IAmYourFaja Jun 15 '12 at 21:17
  • IM processes run entirely separate from the JVM and from other invocations: it's just like running 'ls': once the work is done, the process ends and you have to start a new one if you want to run it again. If IM uses lots of libraries or something, the OS can cache a lot of that in memory so that subsequent program-launches can be faster. Launching another process also causes a context-switch (the OS focuses on a different process and gives CPU time to it) and in low-memory situations, competing concurrent processes can cause thrashing where the OS does more switching than actual work. – Christopher Schultz Jun 15 '12 at 21:33

2 Answers2

1

ImageMagick takes some time to "warm up"

Its better to offload memory/cpu intensive operations outside of your servlet container. In fact, launch your image service in a separate JVM.

Since your application will be loading images in memory and edit them, you can expect frequent Garbage collection that will impede with the performance of the servlet container there by affecting the performance of other parts of your the web application.

sperumal
  • 1,499
  • 10
  • 14
1

Definitely keep the pre-loading of ImageMagick in the web application that requires it to run properly. That way, you won't ever forget that the two webapps should be deployed together.

It's a good idea to keep everything a particular webapp requires together in one place: that's why the WAR format was created and things such as ServletContextListeners exist.

Honestly, I'm not sure I would bother to "thread" the pre-loading of IM at all -- just run some sample command from a ServletContextListener and have it load synchronously.

Christopher Schultz
  • 20,221
  • 9
  • 60
  • 77
  • So if I understand you correctly, you're voting in confidence of a separate thread for pre-loading IM, but one that is still inside the same WAR as my main web app, right? – IAmYourFaja Jun 15 '12 at 21:18
  • I would do it in your "main" webapp, and I wouldn't bother using a separate thread at all: just launch some simple IM task from within your `ServletContextListener` and wait for it to complete before allowing the webapp to come up fully. – Christopher Schultz Jun 15 '12 at 21:34