views:

765

answers:

4

I have an application that has a license for a set number of cpus and I want to be able to set the number of cpus that java runs in to 1 before the check is done. I am running Solaris and have looked at pbind but thought that if I started the application and then used pbind it would have checked the license before it had set the number of CPUs that java could use.

Does anyone know a way of starting an application with a set number of CPUs on Solaris?

A: 

Hi,

Googling over, I found that you are right, pbind binds processes to processors.

More info and examples at: http://docs.sun.com/app/docs/doc/816-5166/pbind-1m?a=view

ATorras
Yeah, thanks, but unfortunatley that doesn't really answer my question.
PintSizedCat
+3  A: 

It is a workaround, but using Solaris 10 you could set up a zone with a single CPU available and then run the application inside that zone.

If you want to do testing without running the full application, this bit of Java is most likely what they are using to get the number of CPU's:

Runtime runtime = Runtime.getRuntime();
int nrOfProcessors = runtime.availableProcessors();

A full example here.

Andre Miller
I'd be quite interested to know if using pbind changes the result of availableProcessors().
Gareth Davis
It should do, taskset changes the results of availableProcessors().
PintSizedCat
+1  A: 

This isn't a complete solution, but might be enough to develop into one. There's definitely a point at which the java process exists (and thus can be controlled by pbind) and at which point it hasn't yet run the code to do the processor check. If you could pause the launch of the application itself until pbind had done its work, this should be OK (assuming that the pbind idea will work from the CPU-checking point of view).

One way to do this that should definitely pause the JVM at an appropriate place is the socket attach for remote debuggers and starting with suspend mode. If you pass the following arguments to the java invocation:

-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,suspend=y,server=y

then the JVM will pause after starting the java process but before executing the main class, until a debugger/agent is attached to port 8000.

So perhaps it would be possible to use a wrapper script to start the program in the background with these parameters, sleep for a second or so, use pbind to set the number of processors to one for the java process, then attach and detach some agent to port 8000 (which will be enough to get Java to proceed with execution).

Flaws or potential hiccoughs in this idea would be whether running in debug mode would notably affect performance of your app (it doesn't seem to have a big impact in general), whether you can control some kind of no-op JDWP agent from the command line, and whether you're able to open ports on the machine. It's not something I've tried to automate before (though I've used something broadly similar in a manual way to increase the niceness of a Java process before letting it loose), so there might be other issues I've overlooked.

Andrzej Doyle
+1  A: 

I think the most direct answer to your question is to use pbind to bind the running shell process, and then start Java from that shell. According to the man page the effects of pbind are inherited by processes that are created from a bound process. Try this:

% pbind -b 0 $$
% java ...
Chris Quenelle