big cpu consumption

B

black-white

hello,

I have a big problem with cpu usage. when i listen microphone to record
what comes, cpu time is consumed apr. 80% everytime which seems
unnecessary. cpu is P4 2.8 GHz. i have lots of programs which does do as
executable from internet and none of them consumes so much. here is the
code, could ou please lead me to solve this problem?

AudioFormat format = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED, // Encoding technique
8000, // Sample Rate
16, // Number of bits
in each channel
2, // Number of
channels (2=stereo)
4, // Number of bytes
in each frame
8000, // Number of frames
per second
true );// formatControls.getFormat();

DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format, line.getBufferSize());
ByteArrayOutputStream out = new ByteArrayOutputStream();
int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
byte[] data = new byte[bufferLengthInBytes];

while (true) {

if ((numBytesRead = line.read(data, 0, bufferLengthInBytes)) == -1) {
break;//here is the place where cpu is consumed!
}

out.write(data, 0, numBytesRead);
}
 
T

Tom Anderson

if ((numBytesRead = line.read(data, 0, bufferLengthInBytes)) == -1) {
break;//here is the place where cpu is consumed!
}

That's what we call a busy-wait, and it is indeed a very good way to waste
all your CPU time. You could try something like this:

while ((numBytesRead = line.read(data, 0, bufferLengthInBytes)) == -1) {
try {
Thread.sleep(t) ;
}
catch (InterruptedException e) {
// can probably ignore this
}
}

Where t is a duration in milliseconds. This basically means that your
program will wait for a while before trying to read data again. It won't
be consuming CPU while it waits.

The problem is picking the right value for t. If it's too long, you run
the risk of the line's buffer overflowing while the reader thread sleeps.
If it's too short, you'll use too much CPU time.

I'd set it based on a calculation of how long the buffer will take to
fill. Like this:

float dataRate = format.getFrameRate() * format.getFrameSize() ; // in bytes per second
float timeToFill = line.getBufferSize() / dataRate ; // in seconds
long t = (long)((timeToFill * f) * 1000) ;

Where f is a fraction, saying how full you want the buffer to get between
reads; i'd set it to 0.5, so the buffer will be half full. That should
mean that if your thread is a bit slow at waking up, there's still little
chance of overflow. You might need to adjust this downwards if you find
there are overflow problems.

Another option would be to set the time adaptively, based on how long the
last sleep was, and how full the buffer got. That's a bit more
complicated, but you can probably work it out.

The underlying problem is that there's no way to read data from a line in
a blocking way. This is a design fault in the library, sadly.

tom
 
B

black-white

hello tom,

thanks a lot fr your detailed description. morrow n the company i will
try what you suggested and i am sure it will be much more better :)
 
B

black-white

jolz, thanks for your answer but i had no problem with running of line,
i had just cpu time wasting problem.
 
J

jolz

jolz, thanks for your answer but i had no problem with running of line,

Are you sure ?
The read()'s doc says:
"This method blocks until the requested amount of data has been read".
So there should be high CPU usage (at least with large enough buffers).
But without start() numBytesRead will be allways 0 and the loop will
behave like while (true) { }
 
E

EJP

That's what we call a busy-wait

No it's not.
, and it is indeed a very good way to
waste all your CPU time.

There is no CPU time being used here at all actually. There is
wall-clock time being spent while the read() method blocks. Not the same
thing.
while ((numBytesRead = line.read(data, 0, bufferLengthInBytes)) == -1) {
try {
Thread.sleep(t) ;
}
catch (InterruptedException e) {
// can probably ignore this
}
}

Where t is a duration in milliseconds. This basically means that your
program will wait for a while before trying to read data again. It won't
be consuming CPU while it waits.

Excuse me but this is all nonsense. The read() will return -1 at the end
of the stream. At this point there will *never* be any more data on the
stream.
 
E

EJP

jolz said:
Are you sure ?
The read()'s doc says:
"This method blocks until the requested amount of data has been read".
So there should be high CPU usage (at least with large enough buffers).

Why? Blocking doesn't consume any CPU.
 
E

EJP

jolz said:
Are you sure ?
The read()'s doc says:
"This method blocks until the requested amount of data has been read".
So there should be high CPU usage (at least with large enough buffers).
But without start() numBytesRead will be allways 0 and the loop will
behave like while (true) { }
 
R

Roedy Green

could ou please lead me to solve this problem?

You might try a different sound card. You might find one that does
some of the work in hardware that your current one is doing with
software, or that has a clever driver to use the aux cpu, leaving the
main one free to run Java. See if you can borrow a high end one to
see if it makes any difference.
 
D

Daniele Futtorovic

Why? Blocking doesn't consume any CPU.

I think he means that, unless Line#start() is called, the call to read()
doesn't block, but returns zero (instead of throwing an IOException),
hence the loop being essentially a for(;;); (you snipped the relevant part).

I don't recall the intrinsics of the AudioSystem since the last time I
used it, but the assumption above seems plausible. Worth a shot, at any
rate.
 
J

jolz

So there should be high CPU usage (at least with large enough buffers).
I think he means that, unless Line#start() is called, the call to read()
doesn't block, but returns zero (instead of throwing an IOException),
hence the loop being essentially a for(;;);

Actualy I ment to write shouldn't. But your interpretation also works:)
but the assumption above seems plausible.

The behaviour is required:
"However, if the data line is closed, __stopped__, drained, or flushed
before the requested amount has been read, the method no longer blocks"
 
T

Tom Anderson

No it's not.

Well, actually it is, although it's waiting for a condition which will
never occur.
There is no CPU time being used here at all actually. There is
wall-clock time being spent while the read() method blocks. Not the same
thing.

And also not what the OP reported:

"I have a big problem with cpu usage. when i listen microphone to record
what comes, cpu time is consumed apr. 80% everytime which seems
unnecessary."

Clearly, CPU time *is* being used, and this *is* a busy-wait. But, having
read what you read elsewhere in this thread, i realise my diagnosis (based
not on knowledge of the API, but on inference from what the OP wrote, ie
guesswork - my bad!) was misguided. I thought that read() was returning -1
when there wasn't data available, which is not what the documentation
says. I imagine your suggestion of sorting out start() is the right one.
Excuse me but this is all nonsense. The read() will return -1 at the end
of the stream. At this point there will *never* be any more data on the
stream.

Fair enough. If the OP's program is busy-waiting for data which will never
come, my approach will still reduce CPU use, though - it makes the
pointless wait far more efficient!

tom
 
E

EJP

Tom said:
Well, actually it is, although it's waiting for a condition which will
never occur.

I don't understand this statement. A blocking operation isn't a
busy-wait by any definition. The OP may well be showing 80% CPU but I
suggest that if it was a busy-wait it would have been 100%.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top