This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
RE: performance problem with process fork in gcj compiled CNI
- From: "Ricardo Temporal" <ricardotemporal at hotmail dot com>
- To: hans dot boehm at hp dot com, java at gcc dot gnu dot org
- Date: Fri, 27 Jan 2006 11:39:13 +0000
- Subject: RE: performance problem with process fork in gcj compiled CNI
- Bcc:
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: Thu, 26 Jan 2006 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;
> }
>
>
>