views:

2467

answers:

9

I'm developing a Java application that streams music via HTTP, and one problem I've come up against is that while the app is reading the audio file from disk and sending it to the client it usually maxes out the CPU at 90-100% (which can cause users problems running other apps).

Is it possible to control the thread doing this work to use less CPU, or does this need to be controlled by the OS? Are there any techniques for managing how intensive your application is at present?

I know you can start threads with a high/low priority, but this doesn't seem to have any effect for me in this scenario.

(I can't get my head past "I've asked the computer to do something, so it's obviously going to do it as fast as it can...")

Thanks!

rod.

+2  A: 

You can lower it's priority using methods in Thread (via Thread.currentThread() if necessary).

You can also put delays in it's processing loop (Thread.sleep()).

Other than that, let the O/S take care of it. If your program can use 100% CPU, and nothing else needs the CPU your app might as well use it rather than letting the O/S idle task have it.

It's also true that streaming data should be I/O bound, so you should definitely review what's being done between reading the data and sending it. Are you reading/sending byte by byte, unbuffered, for example?

EDIT: In response to marr75's comment, I am absolutely not advocating that you write poor, inefficient code which wastes CPU resources - There is an article on my web site which clearly conveys what I think about that mind-set. Rather, what I am saying is that if your code legitimately needs the CPU, and you've prioritized it to behave nicely if the user wants to do other things, then there is no point at all in artificially delaying the outcome just to avoid pegging the CPU - that only does the user the disservice of making them wait longer for the end result, which they presumably want as quickly as possible.

Software Monkey
lowering priority definitely the way to go. That means your app will be as fast as it can (i.e. use as much CPU) but if any other app needs CPU time it can get it.
SCdF
setPriority on an already running thread probably will not work. It might not do anything anyway.
Tom Hawtin - tackline
I once heard an argument for not fixing memory leaks that this answer reminded me of, it was along the lines of, "The whole purpose of a process is to allocate memory, so unless it's blocking other operations, don't fix it." Needless to say, I didn't feel this was the best solution.
marr75
@marr75: That's not at all what I am saying - see my edit.
Software Monkey
@marr75: Besides, the argument cited is both inane and specious - the purpose of a process is not to allocate memory for the sake of it, but rather to accomplish some task; in doing so it should use the minimum possible amount of memory, time, CPU and other resources. Those considerations are often in tension and use of one must be traded off against another.
Software Monkey
+6  A: 

That task (reading a file from the disk and sending it via HTTP) should not use any significant amount of CPU, especially at the bitrates required for music streaming (unless you're talking about multi-channel uncompressed PCM or something like that, but even then it should be I/O-bound and not use a lot of CPU).

You're probably doing the reading/writing in a very inefficient way. Do you read/write each byte separately or are you using some kind of buffer?

Joachim Sauer
A: 

I don't think you can lower the priority without losing the functionality (stream music). Your program gets this much cpu from the OS, because it needs it. It's not like the OS is giving cpu-time away for no reason or because "it's in the mood for it".

If you think, you can do the task without using that much cpu-utilization, you can profile your app and find out, where this high cpu-utilization takes place and then try to improve your code.

I think you are doing the streaming in an inefficient way, but I say streaming CAN be a highly utilizing task.

I repeat, don't think about reducing the cpu-utilization by lowering the priority of the process or telling the OS "Don't give that much cpu-time to this process". That's the whole wrong intuition in my eyes. Reduce the cpu-utilization by improving the algorithms and code after profiling.

A good start in profiling java is this article: http://www.ibm.com/developerworks/edu/os-dw-os-ecl-tptp.html

bitschnau
"Your program gets this much cpu from the OS, because it needs it." that is a dangerous thing to assume. If you have an in-efficient algorithm, then the OS will stupidly give more cpu to you to the detriment of other programs running in the OS.
Chii
That's in fact what I wanted to say. The program gets as much as cpu-time from OS as it "requests" (better word instead of "needs"). How much it requests surely depends on the algorithm, but the OS can not determine if the algorithm is stupidly requesting to much cpu-time or not!
bitschnau
A: 

In addition to the information given above: the JVM is free in how it uses OS threads. The Thread in your Java application might run in a seperate OS thread, or it might share that thread with other Threads. Check the documentation for the JVM you are using for additional information.

Jeroen van Bergen
A: 

Ok, thanks for the advice guys! Looks like I'm just going to have to look into trying to improve the efficiency of the way my app is streaming (though not sure this is going to go far as I'm basically just reading the file from disk and writing it to the client...).

+1  A: 

Do you have one or more of:

  • Software RAID
  • Compressed folder
  • Intrusive virus checker
  • Loopback file system
Stephen Denne
Upped for virus checker and file system, although depending on the compression and OS interaction this could cause an issue too.
marr75
A: 

VisualVM is very easy to use to find out where your CPU time is being spent for Java applications, and it is included in the latest versions of the JDK (named jvisualvm.exe on Windows)

Stephen Denne
+2  A: 

I would check how much buffering you are using. If you read/write one byte at a time you will consume a lot of CPU. However, if you are reading/writing blocks of say 4 kB it shouldn't use much CPU at all. If your network is the internet your CPU shouldn't be much over 10% of a single client.

One approximation for the buffer size is the bandwidth * delay. e.g. if you expect users to stream at 500 KB/s and there is a network latency of up to 0.1 sec, then the buffer size should be around 50 KB.

Peter Lawrey
Well put, well thought out buffers will allow the operating system to take advantage of CPU cache and DMA.
marr75
A: 

Follow up to my "well thought out buffers" comment, a good rule of thumb for TCP buffering, buffer size = 2 * bandwidth * delay

So if you want to stream 214kbps music (around 27kB/s) and have, let's say 60ms of latency, you're looking at 3.24 kilobytes, and rounding off to a nice 4kB buffer will work very well for you on a wide range of systems.

marr75
I think this OP does not exist any more. Just look at the grayed out asker box.
kd304