Re: Nautilus thumbnail creation SLOW. gThumb does a much faster job.



On 4/11/07, Alexander Larsson <alexl redhat com> wrote:
> Now I do notice an interesting possible slow down in this code though
> at line 587 the thumbnailer walks through the list of thumbnails to
> check that the new thumbnail isn't already scheduled for creation, and
> then it walks the list again at line 595 to append schedule the new
> thumbnail. With a few thousand entries this could slow it down a
> little. Would having a hashtable that stores scheduled thumbnails as
> well as in the list help any? Maybe storing the end-of-list pointer so
> appending thumbnail to the list is O(1) instead of O(n)
>
> It also has to loop through this list to remove the item from the list
> at various places (such as line 427), although if the list is FIFO
> then that won't be a problem. We could however hold a pointer to the
> thumbnail's list member in the hashtable so that removing it would be
> O(1) as well.
>
> Would this help speed up thumbnailing with large directories?

I doubt it would make a noticable difference except in enourmous
directories, but it probably wouldn't hurt.

Attached is a patch. In my very unscientific test it seems to speed up
thumbnailing in a large directory (I had about 1000 images in my dir)
slightly, my timings were about 1minute without the patch and about
50seconds with. (The approximations because its hard to know when the
thumbnailing has stopped)

Be nice if people could test it, but i'm not sure if its worth it really.

iain
Index: libnautilus-private/nautilus-thumbnails.c
===================================================================
--- libnautilus-private/nautilus-thumbnails.c	(revision 12857)
+++ libnautilus-private/nautilus-thumbnails.c	(working copy)
@@ -90,6 +90,10 @@
 /* The list of NautilusThumbnailInfo structs containing information about the
    thumbnails we are making. Lock thumbnails_mutex when accessing this. */
 static volatile GList *thumbnails_to_make = NULL;
+static volatile GList *thumbnails_to_make_end = NULL;
+
+static GHashTable *thumbnails_to_make_hash = NULL;
+
 /* The currently thumbnailed icon. it also exists in the thumbnails_to_make list
  * to avoid adding it again. Lock thumbnails_mutex when accessing this. */
 static NautilusThumbnailInfo *currently_thumbnailing = NULL;
@@ -429,6 +433,7 @@
 				   compare_thumbnail_info);
 
 	if (node && node->data != currently_thumbnailing) {
+		g_hash_table_remove (thumbnails_to_make_hash, file_uri);
 		free_thumbnail_info (node->data);
 		thumbnails_to_make = g_list_delete_link ((GList *)thumbnails_to_make, node);
 	}
@@ -446,6 +451,7 @@
 void
 nautilus_thumbnail_remove_all_from_queue (void)
 {
+	NautilusThumbnailInfo *info;
 	GList *l, *next;
 	
 #ifdef DEBUG_THUMBNAILS
@@ -461,6 +467,9 @@
 	while (l != NULL) {
 		next = l->next;
 		if (l->data != currently_thumbnailing) {
+			info = l->data;
+			g_hash_table_remove (thumbnails_to_make_hash, 
+					     info->image_uri);
 			free_thumbnail_info (l->data);
 			thumbnails_to_make = g_list_delete_link ((GList *)thumbnails_to_make, l);
 		}
@@ -554,10 +563,14 @@
 	time_t file_mtime = 0;
 	NautilusThumbnailInfo *info;
 	NautilusThumbnailInfo *existing_info;
-	GList *existing;
 
 	nautilus_file_set_is_thumbnailing (file, TRUE);
 
+	if (thumbnails_to_make_hash == NULL) {
+		thumbnails_to_make_hash = g_hash_table_new (g_str_hash,
+							    g_str_equal);
+	}
+
 	info = g_new0 (NautilusThumbnailInfo, 1);
 	info->image_uri = nautilus_file_get_uri (file);
 	info->mime_type = nautilus_file_get_mime_type (file);
@@ -585,16 +598,21 @@
 	 *********************************/
 
 	/* Check if it is already in the list of thumbnails to make. */
-	existing = g_list_find_custom ((GList*) thumbnails_to_make, info,
-				       compare_thumbnail_info);
-	if (existing == NULL) {
+	existing_info = g_hash_table_lookup (thumbnails_to_make_hash,
+					     info->image_uri);
+	if (existing_info == NULL) {
 		/* Add the thumbnail to the list. */
 #ifdef DEBUG_THUMBNAILS
 		g_message ("(Main Thread) Adding thumbnail: %s\n",
 			   info->image_uri);
 #endif
-		thumbnails_to_make = g_list_append ((GList*) thumbnails_to_make, info);
+		thumbnails_to_make_end = g_list_append ((GList*) thumbnails_to_make_end, info);
+		if (thumbnails_to_make == NULL) {
+			thumbnails_to_make = thumbnails_to_make_end;
+		}
 		
+		g_hash_table_insert (thumbnails_to_make_hash,
+				     info->image_uri, info);
 		/* If the thumbnail thread isn't running, and we haven't
 		   scheduled an idle function to start it up, do that now.
 		   We don't want to start it until all the other work is done,
@@ -609,7 +627,6 @@
 			   info->image_uri);
 #endif
 		/* The file in the queue might need a new original mtime */
-		existing_info = existing->data;
 		existing_info->original_file_mtime = info->original_file_mtime;
 		free_thumbnail_info (info);
 	}
@@ -657,6 +674,7 @@
 		    currently_thumbnailing->original_file_mtime == current_orig_mtime) {
 			g_assert (info == currently_thumbnailing);
 			free_thumbnail_info (currently_thumbnailing);
+
 			thumbnails_to_make = g_list_remove ((GList*) thumbnails_to_make, currently_thumbnailing);
 		}
 		currently_thumbnailing = NULL;
@@ -668,6 +686,7 @@
 #ifdef DEBUG_THUMBNAILS
 			g_message ("(Thumbnail Thread) Exiting\n");
 #endif
+			thumbnails_to_make_end = NULL;
 			thumbnail_thread_is_running = FALSE;
 			pthread_mutex_unlock (&thumbnails_mutex);
 			pthread_exit (NULL);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]