bug 623999 - Takes 35s to start up r=dougt f=taras a=blocking-fennec

This commit is contained in:
Brad Lassey 2011-01-19 17:32:58 -05:00
parent edb072f038
commit 9d589f4402
3 changed files with 81 additions and 26 deletions

View File

@ -194,26 +194,6 @@ find_cdir_entry (struct cdir_entry *entry, int count, const char *name)
return NULL;
}
static uint32_t simple_write(int fd, const void *buf, uint32_t count)
{
uint32_t out_offset = 0;
while (out_offset < count) {
uint32_t written = write(fd, buf + out_offset,
count - out_offset);
if (written == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
continue;
else {
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "simple_write failed");
break;
}
}
out_offset += written;
}
return out_offset;
}
#define SHELL_WRAPPER0(name) \
typedef void (*name ## _t)(JNIEnv *, jclass); \
static name ## _t f_ ## name; \
@ -267,6 +247,31 @@ extern "C" int extractLibs = 1;
extern "C" int extractLibs = 0;
#endif
#ifdef DEBUG
#define DEBUG_EXTRACT_LIBS 1
#endif
#ifdef DEBUG_EXTRACT_LIBS
static uint32_t simple_write(int fd, const void *buf, uint32_t count)
{
uint32_t out_offset = 0;
while (out_offset < count) {
uint32_t written = write(fd, buf + out_offset,
count - out_offset);
if (written == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
continue;
else {
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "simple_write failed");
break;
}
}
out_offset += written;
}
return out_offset;
}
static void
extractFile(const char * path, const struct cdir_entry *entry, void * data)
{
@ -326,6 +331,7 @@ extractFile(const char * path, const struct cdir_entry *entry, void * data)
close(fd);
munmap(buf, 4096);
}
#endif
static void
extractLib(const struct cdir_entry *entry, void * data, void * dest)
@ -422,13 +428,15 @@ lookupLibCacheFd(const char *libName)
}
static void
addLibCacheFd(const char *libName, int fd)
addLibCacheFd(const char *libName, int fd, uint32_t lib_size = 0, void* buffer = NULL)
{
ensureLibCache();
struct lib_cache_info *info = &cache_mapping[cache_count++];
strncpy(info->name, libName, MAX_LIB_CACHE_NAME_LEN - 1);
info->fd = fd;
info->lib_size = lib_size;
info->buffer = buffer;
}
static void * mozload(const char * path, void *zip,
@ -444,6 +452,7 @@ static void * mozload(const char * path, void *zip,
void * data = ((void *)&file->data) + letoh16(file->filename_size) + letoh16(file->extra_field_size);
void * handle;
#ifdef DEBUG_EXTRACT_LIBS
if (extractLibs) {
char fullpath[256];
snprintf(fullpath, 256, "%s/%s", getenv("CACHE_PATH"), path + 4);
@ -462,14 +471,15 @@ static void * mozload(const char * path, void *zip,
#endif
return handle;
}
#endif
size_t offset = letoh32(entry->offset) + sizeof(*file) + letoh16(file->filename_size) + letoh16(file->extra_field_size);
int fd = zip_fd;
void * buf = NULL;
uint32_t lib_size = letoh32(entry->uncompressed_size);
int cache_fd = 0;
if (letoh16(file->compression) == DEFLATE) {
int cache_fd = lookupLibCacheFd(path + 4);
cache_fd = lookupLibCacheFd(path + 4);
fd = cache_fd;
if (fd < 0) {
char fullpath[256];
@ -478,8 +488,13 @@ static void * mozload(const char * path, void *zip,
struct stat status;
if (stat(fullpath, &status) ||
status.st_size != lib_size ||
apk_mtime > status.st_mtime)
apk_mtime > status.st_mtime) {
unlink(fullpath);
fd = -1;
} else {
cache_fd = fd;
addLibCacheFd(path + 4, fd);
}
}
if (fd < 0)
fd = createAshmem(lib_size, path);
@ -504,8 +519,11 @@ static void * mozload(const char * path, void *zip,
if (cache_fd < 0) {
extractLib(entry, data, buf);
addLibCacheFd(path + 4, fd);
addLibCacheFd(path + 4, fd, lib_size, buf);
}
// preload libxul, to avoid slowly demand-paging it
if (!strcmp(path, "lib/libxul.so"))
madvise(buf, entry->uncompressed_size, MADV_WILLNEED);
data = buf;
}
@ -517,7 +535,10 @@ static void * mozload(const char * path, void *zip,
lib_size, offset);
if (!handle)
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't load %s because %s", path, __wrap_dlerror());
if (buf)
// if we're extracting the libs to disk and cache_fd is not valid then
// keep this buffer around so it can be used to write to disk
if (buf && (!extractLibs || cache_fd >= 0))
munmap(buf, lib_size);
#ifdef DEBUG
@ -670,6 +691,36 @@ Java_org_mozilla_gecko_GeckoAppShell_loadLibs(JNIEnv *jenv, jclass jGeckoAppShel
loadLibs(str);
jenv->ReleaseStringUTFChars(jApkName, str);
if (extractLibs && cache_mapping) {
if (!fork()) {
sleep(10);
nice(10);
int count = cache_count;
while (count--) {
struct lib_cache_info *info = &cache_mapping[count];
if (!info->buffer)
continue;
char fullpath[256];
snprintf(fullpath, 256, "%s/%s", getenv("CACHE_PATH"), info->name);
char tmp_path[256];
sprintf(tmp_path, "%s.tmp", fullpath);
int file_fd = open(tmp_path, O_CREAT | O_WRONLY);
// using sendfile would be preferable, but it doesn't seem to work
// with shared memory on any of the devices we've tested
uint32_t sent = write(file_fd, info->buffer, info->lib_size);
munmap(info->buffer, info->lib_size);
info->buffer = 0;
close(file_fd);
if (sent == info->lib_size)
rename(tmp_path, fullpath);
else
unlink(tmp_path);
}
exit(0);
}
}
}
typedef int GeckoProcessType;

View File

@ -53,6 +53,8 @@ const struct mapping_info * getLibraryMapping();
struct lib_cache_info {
char name[MAX_LIB_CACHE_NAME_LEN];
int fd;
uint32_t lib_size;
void* buffer;
};
const struct lib_cache_info * getLibraryCache();

View File

@ -54,8 +54,10 @@ static void set_dlerror(int err)
void *__wrap_dlopen(const char *filename, int flag)
{
#ifdef DEBUG
if (extractLibs)
return dlopen(filename, flag);
#endif
soinfo *ret;