2

I have a Java application which does the following:

  1. Tool takes a document which it will parse.
  2. Tool calls external webservice
  3. Tool completes execution

However, when I tried to run this application in two different 'environments', there is a huge gap between the performance of the tool. On the first environment, it takes only 30 seconds, while on the second tool, it took 40 minutes.

An environment consists of the following:

  1. The machine the app runs on.
  2. The connection to the webservice.
  3. The input document that will be parsed by the tool.

I have been in constant communication between the people on the second environment (40 minute execution), and I am quite stumped.

I am trying to isolate the issue. First, I asked the specs of the machine that they are using and that seems to be fine. I then asked their connection to the webservice and it is okay too.

The input document between the two environments (For this case), are the same; I kept it a constant variable so that I have less issues to check.

Weirdly enough, I asked for more information and found out that it takes a long time with the parsing of the input document. In the 40 minute execution, the tool was 'stuck' on the parsing for 38 minutes. I was thinking if it was my code, but I am quite confused that the first environment only took seconds to parse the same document.

The general structure of my parsing is as follows:

do{
   ... code here.
   do {
      ... code here.
      for{}
   }while
}while
for{}
do{
  ... code here.
}while

code here are mixtures of if statements and function calls (only one function is used though and it is just generally ifs, no loops).

I do know that nested loops take a while and this is worse than O(n^2) and I know I need to work on my optimization, but could it really be the code that causes this huge gap between performance or is there another factor that may cause this gap?

  • Have you asked for their available memory? Huge differences in performance can result if the code is thrashing on one machine but has enough memory on another. If that is the case, the remedy is to reduce your memory usage, of course. – cmaster Aug 26 '16 at 7:25
  • What you need is stack samples. If you can't interrupt it, perhaps something like jstack would work. If the slowdown is 80x, as you say, then each sample has a 79/80 chance of showing you exactly what the problem is. – Mike Dunlavey Aug 26 '16 at 17:46
0

The problem is likely memory based for the parsing. I would ask enough questions about both environments to replicate them with fresh VM's and see if I could find a similar difference between these VM's.

Once you have similar VM's then you can repeat the tests with slightly different specs in order to figure out if the issue becomes exacerbated most by memory, or processing power, or what. At that point you would have a bit of an idea on where to focus your energy during optimization.

2

While you did a good job at pinpointing the problem by determining that it comes from the parsing itself (and not, for instance, the calls to the web service), there is still work to do to find the actual bottleneck.

This is usually done with a profiler. Unfortunately, I imagine that you can't run a profiler in your case for two possible reasons: the distant environment is probably a production environment, and you may not be able to install whatever you want there; some profilers are targeting short pieces of code which perform in terms of seconds, rather than dozens of minutes.

What you can do, on the other hand, is to:

  • Completely isolate the parser code into a standalone Java app. This would ensure that you haven't missed some fancy call to a web service buried deep inside a loop.

  • Add debugging/benchmarking statements which will simply write the current time to a log file. When actually profiling code, this is not a good practice, since it doesn't give you enough precision (in actual profiling, microseconds often matter). However, when we are talking about 40-minutes execution, this should be precise enough.

  • Find the part which takes the most time (be careful with that, a method which takes 50 seconds and is executed once is much less important than a method which takes 5 seconds and is executed 100 times in a loop). From there, you may need, iteratively, to add other debugging/benchmarking statements within the slow block in order to get the actual line where the code is stuck for 38 minutes.

A slightly different approach is to use aspect-oriented programming (AOP) logging. Here's a good start. The idea is that instead of putting manually the debugging/benchmarking statements which will write the current time to the log file, you'll simply decorate the methods you want to measure, and let the AOP library do the actual work.

A positive side effect is that it would encourage you to refactor your do/while code block. Looking at your code, I'm not sure your method is actually doing one and one only thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.