How are you showing the CPU utilisation?
If you use task manager, I suggest you use Sysinternal Process Explorer instead. This has a system information window you can open which will show a totally CPU use, or a checkbox to show utilisation of each processor core.
The fact that you cite CD ripping and file compression as cases where CPU utilisation hits about 25% SUGGESTS to me that the task you are doing is bounded by a single CPU. For example, compressing a file has performance limited by 2 things:
- I/O (disk)
- CPU performance
Most compression can't take advantage of multiple cores, because it is an inherently single=threaded task. So adding more processors in parallel won't go any faster. And if you view the processor utilisation of each core you will see one going flat out and the others pretty much idle. Now, one at 100% and 3 at 0% gives an average of about 25% - so this sort of fits with what you are seeing.
Similarly, CD ripping is limited by the speed at which the data can be pulled off the CD, and then what you do with it. If you (for example) convert audio to MP3 as part of the rip, then that conversion is pretty much single threaded as well, meaning again that multiple CPU cores won't be used (or make the overall job get done faster). Your limit will be set by either the read speed or the speed of a single CPU.
It SOUNDS like the reason you see 20% - 25% is that the jobs where you make the measurement are bounded to a single CPU which is running pretty much flat out, the others are idling because the tasks you are doing can't exploit multiple processors.
To see if the total processor utilisation can go higher you need to run tasks that can exploit multiple CPUs. (Of course nobody tells you if their program does this or not.)
To pick off a point raised by one of the other answers here: Some problems are amenable to parallelism and if a program (for that problem) is written correctly, can exploit multiple CPUs. And some problems can't exploit such parallelism. I'm pretty sure, for example, that LZ-style compression as used in all common zip-type files CANT exploit parallelism because the algorithm needs to read the source file sequentially in order to create the compressed file. Sequential processing like this can't easily be spread over multiple threads (where threads can then be allocated to physical processors).