This patch makes VFS a bit faster by replacing GSList with GPtrArray
and using a clever trick to avoid doing list/array searches on every
VFS lookup.
Andrew Zabolotny <zap@homelink.ru>
diff -ur mc-4.6.2-pre1.orig/vfs/fish.c mc-4.6.2-pre1/vfs/fish.c
old
|
new
|
|
635 | 635 | #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 || (defined _LARGE_FILES && _LARGE_FILES) |
636 | 636 | if (sscanf( reply_str, "%llu", &fh->u.fish.total )!=1) |
637 | 637 | #else |
638 | | if (sscanf( reply_str, "%u", &fh->u.fish.total )!=1) |
| 638 | if (sscanf (reply_str, "%lu", &fh->u.fish.total) != 1) |
639 | 639 | #endif |
640 | 640 | ERRNOR (E_REMOTE, 0); |
641 | 641 | return 1; |
diff -ur mc-4.6.2-pre1.orig/vfs/vfs.c mc-4.6.2-pre1/vfs/vfs.c
old
|
new
|
|
63 | 63 | void *fsinfo; |
64 | 64 | }; |
65 | 65 | |
66 | | static GSList *vfs_openfiles; |
| 66 | static GPtrArray *vfs_openfiles; |
| 67 | static long vfs_free_handle_list = -1; |
67 | 68 | #define VFS_FIRST_HANDLE 100 |
68 | 69 | |
69 | 70 | static struct vfs_class *localfs_class; |
… |
… |
|
72 | 73 | static int |
73 | 74 | vfs_new_handle (struct vfs_class *vclass, void *fsinfo) |
74 | 75 | { |
75 | | static int vfs_handle_counter = VFS_FIRST_HANDLE; |
76 | 76 | struct vfs_openfile *h; |
77 | 77 | |
78 | 78 | h = g_new (struct vfs_openfile, 1); |
79 | | h->handle = vfs_handle_counter++; |
80 | 79 | h->fsinfo = fsinfo; |
81 | 80 | h->vclass = vclass; |
82 | | vfs_openfiles = g_slist_prepend (vfs_openfiles, h); |
83 | | return h->handle; |
84 | | } |
85 | 81 | |
86 | | /* Function to match handle, passed to g_slist_find_custom() */ |
87 | | static gint |
88 | | vfs_cmp_handle (gconstpointer a, gconstpointer b) |
89 | | { |
90 | | if (!a) |
91 | | return 1; |
92 | | return ((struct vfs_openfile *) a)->handle != (long) b; |
| 82 | /* Allocate the first free handle */ |
| 83 | h->handle = vfs_free_handle_list; |
| 84 | if (h->handle == -1) { |
| 85 | /* No free allocated handles, allocate one */ |
| 86 | h->handle = vfs_openfiles->len; |
| 87 | g_ptr_array_add (vfs_openfiles, h); |
| 88 | } else { |
| 89 | vfs_free_handle_list = (long) g_ptr_array_index (vfs_openfiles, vfs_free_handle_list); |
| 90 | g_ptr_array_index (vfs_openfiles, h->handle) = h; |
| 91 | } |
| 92 | |
| 93 | h->handle += VFS_FIRST_HANDLE; |
| 94 | return h->handle; |
93 | 95 | } |
94 | 96 | |
95 | 97 | /* Find VFS class by file handle */ |
96 | 98 | static inline struct vfs_class * |
97 | 99 | vfs_op (int handle) |
98 | 100 | { |
99 | | GSList *l; |
100 | 101 | struct vfs_openfile *h; |
101 | 102 | |
102 | | l = g_slist_find_custom (vfs_openfiles, (void *) (long) handle, |
103 | | vfs_cmp_handle); |
104 | | if (!l) |
105 | | return NULL; |
106 | | h = (struct vfs_openfile *) l->data; |
| 103 | if (handle < VFS_FIRST_HANDLE || |
| 104 | handle - VFS_FIRST_HANDLE >= vfs_openfiles->len) |
| 105 | return NULL; |
| 106 | |
| 107 | h = (struct vfs_openfile *) g_ptr_array_index ( |
| 108 | vfs_openfiles, handle - VFS_FIRST_HANDLE); |
107 | 109 | if (!h) |
108 | | return NULL; |
| 110 | return NULL; |
| 111 | |
| 112 | g_assert (h->handle == handle); |
| 113 | |
109 | 114 | return h->vclass; |
110 | 115 | } |
111 | 116 | |
… |
… |
|
113 | 118 | static inline void * |
114 | 119 | vfs_info (int handle) |
115 | 120 | { |
116 | | GSList *l; |
117 | 121 | struct vfs_openfile *h; |
118 | 122 | |
119 | | l = g_slist_find_custom (vfs_openfiles, (void *) (long) handle, |
120 | | vfs_cmp_handle); |
121 | | if (!l) |
122 | | return NULL; |
123 | | h = (struct vfs_openfile *) l->data; |
| 123 | if (handle < VFS_FIRST_HANDLE || |
| 124 | handle - VFS_FIRST_HANDLE >= vfs_openfiles->len) |
| 125 | return NULL; |
| 126 | |
| 127 | h = (struct vfs_openfile *) g_ptr_array_index ( |
| 128 | vfs_openfiles, handle - VFS_FIRST_HANDLE); |
124 | 129 | if (!h) |
125 | | return NULL; |
| 130 | return NULL; |
| 131 | |
| 132 | g_assert (h->handle == handle); |
| 133 | |
126 | 134 | return h->fsinfo; |
127 | 135 | } |
128 | 136 | |
… |
… |
|
130 | 138 | static inline void |
131 | 139 | vfs_free_handle (int handle) |
132 | 140 | { |
133 | | GSList *l; |
134 | | |
135 | | l = g_slist_find_custom (vfs_openfiles, (void *) (long) handle, |
136 | | vfs_cmp_handle); |
137 | | vfs_openfiles = g_slist_delete_link (vfs_openfiles, l); |
| 141 | if (handle < VFS_FIRST_HANDLE || |
| 142 | handle - VFS_FIRST_HANDLE >= vfs_openfiles->len) |
| 143 | return; |
| 144 | |
| 145 | g_ptr_array_index (vfs_openfiles, handle - VFS_FIRST_HANDLE) = |
| 146 | (void *) vfs_free_handle_list; |
| 147 | vfs_free_handle_list = handle - VFS_FIRST_HANDLE; |
138 | 148 | } |
139 | 149 | |
140 | 150 | static struct vfs_class *vfs_list; |
… |
… |
|
867 | 877 | void |
868 | 878 | vfs_init (void) |
869 | 879 | { |
| 880 | /* create the VFS handle array */ |
| 881 | vfs_openfiles = g_ptr_array_new (); |
| 882 | |
870 | 883 | /* localfs needs to be the first one */ |
871 | 884 | init_localfs(); |
872 | 885 | /* fallback value for vfs_get_class() */ |
… |
… |
|
909 | 922 | if (vfs->done) |
910 | 923 | (*vfs->done) (vfs); |
911 | 924 | |
912 | | g_slist_free (vfs_openfiles); |
| 925 | g_ptr_array_free (vfs_openfiles, TRUE); |
913 | 926 | } |
914 | 927 | |
915 | 928 | /* |