Make VFS faster a bit.

Each VSF entry is added to VFS using vfs_s_insert_entry() via
g_list_append(). For long lists, a lot of walking through entire list
is performed. To get rid that, change type of vfs_s_inode::subdir from
GList to GQueue.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Andrew Borodin 2015-01-16 10:56:08 +03:00
parent a5826c3f6e
commit 7ce3ca0991
3 changed files with 24 additions and 14 deletions

View File

@ -196,7 +196,7 @@ vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root,
for (pseg = 0; path[pseg] != '\0' && !IS_PATH_SEP (path[pseg]); pseg++)
;
for (iter = root->subdir; iter != NULL; iter = g_list_next (iter))
for (iter = g_queue_peek_head_link (root->subdir); iter != NULL; iter = g_list_next (iter))
{
ent = VFS_ENTRY (iter->data);
if (strlen (ent->name) == pseg && strncmp (ent->name, path, pseg) == 0)
@ -259,7 +259,7 @@ vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
return ent;
}
iter = g_list_find_custom (root->subdir, path, (GCompareFunc) vfs_s_entry_compare);
iter = g_queue_find_custom (root->subdir, path, (GCompareFunc) vfs_s_entry_compare);
ent = iter != NULL ? VFS_ENTRY (iter->data) : NULL;
if (ent != NULL && !VFS_SUBCLASS (me)->dir_uptodate (me, ent->ino))
@ -286,7 +286,7 @@ vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
vfs_s_insert_entry (me, root, ent);
iter = g_list_find_custom (root->subdir, path, (GCompareFunc) vfs_s_entry_compare);
iter = g_queue_find_custom (root->subdir, path, (GCompareFunc) vfs_s_entry_compare);
ent = iter != NULL ? VFS_ENTRY (iter->data) : NULL;
}
if (ent == NULL)
@ -441,7 +441,7 @@ vfs_s_opendir (const vfs_path_t * vpath)
}
#endif
info = g_new (struct dirhandle, 1);
info->cur = dir->subdir;
info->cur = g_queue_peek_head_link (dir->subdir);
info->dir = dir;
return info;
@ -888,6 +888,7 @@ vfs_s_new_inode (struct vfs_class *me, struct vfs_s_super *super, struct stat *i
if (initstat != NULL)
ino->st = *initstat;
ino->super = super;
ino->subdir = g_queue_new ();
ino->st.st_nlink = 0;
ino->st.st_ino = VFS_SUBCLASS (me)->inode_counter++;
ino->st.st_dev = VFS_SUBCLASS (me)->rdev;
@ -914,8 +915,16 @@ vfs_s_free_inode (struct vfs_class *me, struct vfs_s_inode *ino)
return;
}
while (ino->subdir != NULL)
vfs_s_free_entry (me, VFS_ENTRY (ino->subdir->data));
while (g_queue_get_length (ino->subdir) != 0)
{
struct vfs_s_entry *entry;
entry = VFS_ENTRY (g_queue_peek_head (ino->subdir));
vfs_s_free_entry (me, entry);
}
g_queue_free (ino->subdir);
ino->subdir = NULL;
CALL (free_inode) (me, ino);
g_free (ino->linkname);
@ -951,7 +960,7 @@ void
vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
{
if (ent->dir != NULL)
ent->dir->subdir = g_list_remove (ent->dir->subdir, ent);
g_queue_remove (ent->dir->subdir, ent);
MC_PTR_FREE (ent->name);
@ -974,7 +983,7 @@ vfs_s_insert_entry (struct vfs_class *me, struct vfs_s_inode *dir, struct vfs_s_
ent->dir = dir;
ent->ino->st.st_nlink++;
dir->subdir = g_list_append (dir->subdir, ent);
g_queue_push_tail (dir->subdir, ent);
}
/* --------------------------------------------------------------------------------------------- */
@ -1708,7 +1717,8 @@ vfs_s_normalize_filename_leading_spaces (struct vfs_s_inode *root_inode, size_t
{
GList *iter;
for (iter = root_inode->subdir; iter != NULL; iter = g_list_next (iter))
for (iter = g_queue_peek_head_link (root_inode->subdir); iter != NULL;
iter = g_list_next (iter))
{
struct vfs_s_entry *entry = VFS_ENTRY (iter->data);

View File

@ -87,7 +87,7 @@ struct vfs_s_inode
struct vfs_s_entry *ent; /* Our entry in the parent directory -
use only for directories because they
cannot be hardlinked */
GList *subdir; /* If this is a directory, its entry. List of vfs_s_entry */
GQueue *subdir; /* If this is a directory, its entry. List of vfs_s_entry */
struct stat st; /* Parameters of this inode */
char *linkname; /* Symlink's contents */
char *localname; /* Filename of local file, if we have one */

View File

@ -271,7 +271,7 @@ extfs_find_entry_int (struct vfs_s_inode *dir, const char *name, GSList * list,
}
pdir = pent;
pl = g_list_find_custom (pent->ino->subdir, p, vfs_s_entry_compare);
pl = g_queue_find_custom (pent->ino->subdir, p, vfs_s_entry_compare);
pent = pl != NULL ? VFS_ENTRY (pl->data) : NULL;
if (pent != NULL && q + 1 > name_end)
{
@ -512,13 +512,13 @@ extfs_read_archive (FILE * extfsd, struct extfs_super_t *current_archive)
{
entry = extfs_entry_new (super->me, p, pent->ino);
entry->dir = pent->ino;
pent->ino->subdir = g_list_append (pent->ino->subdir, entry);
g_queue_push_tail (pent->ino->subdir, entry);
}
else
{
entry = extfs_entry_new (super->me, p, super->root);
entry->dir = super->root;
super->root->subdir = g_list_append (super->root->subdir, entry);
g_queue_push_tail (super->root->subdir, entry);
}
if (!S_ISLNK (hstat.st_mode) && (current_link_name != NULL))
@ -1014,7 +1014,7 @@ extfs_opendir (const vfs_path_t * vpath)
ERRNOR (ENOTDIR, NULL);
info = g_new (GList *, 1);
*info = entry->ino->subdir;
*info = g_queue_peek_head_link (entry->ino->subdir);
return info;
}