<br><font size=2 face="sans-serif">Here's is the URL I tried to include:</font>
<br>
<br><font size=2 face="sans-serif">http://openjdk.java.net/groups/hotspot/docs/RuntimeOverview.html#Java%20Native%20Interface%20(JNI)|outline</font>
<br>
<br>
<br><font size=2 face="sans-serif">We are using the concurrent GC with
a single generation.  After we workaround this immediate issue, we
plan to migrate to multiple generations and tweak the sizes of the generations.</font>
<br>
<br><font size=2 face="sans-serif">It is encouraging to hear that HotSpot
uses a different algorithm.  I'll see what I can do to accellerate
its usage.</font>
<br>
<br><font size=2 face="sans-serif">I'd like to understand HotSpot's behavior
a little better.  It sounds like your algorithm can do the mark &
sweep on a Java thread in native code without pausing that thread?</font>
<br>
<br><font size=2 face="sans-serif">Thanks for all the feedback.  I'll
continue reading ...</font>
<br>
<br><font size=2 face="sans-serif"><br>
Mark Maxey<br>
Raytheon, Garland<br>
580/2/P22-1<br>
(972)205-5760<br>
Mark_R_Maxey@Raytheon.com</font>
<br>
<br>
<br>
<table width=100%>
<tr valign=top>
<td width=40%><font size=1 face="sans-serif"><b>Paul Hohensee <Paul.Hohensee@Sun.COM></b>
</font>
<br><font size=1 face="sans-serif">Sent by: Paul.Hohensee@Sun.COM</font>
<p><font size=1 face="sans-serif">04/14/2009 05:06 PM</font>
<td width=59%>
<table width=100%>
<tr valign=top>
<td>
<div align=right><font size=1 face="sans-serif">To</font></div>
<td><font size=1 face="sans-serif">Mark R Maxey <Mark_R_Maxey@RAYTHEON.COM></font>
<tr valign=top>
<td>
<div align=right><font size=1 face="sans-serif">cc</font></div>
<td><font size=1 face="sans-serif">"Y. Srinivas Ramakrishna"
<Y.S.Ramakrishna@Sun.COM>, hotspot-gc-dev@openjdk.java.net, Andrew
M Dungan <Andrew_M_Dungan@RAYTHEON.COM>, David A Lilly <David_A_Lilly@RAYTHEON.COM></font>
<tr valign=top>
<td>
<div align=right><font size=1 face="sans-serif">Subject</font></div>
<td><font size=1 face="sans-serif">Re: Garbage Collection Pauses &
Non-interruptable System Calls</font></table>
<br>
<table>
<tr valign=top>
<td>
<td></table>
<br></table>
<br>
<br>
<br><tt><font size=2>The url for "Hotspot Runtime Overview of JNI"
didn't come through for me.<br>
<br>
In any case, as Ramki noted, Hotspot lets native code called from Java
<br>
run free<br>
during GC pauses, unless said native code calls back into the jvm for <br>
some reason,<br>
including just returning back to Java from native.  Hotspot does _not_
<br>
try to<br>
pause threads executing native code, nor does Hotspot use signal mechanisms<br>
to block threads executing Java code so GC can happen.  Hotspot uses
a <br>
polling<br>
mechanism instead because signal delivery mechanisms on Unix and Linux
are<br>
unreliable.  I doubt you'll be able to reproduce the JRockit issue
with <br>
Hotspot.<br>
You might have other problems, but not that one.<br>
<br>
I suggest forwarding your questions to the JRockit team at Oracle.  <br>
Though I suspect<br>
some of them are on this list too. :)<br>
<br>
Please try Hotspot before you give up on Java.  From your description,
<br>
you should<br>
use the CMS (concurrent mark-sweep) collector.  See also the GC <br>
performance info<br>
accessible from<br>
<br>
http://java.sun.com/performance<br>
<br>
and Jon Masamitsu's blog<br>
<br>
http://blogs.sun.com/jonthecollector/<br>
<br>
Paul<br>
<br>
Mark R Maxey wrote:<br>
><br>
> After reading the last paragraph of HotSpot Runtime Overview of JNI
<br>
> more closely, I understand more.  I think we're almost on the
same <br>
> page.  The problem seems to be that all threads are suspended
until <br>
> the Java thread returns from the native call.<br>
><br>
><br>
> Mark Maxey<br>
> Raytheon, Garland<br>
> 580/2/P22-1<br>
> (972)205-5760<br>
> Mark_R_Maxey@Raytheon.com<br>
><br>
><br>
> *Mark R Maxey/US/Raytheon*<br>
><br>
> 04/14/2009 12:37 PM<br>
><br>
>                  <br>
> To<br>
>                  "Y.
Srinivas Ramakrishna" <Y.S.Ramakrishna@Sun.COM><br>
> cc<br>
>                  hotspot-gc-dev@openjdk.java.net,
Y.S.Ramakrishna@Sun.COM, Andrew M <br>
> Dungan/US/Raytheon@MAIL, David A Lilly/RCS/Raytheon/US@MAIL, Mark
R <br>
> Maxey/US/Raytheon@MAIL<br>
> Subject<br>
>                  Re:
Garbage Collection Pauses & Non-interruptable System CallsLink <br>
> <Notes://MK2-MSG05/86256EF3005F851B/38D46BF5E8F08834852564B500129B2C/E1F59319D41C5C4886257598005422BD>
<br>
><br>
><br>
><br>
><br>
>                  <br>
><br>
><br>
><br>
><br>
> Thank you for your reply.  The speed and depth of your response
is <br>
> encouraging.<br>
><br>
> Let me confess something I should have done up-front.  The behavior
<br>
> we're seeing is using JDK 5 via JRockit R27.6.  We're in the
process <br>
> of reproducing these problems under HotSpot JDK 6 Update 12, though
<br>
> it'll be a few days before we can do so.  The reason I'm pinging
this <br>
> forum is to research in advance what differences we might expect <br>
> between the two JVMs.<br>
><br>
> Let me describe exactly what we're seeing as provided by doing an
<br>
> strace on the process:<br>
><br>
>    1. A Java thread calls a native C code that ultimately
calls a<br>
>       pwrite().  We suspect that the device driver
ultimately makes a<br>
>       non-interruptable system call to transfer the
data directly from<br>
>       our mem-aligned 128 MB buffer to disk.<br>
>    2. The GC thread sends a tgkill(SIGUSR1) to all threads<br>
>    3. The GC thread waits on mutex #1 (presumably waiting
on all the<br>
>       threads to signal it that it can begin GC)<br>
>    4. The Java thread wakes mutex #1 (presumably signaling
the GC it<br>
>       is ready to go)<br>
>    5. The Java thread waits on mutex #2 (presumably waiting
on GC to<br>
>       finish)<br>
>    6. The GC thread wakes mutex #2 (presumably telling the
Java thread<br>
>       it can resume processing)<br>
><br>
><br>
> We're seeing times between #3 & #4 that are proportional to the
amount <br>
> of time spent in the pwrite().  We also see some overhead between
#5 <br>
> &#6 that is proportional to the number of Java threads we have
<br>
> (currently between 30 & 40 that we've created not counting the
JVMs).<br>
><br>
> Unfortunately, the JRockit logging only reveals the actual time GC
<br>
> takes (#4 - #5).  Hopefully, HotSpot's logging includes the total
time <br>
> (#2 - #6).<br>
><br>
> I'm pursuing these questions with Oracle/BEA.  Again, I'm just
trying <br>
> get a feel for HotSpot's behavior in comparison.  While we're
using <br>
> JRockit today, HotSpot will be our ultimate platform.<br>
><br>
><br>
> One alternate solution that has been suggested is infrequently calling
<br>
> GC explicitly within our code during special times when we know we
can <br>
> afford to take the hit.  We would even accept a greater hit than
<br>
> normal if we could avoid being impacted during critical times.  
<br>
> Everything I've ever read says to not do this, but I'm curious why
in <br>
> this case this is a bad idea.  Note that we're using the concurrent
<br>
> GC, so I'm not even sure if System.gc() supports this.<br>
><br>
><br>
> Thanks again!<br>
><br>
><br>
> Mark Maxey<br>
> Raytheon, Garland<br>
> 580/2/P22-1<br>
> (972)205-5760<br>
> Mark_R_Maxey@Raytheon.com<br>
><br>
><br>
> *"Y. Srinivas Ramakrishna" <Y.S.Ramakrishna@Sun.COM>*<br>
> Sent by: Y.S.Ramakrishna@Sun.COM<br>
><br>
> 04/14/2009 10:19 AM<br>
><br>
>                  <br>
> To<br>
>                  Mark
R Maxey <Mark_R_Maxey@raytheon.com><br>
> cc<br>
>                  hotspot-gc-dev@openjdk.java.net<br>
> Subject<br>
>                  Re:
Garbage Collection Pauses & Non-interruptable System Calls<br>
><br>
><br>
><br>
>                  <br>
><br>
><br>
><br>
><br>
><br>
> Hello Mark --<br>
><br>
> I am assuming your threads doing DMA are actually executing native
<br>
> code (or<br>
> waiting for signals in native code).  Threads in native code
do not <br>
> need to<br>
> synchronize \in any manner with GC while they are executing native
code.<br>
> It is only the transitions to and from native mode (from Java code)
that<br>
> require<br>
> synchronization. Roughly speaking, the JVM fences off those native<br>
> threads so that, in the event that they need to re-enter the JVM or<br>
> access the Java heap, they will be suspended until a GC/safepoint
that<br>
> is in progress is completed.<br>
><br>
> Thus, I do not believe you need to fear that a long-running DMA call
would<br>
> cause GC's to be delayed (which I understand is your  main concern
below).<br>
><br>
> Have you actually seen cases where this is happening? If so, what<br>
> version of the JDK<br>
> are you running?<br>
><br>
> thanks.<br>
> -- ramki<br>
><br>
> Mark R Maxey wrote:<br>
> > Hello,<br>
> ><br>
> > I have a problem I was hoping with which I need some advice.<br>
> ><br>
> > We wrote a custom JNI library for file I/O that sits underneath
the <br>
> Java<br>
> > NIO FileChannel.  One of our driving requirements is highly
performant<br>
> > file I/O.  We achieved this by doing DMA I/O from large
direct memory<br>
> > aligned buffers.  The JNI is very trivial - it just takes
a buffer and<br>
> > performs the appropriate system call based on the parameters
given <br>
> to it.<br>
> > 100% of the logic for calculating offsets, buffer management,
etc. <br>
> is all<br>
> > in our implementation of java.nio.FileChannel.<br>
> ><br>
> > Here's our problem:  We have requirements to respond to
some <br>
> messages in<br>
> > as little as 250 ms.  During this time, we're doing file
writes of <br>
> 128 MB<br>
> > that take around 200 ms.  When GC kicks in, it tries to
pause all <br>
> threads.<br>
> >  Because the DMA write is non-interruptable, GC waits for
the I/O to<br>
> > complete before being able to pause the thread & run.  That
means <br>
> that GC<br>
> > can take well over 200 ms putting us in grave danger of missing
our<br>
> > timelines.  Worse, there is always the chance the write
will hang <br>
> due to a<br>
> > bad filesystem.   We've seen this cause the JVM to hang
indefinitely<br>
> > forcing us to cycle the process.<br>
> ><br>
> > Unless we find a solution that allows GC to continue while doing
<br>
> this I/O,<br>
> > we will convert all the code to C++.  While that might solve
our <br>
> timeline<br>
> > for that particular process, we have many less performance critical<br>
> > processes that use our JNI FileChannel libraries that would hang
if a<br>
> > filesystem goes bad.<br>
> ><br>
> > We've tweaked the file system device timeouts down to a minimum,
but <br>
> they<br>
> > are still very high (on the order of several seconds to minutes).
 It<br>
> > would be nice if the JVM had a similar timeout for pausing threads,
<br>
> i.e.,<br>
> > where the pause times out after X number of milliseconds.  We'd
be <br>
> willing<br>
> > to sacrifice a larger heap size and postpone GC in the hopes
that <br>
> the next<br>
> > time it ran GC, we wouldn't be in the middle of a non-interruptable
<br>
> system<br>
> > call.<br>
> ><br>
> > The only solution being batted around here is pushing the system
<br>
> calls out<br>
> > of Java threads and into native threads.  The JNI call would
push <br>
> the info<br>
> > for the I/O call onto a native C++ queue where a small number
of native<br>
> > threads (3?) would pull the data off the queue and perform the
actual<br>
> > system call.   The trick is finding an implementation where
the Java<br>
> > thread blocked waiting on a response from the native thread is<br>
> > interruptible.  All this assumes GC doesn't try to pause
native <br>
> threads.<br>
> > We thought about using pthreads, but were concerned about its
signal<br>
> > interaction with the JVM.  So, we're leaning towards using
pipes to <br>
> push<br>
> > data from one thread to another.<br>
> ><br>
> > If you have any suggestions or advice, we are desperate for your
wisdom.<br>
> ><br>
> > Thanks!<br>
> ><br>
> ><br>
> > Mark Maxey<br>
> > Raytheon, Garland<br>
> > 580/2/P22-1<br>
> > (972)205-5760<br>
> > Mark_R_Maxey@Raytheon.com<br>
> ><br>
> >  <br>
><br>
><br>
><br>
><br>
><br>
</font></tt>
<br>
<br>
<br>