Very poor performance of JNI AttachCurrentThread on Linux

Dmitry Samersoff dmitry.samersoff at oracle.com
Tue Feb 26 13:38:59 PST 2013


Andrew,

Filed a bug JDK-8009062

-Dmitry


On 2013-02-26 21:58, 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;
> }
> 
> 


-- 
Dmitry Samersoff
Oracle Java development team, Saint Petersburg, Russia
* Give Rabbit time, and he'll always get the answer


More information about the hotspot-dev mailing list