From fd3a9fb0c3b555d2fc93a6436da840ab4ea2fac1 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 27 Feb 2014 18:18:25 -0800 Subject: [PATCH] Vastly reduce the number of read(2)s done in tzload. This costs us about 1000 fewer syscalls, which makes "adb shell strace date" a lot more readable (which is the reason I've been meaning to fix this for a long time now), but also actually saves a measurable amount of time. Longer-term we should try to keep the tzdata mmap(2)ed in like libcore does. Change-Id: I1dd9c81968a13d3a6a55ba17f8a7d5c1f38cd103 --- libc/tzcode/localtime.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c index 202f031af..258ea5e28 100644 --- a/libc/tzcode/localtime.c +++ b/libc/tzcode/localtime.c @@ -2167,26 +2167,40 @@ static int __bionic_open_tzdata_path(const char* path_prefix_variable, const cha } off_t specific_zone_offset = -1; + ssize_t index_size = ntohl(header.data_offset) - ntohl(header.index_offset); + char* index = malloc(index_size); + if (TEMP_FAILURE_RETRY(read(fd, index, index_size)) != index_size) { + fprintf(stderr, "%s: could not read index of \"%s\": %s\n", + __FUNCTION__, path, (bytes_read == -1) ? strerror(errno) : "short read"); + free(index); + close(fd); + return -1; + } static const size_t NAME_LENGTH = 40; - unsigned char buf[NAME_LENGTH + 3 * sizeof(int32_t)]; + struct index_entry_t { + char buf[NAME_LENGTH]; + int32_t start; + int32_t length; + int32_t raw_gmt_offset; + }; - size_t id_count = (ntohl(header.data_offset) - ntohl(header.index_offset)) / sizeof(buf); + size_t id_count = (ntohl(header.data_offset) - ntohl(header.index_offset)) / sizeof(struct index_entry_t); + struct index_entry_t* entry = (struct index_entry_t*) index; for (size_t i = 0; i < id_count; ++i) { - if (TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf))) != (ssize_t) sizeof(buf)) { - break; - } - char this_id[NAME_LENGTH + 1]; - memcpy(this_id, buf, NAME_LENGTH); + memcpy(this_id, entry->buf, NAME_LENGTH); this_id[NAME_LENGTH] = '\0'; if (strcmp(this_id, olson_id) == 0) { - specific_zone_offset = to_int(buf + NAME_LENGTH) + ntohl(header.data_offset); - *data_size = to_int(buf + NAME_LENGTH + sizeof(int32_t)); + specific_zone_offset = ntohl(entry->start) + ntohl(header.data_offset); + *data_size = ntohl(entry->length); break; } + + ++entry; } + free(index); if (specific_zone_offset == -1) { XLOG(("%s: couldn't find zone \"%s\"\n", __FUNCTION__, olson_id));