From a0d07f5c79aece51b890dee87d6c0828d915b224 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Sun, 22 Oct 2006 10:03:59 +0000 Subject: [PATCH] speed up e17's login - reduce disk IO wait. on my p4 3.4ghz + reiser3fs IO Wait time went from 2.6 to 1.9 seconds (total login time went from 3.01511 to 2.29971, with 100% cached login time being 0.41809) on my core 2 duo laptop + ext3fs IO Wait time went from 2.05 to 1.15 seconds (total login time went from 2.50988 to 1.60785, with 100% cached login time being 0.45850) this should speed up e's login a bit... i hope. note - it is adaptive. it needs you to log in at least once using the current code as it traps and logs certain file accesses and needs that log to replay next login. SVN revision: 26742 --- configure.in | 1 + src/Makefile.am | 2 +- src/bin/e_main.c | 3 + src/bin/e_start_main.c | 76 ++++++++++++- src/preload/Makefile.am | 28 +++-- src/preload/e_precache.c | 227 +++++++++++++++++++++++++++++++++++++++ src/preload/e_precache.h | 17 +++ 7 files changed, 343 insertions(+), 11 deletions(-) create mode 100644 src/preload/e_precache.c create mode 100644 src/preload/e_precache.h diff --git a/configure.in b/configure.in index 930083b57..9cccfe219 100644 --- a/configure.in +++ b/configure.in @@ -280,6 +280,7 @@ src/modules/ibox/Makefile src/modules/ibox/module.desktop src/modules/start/Makefile src/modules/start/module.desktop +src/preload/Makefile data/Makefile data/fonts/Makefile data/images/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index c3625499b..d29641709 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,2 +1,2 @@ MAINTAINERCLEANFILES = Makefile.in -SUBDIRS = bin modules +SUBDIRS = bin modules preload diff --git a/src/bin/e_main.c b/src/bin/e_main.c index 0e39fbae4..b19160ebe 100644 --- a/src/bin/e_main.c +++ b/src/bin/e_main.c @@ -3,6 +3,8 @@ */ #include "e.h" +EAPI int e_precache_end = 0; + /* local subsystem functions */ static void _e_main_shutdown_push(int (*func)(void)); static void _e_main_shutdown(int errorcode); @@ -1404,6 +1406,7 @@ _e_main_cb_idler_after(void *data __UNUSED__) { TS("SLEEP"); first_idle = 0; + e_precache_end = 1; } } return 1; diff --git a/src/bin/e_start_main.c b/src/bin/e_start_main.c index 5a0348551..c86455a42 100644 --- a/src/bin/e_start_main.c +++ b/src/bin/e_start_main.c @@ -3,6 +3,10 @@ #include #include #include +#include +#include +#include +#include #ifdef HAVE_ALLOCA_H #include #endif @@ -248,6 +252,72 @@ _prefix_try_argv(char *argv0) return 0; } +static void +precache(void) +{ + FILE *f; + char *home; + char buf[4096], tbuf[256 * 1024]; + struct stat st; + int l, fd, children = 0, cret; + + home = getenv("HOME"); + if (home) + snprintf(buf, sizeof(buf), "%s/.e-precache", home); + else + snprintf(buf, sizeof(buf), "/tmp/.e-precache"); + f = fopen(buf, "r"); + if (!f) return; + unlink(buf); + if (fork()) return; + while (fgets(buf, sizeof(buf), f)); + rewind(f); + while (fgets(buf, sizeof(buf), f)) + { + l = strlen(buf); + if (l > 0) buf[l - 1] = 0; + if (!fork()) + { + if (buf[0] == 's') + { + stat(buf + 2, &st); + } + else if (buf[0] == 'o') + { + fd = open(buf + 2, O_RDONLY); + if (fd >= 0) + { + while (read(fd, tbuf, 256 * 1024) > 0); + close(fd); + } + } + else if (buf[0] == 'd') + { + fd = open(buf + 2, O_RDONLY); + if (fd >= 0) + { + while (read(fd, tbuf, 256 * 1024) > 0); + close(fd); + } + } + exit(0); + } + children++; + if (children > 400) + { + wait(&cret); + children--; + } + } + fclose(f); + while (children > 0) + { + wait(&cret); + children--; + } + exit(0); +} + int main(int argc, char **argv) { @@ -268,8 +338,10 @@ main(int argc, char **argv) else snprintf(buf, sizeof(buf), "%s/lib", _prefix_path); env_set("LD_LIBRARY_PATH", buf); -// snprintf(buf, sizeof(buf), "%s/lib/enlightenment/preload/e_precache.so", _prefix_path); -// env_set("LD_PRELOAD", buf); + snprintf(buf, sizeof(buf), "%s/lib/enlightenment/preload/e_precache.so", _prefix_path); + env_set("LD_PRELOAD", buf); + + precache(); args = alloca((argc + 1) * sizeof(char *)); args[0] = "enlightenment"; diff --git a/src/preload/Makefile.am b/src/preload/Makefile.am index f91560829..7e611ad59 100644 --- a/src/preload/Makefile.am +++ b/src/preload/Makefile.am @@ -3,12 +3,24 @@ MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I. \ -I$(top_srcdir) \ -I$(top_srcdir)src/preload \ - @x_cflags@ + @x_cflags@ \ + @e_cflags@ + pkgdir = $(libdir)/enlightenment/preload -pkg_LTLIBRARIES = e_hack.la -e_hack_la_SOURCES = \ -e_hack.c \ -e_hack.h -e_hack_la_LIBADD = @x_libs@ @dlopen_libs@ -e_hack_la_LDFLAGS = -module -avoid-version -e_hack_la_DEPENDENCIES = $(top_builddir)/config.h + +#pkg_LTLIBRARIES = e_hack.la e_precache.la +pkg_LTLIBRARIES = e_precache.la + +#e_hack_la_SOURCES = \ +#e_hack.c \ +#e_hack.h +#e_hack_la_LIBADD = @x_libs@ @dlopen_libs@ +#e_hack_la_LDFLAGS = -module -avoid-version +#e_hack_la_DEPENDENCIES = $(top_builddir)/config.h + +e_precache_la_SOURCES = \ +e_precache.c \ +e_precache.h +e_precache_la_LIBADD = @e_libs@ @dlopen_libs@ +e_precache_la_LDFLAGS = -module -avoid-version +e_precache_la_DEPENDENCIES = $(top_builddir)/config.h diff --git a/src/preload/e_precache.c b/src/preload/e_precache.c new file mode 100644 index 000000000..40189208f --- /dev/null +++ b/src/preload/e_precache.c @@ -0,0 +1,227 @@ +#include "config.h" +#include "e_precache.h" + + +static void *lib_evas = NULL; +static void *lib_ecore_file = NULL; +static void *lib_eet = NULL; + +static int *e_precache_end = 0; + +/* internal calls */ +static int log_fd = -1; +static int do_log = 0; + +static void +log_open(void) +{ + char buf[4096], *home; + + if (log_fd != -1) return; +#ifdef HAVE_UNSETENV + unsetenv("LD_PRELOAD"); +#else + if (getenv("LD_PRELOAD")) putenv("LD_PRELOAD"); +#endif + home = getenv("HOME"); + if (home) + snprintf(buf, sizeof(buf), "%s/.e-precache", home); + else + snprintf(buf, sizeof(buf), "/tmp/.e-precache"); + log_fd = open(buf, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR|S_IWUSR); + do_log = 1; + e_precache_end = dlsym(NULL, "e_precache_end"); +} + +static void +log_close(void) +{ + close(log_fd); + do_log = 0; +} + +static void +log_write(const char *type, const char *file) +{ + static Evas_Hash *s_hash = NULL; + static Evas_Hash *o_hash = NULL; + static Evas_Hash *d_hash = NULL; + char buf[2]; + + if ((*e_precache_end) && (*e_precache_end)) + { + log_close(); + return; + } + if (type[0] == 's') + { + if (evas_hash_find(s_hash, file)) return; + s_hash = evas_hash_add(s_hash, file, (void *)1); + } + else if (type[0] == 'o') + { + if (evas_hash_find(o_hash, file)) return; + o_hash = evas_hash_add(o_hash, file, (void *)1); + } + else if (type[0] == 'd') + { + if (evas_hash_find(d_hash, file)) return; + d_hash = evas_hash_add(d_hash, file, (void *)1); + } + buf[0] = type[0]; buf[1] = ' '; + write(log_fd, buf, 2); + write(log_fd, file, strlen(file)); + write(log_fd, "\n", 1); +} + + +/* intercepts */ +void +evas_object_image_file_set(Evas_Object *obj, const char *file, const char *key) +{ + static void (*func) (Evas_Object *obj, const char *file, const char *key) = NULL; + if (!func) + { + if (!lib_evas) + lib_evas = dlopen("libevas.so", RTLD_GLOBAL | RTLD_LAZY); + func = dlsym(lib_evas, "evas_object_image_file_set"); + log_open(); + } + if (do_log) log_write("o", file); + (*func) (obj, file, key); +} + +time_t +ecore_file_mod_time(const char *file) +{ + static time_t (*func) (const char *file) = NULL; + if (!func) + { + if (!lib_ecore_file) + lib_ecore_file = dlopen("libecore_file.so", RTLD_GLOBAL | RTLD_LAZY); + func = dlsym(lib_ecore_file, "ecore_file_mod_time"); + log_open(); + } + if (do_log) log_write("s", file); + return (*func) (file); +} + +int +ecore_file_size(const char *file) +{ + static int (*func) (const char *file) = NULL; + if (!func) + { + if (!lib_ecore_file) + lib_ecore_file = dlopen("libecore_file.so", RTLD_GLOBAL | RTLD_LAZY); + func = dlsym(lib_ecore_file, "ecore_file_size"); + log_open(); + } + if (do_log) log_write("s", file); + return (*func) (file); +} + +int +ecore_file_exists(const char *file) +{ + static int (*func) (const char *file) = NULL; + if (!func) + { + if (!lib_ecore_file) + lib_ecore_file = dlopen("libecore_file.so", RTLD_GLOBAL | RTLD_LAZY); + func = dlsym(lib_ecore_file, "ecore_file_exists"); + log_open(); + } + if (do_log) log_write("s", file); + return (*func) (file); +} + +int +ecore_file_is_dir(const char *file) +{ + static int (*func) (const char *file) = NULL; + if (!func) + { + if (!lib_ecore_file) + lib_ecore_file = dlopen("libecore_file.so", RTLD_GLOBAL | RTLD_LAZY); + func = dlsym(lib_ecore_file, "ecore_file_is_dir"); + log_open(); + } + if (do_log) log_write("s", file); + return (*func) (file); +} + +int +ecore_file_can_read(const char *file) +{ + static int (*func) (const char *file) = NULL; + if (!func) + { + if (!lib_ecore_file) + lib_ecore_file = dlopen("libecore_file.so", RTLD_GLOBAL | RTLD_LAZY); + func = dlsym(lib_ecore_file, "ecore_file_can_read"); + log_open(); + } + if (do_log) log_write("s", file); + return (*func) (file); +} + +int +ecore_file_can_write(const char *file) +{ + static int (*func) (const char *file) = NULL; + if (!func) + { + if (!lib_ecore_file) + lib_ecore_file = dlopen("libecore_file.so", RTLD_GLOBAL | RTLD_LAZY); + func = dlsym(lib_ecore_file, "ecore_file_can_write"); + log_open(); + } + if (do_log) log_write("s", file); + return (*func) (file); +} + +int +ecore_file_can_exec(const char *file) +{ + static int (*func) (const char *file) = NULL; + if (!func) + { + if (!lib_ecore_file) + lib_ecore_file = dlopen("libecore_file.so", RTLD_GLOBAL | RTLD_LAZY); + func = dlsym(lib_ecore_file, "ecore_file_can_exec"); + log_open(); + } + if (do_log) log_write("s", file); + return (*func) (file); +} + +Ecore_List * +ecore_file_ls(const char *file) +{ + static Ecore_List * (*func) (const char *file) = NULL; + if (!func) + { + if (!lib_ecore_file) + lib_ecore_file = dlopen("libecore_file.so", RTLD_GLOBAL | RTLD_LAZY); + func = dlsym(lib_ecore_file, "ecore_file_ls"); + log_open(); + } + if (do_log) log_write("d", file); + return (*func) (file); +} + +Eet_File * +eet_open(const char *file, Eet_File_Mode mode) +{ + static Eet_File * (*func) (const char *file, Eet_File_Mode mode) = NULL; + if (!func) + { + if (!lib_eet) + lib_eet = dlopen("libeet.so", RTLD_GLOBAL | RTLD_LAZY); + func = dlsym(lib_eet, "eet_open"); + log_open(); + } + if (do_log) log_write("o", file); + return (*func) (file, mode); +} diff --git a/src/preload/e_precache.h b/src/preload/e_precache.h new file mode 100644 index 000000000..71681b3c3 --- /dev/null +++ b/src/preload/e_precache.h @@ -0,0 +1,17 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_ALLOCA_H +#include +#endif +#include +#include +#include +#include