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
This commit is contained in:
Carsten Haitzler 2006-10-22 10:03:59 +00:00
parent f6ab7d952e
commit a0d07f5c79
7 changed files with 343 additions and 11 deletions

View File

@ -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

View File

@ -1,2 +1,2 @@
MAINTAINERCLEANFILES = Makefile.in
SUBDIRS = bin modules
SUBDIRS = bin modules preload

View File

@ -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;

View File

@ -3,6 +3,10 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <fcntl.h>
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#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";

View File

@ -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

227
src/preload/e_precache.c Normal file
View File

@ -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);
}

17
src/preload/e_precache.h Normal file
View File

@ -0,0 +1,17 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <dlfcn.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <fcntl.h>
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#include <Evas.h>
#include <Ecore.h>
#include <Ecore_File.h>
#include <Eet.h>