From 9389a2ef3af7df2a0cb81e5f579cebac91fb49d5 Mon Sep 17 00:00:00 2001 From: Yevgen Muntyan <17531749+muntyan@users.noreply.github.com> Date: Tue, 13 Mar 2007 01:29:11 -0500 Subject: [PATCH] stat() all files in folder immediately; do not store stat buffer in file structure, to reduce memory consumption --- moo/moofileview/moofile-private.h | 4 +-- moo/moofileview/moofile.c | 38 +++++++++++++++++---------- moo/moofileview/moofilesystem.c | 26 +++++++++++++++++++ moo/moofileview/moofolder-private.h | 2 ++ moo/moofileview/moofolder.c | 40 ++++++++++++++++++++++++++--- 5 files changed, 90 insertions(+), 20 deletions(-) diff --git a/moo/moofileview/moofile-private.h b/moo/moofileview/moofile-private.h index a1a8b78d..b1c0cf4e 100644 --- a/moo/moofileview/moofile-private.h +++ b/moo/moofileview/moofile-private.h @@ -52,8 +52,7 @@ struct _MooFile guint8 icon; const char *mime_type; int ref_count; -/* TODO: who needs whole structure? */ - struct stat statbuf; + struct stat *statbuf; }; @@ -88,6 +87,7 @@ guint8 _moo_file_get_icon_type (MooFile *file, const char *dirname); void _moo_file_stat (MooFile *file, const char *dirname); +void _moo_file_free_statbuf (MooFile *file); void _moo_file_find_mime_type (MooFile *file, const char *path); diff --git a/moo/moofileview/moofile.c b/moo/moofileview/moofile.c index e7a55657..65a7644b 100644 --- a/moo/moofileview/moofile.c +++ b/moo/moofileview/moofile.c @@ -87,10 +87,7 @@ void _moo_file_find_mime_type (MooFile *file, const char *path) { - if (file->flags & MOO_FILE_HAS_STAT) - file->mime_type = xdg_mime_get_mime_type_for_file (path, &file->statbuf); - else - file->mime_type = xdg_mime_get_mime_type_for_file (path, NULL); + file->mime_type = xdg_mime_get_mime_type_for_file (path, file->statbuf); if (!file->mime_type || !file->mime_type[0]) { @@ -131,7 +128,7 @@ _moo_file_new (const char *dirname, g_return_val_if_fail (display_name != NULL, NULL); } - file = g_new0 (MooFile, 1); + file = _moo_new0 (MooFile); file->ref_count = 1; file->name = g_strdup (basename); @@ -171,7 +168,8 @@ _moo_file_unref (MooFile *file) g_free (file->case_display_name); g_free (file->collation_key); g_free (file->link_target); - g_free (file); + _moo_free (struct stat, file->statbuf); + _moo_free (MooFile, file); } } @@ -194,7 +192,10 @@ _moo_file_stat (MooFile *file, errno = 0; - if (g_lstat (fullname, &file->statbuf) != 0) + if (!file->statbuf) + file->statbuf = _moo_new (struct stat); + + if (g_lstat (fullname, file->statbuf) != 0) { if (errno == ENOENT) { @@ -219,7 +220,7 @@ _moo_file_stat (MooFile *file, else { #ifdef S_ISLNK - if (S_ISLNK (file->statbuf.st_mode)) + if (S_ISLNK (file->statbuf->st_mode)) { static char buf[1024]; gssize len; @@ -227,7 +228,7 @@ _moo_file_stat (MooFile *file, file->info |= MOO_FILE_INFO_IS_LINK; errno = 0; - if (g_stat (fullname, &file->statbuf) != 0) + if (g_stat (fullname, file->statbuf) != 0) { if (errno == ENOENT) { @@ -272,22 +273,22 @@ _moo_file_stat (MooFile *file, if ((file->info & MOO_FILE_INFO_EXISTS) && !(file->info & MOO_FILE_INFO_IS_LOCKED)) { - if (S_ISDIR (file->statbuf.st_mode)) + if (S_ISDIR (file->statbuf->st_mode)) file->info |= MOO_FILE_INFO_IS_DIR; #ifdef S_ISBLK - else if (S_ISBLK (file->statbuf.st_mode)) + else if (S_ISBLK (file->statbuf->st_mode)) file->info |= MOO_FILE_INFO_IS_BLOCK_DEV; #endif #ifdef S_ISCHR - else if (S_ISCHR (file->statbuf.st_mode)) + else if (S_ISCHR (file->statbuf->st_mode)) file->info |= MOO_FILE_INFO_IS_CHAR_DEV; #endif #ifdef S_ISFIFO - else if (S_ISFIFO (file->statbuf.st_mode)) + else if (S_ISFIFO (file->statbuf->st_mode)) file->info |= MOO_FILE_INFO_IS_FIFO; #endif #ifdef S_ISSOCK - else if (S_ISSOCK (file->statbuf.st_mode)) + else if (S_ISSOCK (file->statbuf->st_mode)) file->info |= MOO_FILE_INFO_IS_SOCKET; #endif } @@ -306,6 +307,15 @@ _moo_file_stat (MooFile *file, g_free (fullname); } +void +_moo_file_free_statbuf (MooFile *file) +{ + g_return_if_fail (file != NULL); + _moo_free (struct stat, file->statbuf); + file->statbuf = NULL; + file->flags &= ~MOO_FILE_HAS_STAT; +} + gboolean _moo_file_test (const MooFile *file, diff --git a/moo/moofileview/moofilesystem.c b/moo/moofileview/moofilesystem.c index bd0b955a..e6b97e77 100644 --- a/moo/moofileview/moofilesystem.c +++ b/moo/moofileview/moofilesystem.c @@ -47,6 +47,7 @@ struct _MooFileSystemPrivate { GHashTable *folders; MooFileWatch *fam; FoldersCache cache; + guint debug_timeout; }; static MooFileSystem *fs_instance = NULL; @@ -210,6 +211,25 @@ _moo_file_system_folder_finalized (MooFileSystem *fs, } +static void +calc_mem_hash_cb (G_GNUC_UNUSED const char *name, + MooFolder *folder, + gsize *mem) +{ + mem[0] += _moo_folder_mem_usage (folder); + mem[1] += g_hash_table_size (folder->impl->files); +} + +static gboolean +debug_timeout (MooFileSystem *fs) +{ + gsize mem[2] = {0, 0}; + g_hash_table_foreach (fs->priv->folders, (GHFunc) calc_mem_hash_cb, mem); + g_print ("%u bytes in %u files\n", mem[0], mem[1]); + return TRUE; +} + + static void _moo_file_system_init (MooFileSystem *fs) { @@ -217,6 +237,9 @@ _moo_file_system_init (MooFileSystem *fs) fs->priv->folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); fs->priv->cache.queue = g_queue_new (); fs->priv->cache.paths = g_hash_table_new (g_str_hash, g_str_equal); + + if (0) + fs->priv->debug_timeout = g_timeout_add (5000, (GSourceFunc) debug_timeout, fs); } @@ -238,6 +261,9 @@ moo_file_system_dispose (GObject *object) moo_file_watch_unref (fs->priv->fam); } + if (fs->priv->debug_timeout) + g_source_remove (fs->priv->debug_timeout); + g_free (fs->priv); fs->priv = NULL; } diff --git a/moo/moofileview/moofolder-private.h b/moo/moofileview/moofolder-private.h index 79eeb841..ac3f4a27 100644 --- a/moo/moofileview/moofolder-private.h +++ b/moo/moofileview/moofolder-private.h @@ -104,6 +104,8 @@ void _moo_file_system_folder_finalized (MooFileSystem *fs, void _moo_file_system_folder_deleted (MooFileSystem *fs, MooFolderImpl *folder); +gsize _moo_folder_mem_usage (MooFolder *folder); + G_END_DECLS diff --git a/moo/moofileview/moofolder.c b/moo/moofileview/moofolder.c index 6b2a8f75..2299d255 100644 --- a/moo/moofileview/moofolder.c +++ b/moo/moofileview/moofolder.c @@ -231,6 +231,31 @@ moo_folder_dispose (GObject *object) } +static void +add_file_size (G_GNUC_UNUSED const char *filename, + MooFile *file, + gsize *mem) +{ + *mem += sizeof *file; +#define STRING_SIZE(s) ((s) ? (strlen (s) + 1) : 0) + *mem += STRING_SIZE (file->name); + *mem += STRING_SIZE (file->link_target); + *mem += STRING_SIZE (file->display_name); + *mem += STRING_SIZE (file->case_display_name); + *mem += STRING_SIZE (file->collation_key); +#undef STRING_SIZE +} + +gsize +_moo_folder_mem_usage (MooFolder *folder) +{ + gsize mem = 0; + mem += sizeof (MooFolderImpl); + g_hash_table_foreach (folder->impl->files, (GHFunc) add_file_size, &mem); + return mem; +} + + MooFolder * _moo_folder_new_with_impl (MooFolderImpl *impl) { @@ -472,6 +497,7 @@ get_names (MooFolderImpl *impl) file->icon = _moo_file_icon_blank (); g_hash_table_insert (impl->files, g_strdup (name), file); added = g_slist_prepend (added, file); + _moo_file_stat (file, impl->path); } else { @@ -655,6 +681,7 @@ get_icons_a_bit (MooFolderImpl *impl) } #endif + _moo_file_free_statbuf (file); _moo_file_unref (file); g_slist_free (changed); @@ -914,6 +941,8 @@ file_created (MooFolderImpl *impl, } #endif + _moo_file_free_statbuf (file); + g_hash_table_insert (impl->files, g_strdup (name), file); list = g_slist_append (NULL, file); folder_emit_files (impl, FILES_ADDED, list); @@ -1011,9 +1040,10 @@ moo_file_get_type_string (MooFile *file) /* XXX */ static char * -moo_file_get_size_string (MooFile *file) +get_size_string (struct stat *statbuf) { - return g_strdup_printf ("%" G_GINT64_FORMAT, (MooFileSize) file->statbuf.st_size); + g_return_val_if_fail (statbuf != NULL, NULL); + return g_strdup_printf ("%" G_GINT64_FORMAT, (MooFileSize) statbuf->st_size); } @@ -1031,7 +1061,9 @@ moo_file_get_mtime_string (MooFile *file) return NULL; #endif - if (strftime (buf, 1024, "%x %X", localtime ((time_t*)&file->statbuf.st_mtime))) + g_return_val_if_fail (file->statbuf != NULL, NULL); + + if (strftime (buf, 1024, "%x %X", localtime ((time_t*)&file->statbuf->st_mtime))) return g_strdup (buf); else return NULL; @@ -1092,7 +1124,7 @@ _moo_folder_get_file_info (MooFolder *folder, if (!(file->info & MOO_FILE_INFO_IS_DIR)) { g_ptr_array_add (array, g_strdup ("Size:")); - g_ptr_array_add (array, moo_file_get_size_string (file)); + g_ptr_array_add (array, get_size_string (file->statbuf)); } mtime = moo_file_get_mtime_string (file);