This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: performance problem with process fork in gcj compiled CNI


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;
> }
>
>
>



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]