performance problem with process fork in gcj compiled CNI
Ricardo Temporal
ricardotemporal@hotmail.com
Fri Jan 27 14:25:00 GMT 2006
Hi,
I saw SUSV3 about the fork and really pthread_atfork documentations says:
"There are at least two serious problems with the semantics of fork() in a
multi-threaded program. One problem has to do with state (for example,
memory) covered by mutexes. Consider the case where one thread has a mutex
locked and the state covered by that mutex is inconsistent while another
thread calls fork(). In the child, the mutex is in the locked state (locked
by a nonexistent thread and thus can never be unlocked). Having the child
simply reinitialize the mutex is unsatisfactory since this approach does not
resolve the question about how to correct or otherwise deal with the
inconsistent state in the child."
The documentation suggests a workaround using fork handlers to be done in
libgcj and not in my application.
So I tried to forget the fork and launch 2 instances of the program by
the shell and I've got the same results.
It seems that the library libgcj.so is shared and synchronized.
Follow the new version of the program without any fork.
Please comments.
Temporal.
#include <iostream>
#include <string>
#include <unistd.h>
#include <gcj/cni.h>
#include <java/lang/Double.h>
#include <java/util/ArrayList.h>
using namespace std;
using namespace java::lang;
using namespace java::util;
int main(int argc, char **argv)
{
if (argc != 2)
{
cerr << "usage: integer" << endl;
return 1;
}
cout << "begin" << endl;
JvCreateJavaVM(NULL);
JvAttachCurrentThread(NULL, NULL);
ArrayList *arrayList = new ArrayList;
int loopSize = atol(argv[1]);
int maxArraySize = loopSize >> 3;
for(int i = 0, j = 0; i < loopSize; i++, j++)
{
arrayList->add(new Double((jdouble)(double)i));
if (j == maxArraySize)
{
j = 0;
jint size = arrayList->size();
arrayList->clear();
cout << getpid() << ", clear from " << (int)size << " to " <<
(int)arrayList->size() << endl;
}
}
JvDetachCurrentThread();
cout << "end" << endl;
return 0;
}
>From: "Boehm, Hans" <hans.boehm@hp.com>
>To: "Ricardo Temporal" <ricardotemporal@hotmail.com>,<java@gcc.gnu.org>
>Subject: RE: performance problem with process fork in gcj compiled CNI
>Date: 2006年1月26日 11:47:21 -0800
>>I'm amazed it does anything useful at all.
>>Once you've created a JVM, your process is multithreaded. The fork()
>child only has one of those threads active, and is only allowed to call
>async-signal-safe functions until it performs an exec(). (See the SUSV3
>spec of fork().) You're not even close to satisfying those
>requirements.
>>Hans
>> > -----Original Message-----
> > From: java-owner@gcc.gnu.org [mailto:java-owner@gcc.gnu.org]
> > On Behalf Of Ricardo Temporal
> > Sent: Thursday, January 26, 2006 5:11 AM
> > To: java@gcc.gnu.org
> > Subject: performance problem with process fork in gcj compiled CNI
> >
> >
> > performance problem with process fork in gcj compiled CNI
> >
> > Hello,
> >
> > I have a simple C++ program with a main function that
> > fork itself's
> > process and then it starts a loop calling some processing in
> > java compiled
> > code, using CNI.
> >
> > I intend to split processing in a machine with 2 CPUs using fork
> > technology, I'm not able to use another solution.
> >
> > When I run the program without forking, it takes about T
> > seconds to
> > finish consuming 100% of CPU and 50% of the machine.
> >
> > When I run the program with a fork in the beginning, it
> > takes more than
> > 2T seconds to finish with each process consuming 100% of CPU and both
> > consuming 100% of the machine.
> >
> > What's happening ?
> >
> > Temporal.
> >
> > #include <iostream>
> > #include <string>
> > #include <sys/types.h>
> > #include <unistd.h>
> > #include <gcj/cni.h>
> > #include <java/lang/Double.h>
> > #include <java/util/ArrayList.h>
> >
> > using namespace std;
> > using namespace java::lang;
> > using namespace java::util;
> >
> > int globalVariable = 2;
> >
> > /*
> > Code Templates:
> >
> > http://www-personal.umich.edu/~rusekd/articles/soc_prelim.html
> > http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html
> > */
> >
> > int main(int argc, char **argv)
> > {
> > if (argc != 3)
> > {
> > cerr << "usage: integer bool" << endl;
> > return 1;
> > }
> >
> > cout << "begin" << endl;
> >
> > JvCreateJavaVM(NULL);
> > JvAttachCurrentThread(NULL, NULL);
> >
> > string sIdentifier;
> > int iStackVariable = 20;
> >
> > pid_t pID = (atol(argv[2]) ? fork() : 1);
> >
> > if (pID == 0) // child
> > {
> > // Code only executed by child process
> >
> > sIdentifier = "Child Process: ";
> > globalVariable++;
> > iStackVariable++;
> > }
> > else if (pID < 0) // failed to fork
> > {
> > cerr << "Failed to fork" << endl;
> > exit(1);
> > // Throw exception
> > }
> > else // parent
> > {
> > // Code only executed by parent process
> >
> > sIdentifier = "Parent Process:";
> > }
> >
> > // Code executed by both parent and child.
> >
> > cout << sIdentifier;
> > cout << " Global variable: " << globalVariable;
> > cout << " Stack variable: " << iStackVariable << endl;
> >
> > ArrayList *arrayList = new ArrayList;
> >
> > int loopSize = atol(argv[1]);
> > int maxArraySize = loopSize >> 3;
> >
> > for(int i = 0, j = 0; i < loopSize; i++, j++)
> > {
> > arrayList->add(new Double((jdouble)(double)i));
> >
> > if (j == maxArraySize)
> > {
> > j = 0;
> >
> > jint size = arrayList->size();
> >
> > arrayList->clear();
> >
> > cout << pID << ", clear from " <<
> > (int)size << " to " <<
> > (int)arrayList->size() << endl;
> > }
> > }
> >
> > JvDetachCurrentThread();
> >
> > cout << "end" << endl;
> >
> > return 0;
> > }
> >
> >
> >
More information about the Java
mailing list