7

Greets-

We gots a few nutters in work who enjoy using

while(true) { //Code } 

in their code. As you can imagine this maxes out the CPU. Does anyone know ways to reduce the CPU utilization so that other people can use the server as well.

The code itself is just constantly polling the internet for updates on sites. Therefore I'd imagine a little sleep method would greatly reduce the the CPU usage.

Also all manipulation is being done in String objects (Java) anyone know how much StringBuilders would reduce the over head by?

Thanks for any pointers

Steve
  • 21,163
  • 21
  • 69
  • 92
  • 4
    `while (true)` is simply an idiom that says "do this forever." By itself, it does nothing; the code within it is what consumes CPU cycles. If the code inside is making network requests, then it will give up its timeslice when doing so, so other users will get theirs; a `sleep()` should not significantly affect overall server throughput (although it'd be a nice thing for those servers that are getting hit by the program). And finally, `StringBuilder` may or (more likely) may not improve performance. But that's why profilers exist: they can tell you what's taking the most time in the program. – kdgregory Mar 28 '10 at 13:04
  • 3
    As always run a profiler to identify where the cpu goes. Then use that data to beat the responsible developer over the head. – Thorbjørn Ravn Andersen Mar 28 '10 at 13:11
  • 1
    For your 2nd question, note that the compiler _can_ optimize string concatenations using a StringBuilder in the bytecode. For details see this post: http://stackoverflow.com/questions/1532461/stringbuilder-vs-string-concatenation-in-tostring-in-java – Péter Török Mar 28 '10 at 14:15

9 Answers9

8

A lot of the "folk wisdom" about StringBuilder is incorrect. For example, changing this:

String s = s1 + ":" + s2 + ":" + s3;

to this:

StringBuilder sb = new StringBuilder(s1);
sb.append(":");
sb.append(s2);
sb.append(":");
sb.append(s3);
String s = sb.toString();

probably won't make it go any faster. This is because the Java compiler actually translates the concatenation sequence into an equivalent sequence of appends to a temporary StringBuilder. Unless you are concatenating Strings in a loop, you are better of just using the + operator. Your code will be easier to read.

The other point that should be made is that you should use a profiler to identify the places in your code that would benefit from work to improve performance. Most developers' intuition about what is worth optimizing is not that reliable.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
6

I'll start off with your second question, I would like to agree with the rest that StringBuilder vs String is very much dependent on the particular string manipulations. I had "benchmarked" this once and generally speaking as the amount of new string allocations went up (usually in the form of concatenations) the overall execution time went up. I won't go into the details and just say that StringBuilder turned out to be most efficient overtime, when compared to String, StringBuffer, String.format(), MessageFormat...

My rule of thumb is that whenever I wish to concatenate more than 3 string together I always use StringBuilder.

As for your first question. We had a requirement to bring CPU usage to 5%. Not an easy task. We used Spring's AOP mechanism to add a Thread.sleep() to before any method execution of a CPU intensive method. The Thread.sleep() would get invoked only if some limit had been exceeded. I am sorry to say that the computation of this limit is not that simple. And even sorrier to say that I still have not obtained the permission to post it up on the net. So this is just in order to put you on an interesting but complicated track that has proven to work over time.

Yaneeve
  • 4,751
  • 10
  • 49
  • 87
  • 6
    What possible reasoning could lead to a requirement of "no more than 5% CPU time"? If you have a CPU-intensive task, then you have a CPU-intensive task. There's no way around that, and adding sleeps to your code simply makes that task take longer. If you're concerned about a particular program's impact on overall system resources, then it's far more intelligent to simply reduce the priority of that program. Or buy another computer. – kdgregory Mar 28 '10 at 23:39
  • 1
    Personally, I couldn't agree with you more! Yet I am but a mere programmer and did not "engineer" this solution. My only point was that this type of thing COULD be done, if need be :) – Yaneeve Mar 29 '10 at 05:43
  • @Yaneeve .. Too late to ask this. How did you manage the tradeoff between speed and CPU usage ? I am sure , sleep had a performance impact as it increased the execution time. – bluelurker Nov 20 '15 at 08:32
  • 1
    @bluelurker it wasn't much of a balancing act. We were directed to control the maximum cpu usage not processing time. This meant that as long as we didn't start amassing a backlog we were in the clear. We ran load tests and saw that given the hardware and projected load we would be okay. I think the fact that most of our work aside from parsing and transformations of data was disk and network io helped a lot. We tried to insert sleeps only around cpu intensive parts not io. Since io is at least an order of a magnitude slower than cpu throwing lots of theads at io in the interm probably helped – Yaneeve Nov 21 '15 at 19:57
  • @Yaneeve.. That's interesting. – bluelurker Nov 24 '15 at 05:39
4

How often do those sites update? You're probably really annoying the hosts. Just stick a Thread.sleep(60 * 1000); at the end of the loop and you can avoid this. That'll poll them once a minute—surely that's enough?

Samir Talwar
  • 14,220
  • 3
  • 41
  • 65
2

Make it wait some time before firing again, like this:

while(true) { 
  //Code 
  Thread.sleep (1000); //Wait 1 second
} 

As for the second question, it would reduce memory and possibly CPU usage as well, but the gains really depend on what's happening with those strings.

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
2

A sleep would reduce the CPU usage. As for the StringBuilders they could lower the memory usage and improve performance.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
0

You could also try

Thread.yield()
helpermethod
  • 59,493
  • 71
  • 188
  • 276
  • 4
    @Helper Method - "Yield" only causes the currently executing thread object to temporarily pause and allow other threads to execute... so this will only reduce CPU usage significantly if there are any other user applications running in parallel. "Sleep" will be more adequate to what he wants to achieve. – XpiritO Mar 28 '10 at 13:09
  • @XpritO Sry, you're right. Didn't quite get the point of the OP. Maybe I shouldn't read post before my 2nd coffee ^^. – helpermethod Mar 29 '10 at 10:56
  • that's the reason in 5% of CPU load, to give other apps space to 'breathe' on the same computer, and that can be achieved by putting some Thread.yield() in critical places of code. I am doing that and it is very usefull from the point of normal software usage experience.. – ante.sabo May 06 '11 at 08:06
0

If their code is in a separate JVM and is running on Linux or some other Unix, require them to run their program at nice 20.

Or you could have them run inside a virtual machine like VirtualBox and use it to limit the processor utilization.

Or you could fire them if they continue burn cycles like that instead of using some event-driven model or Thread.sleep.

Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
0

Never assume something you see in the code is bad (or good) for performance. Performance issues are notoriously deceptive.

Here's an easy way to see for sure what is taking the time.

Community
  • 1
  • 1
Mike Dunlavey
  • 40,059
  • 14
  • 91
  • 135
0
  1. What sites is the code polling? Do they support an RSS push?
  2. If they do, then there is no need to poll the sites, and instead plug a module to wait for updates. The current method then waits using wait();
  3. The new module then notifies the object with this method using notifyAll().
  4. Admittedly this is some extra work, but it saves a whole lot of bandwidth and computation.
VGDIV
  • 679
  • 1
  • 7
  • 16