Very poor performance of JNI AttachCurrentThread on Linux

Dean Long dean.long at oracle.com
Tue Feb 26 15:28:42 PST 2013


This function should only get called in debug builds or for the initial 
thread, so I'm guessing
the app has a custom launcher because, if I'm not mistaken, the default 
launcher creates
a separate main thread to attach to the JVM while the initial thread waits.

But even so,  I don't think we need this function.  We already captured 
the bounds of the
initial thread in os::Linux::capture_initial_stack(), and the current 
range can be read using
getrlimit().

However if we do decide to keep get_stack_bounds(), I don't see why it 
can't use stdio like
find_vma().

dl

On 2/26/2013 9:58 AM, Andrew Haley wrote:
> get_stack_bounds() was rewritten because of a small memory leak.
> Instead of simply free()ing the memory to prevent the leak, it was
> rewritten to use a byte-by-byte loop around read() :
>
> http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2011-February/001864.html
>
> Unfortunately, the performance impact of this change is tragic.  As
> you can imagine, tens of thousands of system calls are made whenever
> get_stack_bounds() is called.
>
> Before rewrite: typically 100 microseconds
> After rewrite: typically 1500 microseconds
>
> It's impossible for me to tell from the discussion on the mailing list
> why such a change was made.  There is a rather elliptical comment
>
>> I'm strictly against reading /proc entry using stdio functions,
>> as (a) /proc file could be changed while we are reading it (b) it's not
>> fancy as we are buffering kmem.
> but this doesn't make any sense.  If the contents of "/proc/self/maps"
> really did change while it was being read, reading a byte at a time
> wouldn't help at all.  I don't know what the second sentence means.
>
> It would be possible to read "/proc/self/maps" in chunks and scan that,
> but my measurements show that it would not be significantly faster
> than the original version of get_stack_bounds().
>
> This severe regression is impacting a current large Java deployment.
> See https://bugzilla.redhat.com/show_bug.cgi?id=902004
>
> Is there any reason why I should not simply submit a webrev that reverts
> to the original code, with suitable use of free() ?  I have attached the
> code that I am testing.
>
> Andrew.
>
>
>
>
> static bool
> get_stack_bounds(uintptr_t *bottom, uintptr_t *top)
> {
>    FILE *f = fopen("/proc/self/maps", "r");
>    if (f == NULL)
>      return false;
>    char *str = NULL;
>    while (!feof(f)) {
>      size_t dummy;
>      ssize_t len = getline(&str, &dummy, f);
>      if (len == -1) {
>        free(str);
>        fclose(f);
>        return false;
>      }
>
>      if (len > 0 && str[len-1] == '\n') {
>        str[len-1] = 0;
>        len--;
>      }
>
>      static const char *stack_str = "[stack]";
>      if (len > (ssize_t)strlen(stack_str)
> 	&& (strcmp(str + len - strlen(stack_str), stack_str) == 0)) {
>        if (sscanf(str, "%" SCNxPTR "-%" SCNxPTR, bottom, top) == 2) {
>          uintptr_t sp = (uintptr_t)__builtin_frame_address(0);
>          if (sp >= *bottom && sp <= *top) {
>            free(str);
>            fclose(f);
>            return true;
>          }
>        }
>      }
>    }
>    free(str);
>    fclose(f);
>    return false;
> }
>
>



More information about the hotspot-dev mailing list