Very poor performance of JNI AttachCurrentThread on Linux

Adam Domurad adomurad at redhat.com
Thu Mar 28 12:02:45 PDT 2013


On 03/11/2013 01:19 PM, Dmitry Samersoff wrote:
> Adam,
>
> Sorry! I can't provide any estimations right now. But it's a high
> priority issue in my queue, and I plan to provide a fix as soon as it
> become possible.
>
> -Dmitry
>
> On 2013-03-06 21:45, Adam Domurad wrote:
>> On 03/01/2013 11:00 AM, Dmitry Samersoff wrote:
>>> Adam,
>>>
>>> Thank you for advice! I'm looking for a possibility to remove
>>> get_stack_bounds function entirely as Dean suggested. But it takes some
>>> time.
>> Hi again, not to be a bother, but do you have a rough time-frame that
>> the fix will take?
>>
>> Thanks,
>> -Adam
>

As per our off-list chat, I have attached my implementation of a revised 
implementation of get_stack_bounds with a small test-case. As far as 
performance is concerned, it's an order of magnitude faster from my 
timings. This should be suitable given that no problems were reported 
with the old implementation.

Happy hacking,
-Adam
-------------- next part --------------
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <fcntl.h>
#include <unistd.h>

typedef int bool;
#define false 0
#define true 1

static bool
get_stack_bounds(uintptr_t *bottom, uintptr_t *top) {
	int fd = open("/proc/self/maps", O_RDONLY);
	if (fd < 0) {
		return false;
	}

	int line_len = 0; /* Length of partially copied line portion */
	const int BUFFER_SIZE = 256; /* Comfortable upper bound on possible line size */
	char buffer[BUFFER_SIZE];

	bool success = false;
	for (;;) {
		int read_len = read(fd, buffer + line_len, BUFFER_SIZE - line_len - 1);

		if (read_len <= 0) {
			break; /* Fail */
		}

		char *buffer_end = buffer + line_len + read_len;
		*buffer_end = '\0'; /* Null-terminate for string functions */

		const char *stack_loc = strstr(buffer, "[stack]");

		/* We either find '[stack]', or we try to complete the last line */
		const char *line_end = stack_loc ? stack_loc : buffer_end;
		const char *line_start = line_end;

		/* Find start of line */
		while (line_start > buffer && line_start[-1] != '\n') {
			line_start--;
		}

		if (stack_loc) {
			if (sscanf(line_start, "%" SCNxPTR "-%" SCNxPTR, bottom, top) == 2) {
				uintptr_t sp = (uintptr_t) __builtin_frame_address(0);
				success = (sp >= *bottom && sp <= *top);
			}
			break; /* Succeed if we parsed valid stack bounds */
		}

		line_len = line_end - line_start;

		if (line_len >= BUFFER_SIZE - 1) {
			break; /* Line too large, fail */
		}

		memcpy(buffer, line_start, line_len);
	}

	close(fd);
	return success;
}

int main(void) {
	bool something_failed = false;
	int i;
	for (i = 2; i <= 1024 * 4; i++) {
		uintptr_t bottom, top;
		bool success = get_stack_bounds(&bottom, &top);
		if (!success) {
			something_failed = true;
			printf("FAILED FOR %d\n", i);
		}
	}
	if (!something_failed) {
		printf("All success\n");
	}

	return 0;
}


More information about the hotspot-dev mailing list