internalize pixbuf loading for 30% more speedup; because of GC extreme slowness,...
authorgc <gc>
Sun, 30 Mar 2008 18:14:04 +0000 (18:14 +0000)
committergc <gc>
Sun, 30 Mar 2008 18:14:04 +0000 (18:14 +0000)
bin/booh-classifier
ext/rbbooh.cc

index d33775b..65f0c62 100644 (file)
@@ -433,16 +433,11 @@ class Entry
             loader = Gdk::PixbufLoader.new
             loader.signal_connect('size-prepared') { |l, w, h|
                 r = specify_size.call(w, h)
-                msg 3, "specified sizes: #{r[0]} #{r[1]}"
+                #msg 3, "specified sizes: #{r[0]} #{r[1]}"
                 loader.set_size(*specify_size.call(w, h))
             }
             loader.signal_connect('area-prepared') { pixbuf = loader.pixbuf }
-            file = File.new(image_path)
-            while (chunk = file.read(4096)) != nil
-                loader.write(chunk)
-                Gtk.main_iteration while Gtk.events_pending?
-            end
-            file.close
+            loader.load_not_freezing_ui(image_path)
             loader.close
             if pixbuf.nil?
                 raise "Loaded pixbuf nil - #{path} #{image_path}"
@@ -475,6 +470,34 @@ end
 
 $allentries = []
 
+def gc
+    start = Time.now
+    GC.start
+    msg 3, "GC in #{Time.now - start} s"
+end
+
+def free_cache
+    i = $allentries.index($mainview.get_shown_entry)
+    return if i.nil?
+    start = Time.now
+    ($allentries.size - 1).downto($config['preload-distance'].to_i + 1) { |j|
+        index = i + j
+        if i + j < $allentries.size
+            $allentries[i+j].free_pixbuf_full
+            $allentries[i+j].free_pixbuf_main
+        end
+        if i - j > 0
+            $allentries[i-j].free_pixbuf_full
+            $allentries[i-j].free_pixbuf_main
+        end
+    }
+    msg 3, "freeing done in #{Time.now - start} s"
+    if get_mem > $config['cache-memory-use-figure'] * 3 / 4
+        gc
+        get_mem
+    end
+end
+
 def run_preloader_real
     msg 3, "*** >> main preloading triggered..."
     if $preloader_running
@@ -483,12 +506,11 @@ def run_preloader_real
     end
     $preloader_running = true
     if $mainview.get_shown_entry
-        mem = get_mem
-        if mem > $config['cache-memory-use-figure']
+        if get_mem > $config['cache-memory-use-figure']
             msg 3, "too much RSS, stopping preloading, triggering GC"
             $preloader_running = false
-            GC.start
-            msg 3, "GC finished"
+            gc
+            get_mem
             return
         end
         index = $allentries.index($mainview.get_shown_entry)
@@ -514,7 +536,7 @@ def run_preloader_real
                 return
             end
         end
-        check_memory_free_cache_if_needed
+        free_cache
     end
     $preloader_running = false
     msg 3, "*** << main preloading finished"
@@ -573,7 +595,7 @@ class MainView < Gtk::DrawingArea
             end
         end
         @entry = entry
-        redraw        
+        redraw
         run_preloader
         msg 3, "entry shown in: #{Time.now - t1} s"
     end
@@ -596,6 +618,7 @@ class MainView < Gtk::DrawingArea
         window.clear
         draw
         window.end_paint
+        Gtk.main_iteration while Gtk.events_pending?
     end
 
     def update_shown
@@ -641,30 +664,6 @@ class MainView < Gtk::DrawingArea
     end
 end
 
-def check_memory_free_cache_if_needed
-    i = $allentries.index($mainview.get_shown_entry)
-    return if i.nil?
-    if get_mem < $config['cache-memory-use-figure'] * 2 / 3
-        return
-    end
-    msg 3, "too much RSS, triggering GC"
-    GC.start
-    msg 3, "GC finished"
-    ($allentries.size - 1).downto(1) { |j|
-        if get_mem < $config['cache-memory-use-figure'] / 2
-            break
-        end
-        index = i + j
-        msg 3, "too much RSS, freeing full size of #{i+j} and #{i-j}..."
-        if i + j < $allentries.size
-            $allentries[i+j].free_pixbuf_full
-        end
-        if i - j > 0
-            $allentries[i-j].free_pixbuf_full
-        end
-    }
-end
-
 def autoscroll_if_needed(button)
     xpos_left = button.allocation.x
     xpos_right = button.allocation.x + button.allocation.width
@@ -953,7 +952,7 @@ end
 
 def show_entry(entry, i, tips)
     #- scope entry
-    msg 3, "showing entry #{entry}"
+    #msg 3, "showing entry #{entry}"
     entry.image = Gtk::Image.new(entry.pixbuf_thumbnail)
     if entry.type == 'video'
         entry.button = Gtk::Button.new.add(Gtk::HBox.new.pack_start(da1 = Gtk::DrawingArea.new.set_size_request($videoborder_pixbuf.width, -1), false, false).
@@ -1021,9 +1020,6 @@ def show_entries(allentries)
             end
 
             total_loaded_size += file_size(entry.path)
-            if i % 4 == 0
-                check_memory_free_cache_if_needed
-            end
             total_loaded_files += 1
             i += 1
             if i > $config['preload-distance'].to_i && i <= $config['preload-distance'].to_i * 2
index a2023f1..c3e1fa5 100644 (file)
@@ -174,6 +174,26 @@ static VALUE modify_bg(VALUE self, VALUE state, VALUE color) {
         return self;
 }
 
+// internalize pixbuf loading for 30% more speedup
+static VALUE load_not_freezing_ui(VALUE self, VALUE path) {
+        char buf[65536];
+        size_t amount;
+        GdkPixbufLoader* loader = GDK_PIXBUF_LOADER(RVAL2GOBJ(self));
+        GError* error = NULL;
+        FILE* f = fopen(RVAL2CSTR(path), "r");
+        while ((amount = fread(buf, 1, 65536, f)) > 0) {
+                if (!gdk_pixbuf_loader_write(loader, (const guchar*) buf, amount, &error)) {
+                        fclose(f);
+                        RAISE_GERROR(error);
+                }
+                while (gtk_events_pending()) {
+                        gtk_main_iteration();
+                }
+        }
+        fclose(f);
+        return self;
+}
+
 extern "C" {
 void 
 Init_libadds()
@@ -189,6 +209,9 @@ Init_libadds()
     cinfo = (RGObjClassInfo*)rbgobj_lookup_class_by_gtype(GTK_TYPE_WIDGET, Qnil);
     rb_define_method(cinfo->klass, "modify_bg", (VALUE (*)(...)) modify_bg, 2);
 
+    cinfo = (RGObjClassInfo*)rbgobj_lookup_class_by_gtype(GDK_TYPE_PIXBUF_LOADER, Qnil);
+    rb_define_method(cinfo->klass, "load_not_freezing_ui", (VALUE (*)(...)) load_not_freezing_ui, 1);
+
     VALUE exif = rb_define_module("Exif");
     rb_define_module_function(exif, "orientation", (VALUE (*)(...)) exif_orientation, 1);
     rb_define_module_function(exif, "set_orientation", (VALUE (*)(...)) exif_set_orientation, 2);