increase a lot merging performance by workarounding some slow uses of rexml
authorGuillaume Cottenceau <gcottenc@gmail.com>
Thu, 25 Dec 2008 20:11:09 +0000 (21:11 +0100)
committerGuillaume Cottenceau <gcottenc@gmail.com>
Thu, 25 Dec 2008 20:11:09 +0000 (21:11 +0100)
bin/booh-backend

index edd8febeda6723c0bc9e416123fec5be2727f445..f9eb1f173ddef2bf365d19e4b32c24177e84e876 100755 (executable)
@@ -797,6 +797,14 @@ def walk_source_dir
         end
         xmldir.delete_attribute('already-generated')
 
+        #- preprocess all the existing elements, rexml is slow with that
+        optelements = {}
+        xmldir.elements.each { |elem|
+            if filename = elem.attributes['filename']
+                optelements[elem.name + '|' + filename] = elem
+            end
+        }
+
         #- read images/videos entries from config or from directories depending on mode
         entries = []
         if $mode == 'use_config' || $mode == 'use_config_changetheme'
@@ -809,25 +817,20 @@ def walk_source_dir
         else
             msg 2, _("Examining %s...") % dir
             entries = Dir.entries(dir).sort
-            #- preprocess all the existing elements, rexml is slow with that
-            optelements = []
-            xmldir.elements.each { |elem|
-                optelements << elem.name + '|' + elem.attributes['filename']
-            }
             #- populate config in case of gen_config, add new files in case of merge_config
             for file in entries
                 if file =~ /['"\[\]]/
                     msg 1, _("Ignoring %s, contains one of forbidden characters: '\"[]") % "#{dir}/#{file}"
                 else
                     type = entry2type(file)
-                    if type && ! optelements.include?(type + '|' + utf8(file))
+                    if type && ! optelements[type + '|' + utf8(file)]
                         #- hack: don't run identify (which is slow) if format only contains default %t
                         if $commentsformat && type == 'image' && $commentsformat != '%t'
                             comment = utf8(`identify -format "#{$commentsformat}" '#{dir}/#{file}'`.chomp.sub(/\.$/, ''))
                         else
                             comment = utf8cut(file.sub(/\.[^\.]+$/, ''), 18)
                         end
-                        xmldir.add_element type, { "filename" => utf8(file), "caption" => comment }
+                        optelements[type + '|' + utf8(file)] = xmldir.add_element(type, { "filename" => utf8(file), "caption" => comment })
                     end
                 end
             end
@@ -945,12 +948,12 @@ def walk_source_dir
         images.each { |img|
             info("processing element")
             base_dest_img = dest_dir + '/' + make_dest_filename(img.sub(/\.[^\.]+$/, ''))
+            elem = optelements['image|' + utf8(img)]
             if $forgui
                 thumbnail_dest_img = base_dest_img + "-#{$default_size['thumbnails']}.jpg"
-                gen_thumbnails_element("#{dir}/#{img}", xmldir, true, [ { 'filename' => thumbnail_dest_img, 'size' => $default_size['thumbnails'] } ])
+                gen_thumbnails_element("#{dir}/#{img}", elem, true, [ { 'filename' => thumbnail_dest_img, 'size' => $default_size['thumbnails'] } ])
             else
                 todo = []
-                elem = xmldir.elements["image[@filename='#{utf8(img)}']"]
                 for sizeobj in $images_size
                     size_fullscreen = sizeobj['fullscreen']
                     size_thumbnails = sizeobj['thumbnails']
@@ -965,7 +968,7 @@ def walk_source_dir
                     thumbnail_images[sizeobj['name']] << File.basename(thumbnail_dest_img)
                     todo << { 'filename' => thumbnail_dest_img,  'size' => size_thumbnails }
                 end
-                gen_thumbnails_element("#{dir}/#{img}", xmldir, true, todo)
+                gen_thumbnails_element("#{dir}/#{img}", elem, true, todo)
                 if $limit_sizes =~ /original/
                     fullscreen_images['original'] << img
                 end
@@ -989,9 +992,10 @@ def walk_source_dir
         #- create thumbnails for videos
         videos.each { |video|
             info("processing element")
+            elem = optelements['video|' + utf8(video)]
             if $forgui
                 thumbnail_dest_img = dest_dir + '/' + make_dest_filename(video.sub(/\.[^\.]+$/, '')) + "-#{$default_size['thumbnails']}.jpg"
-                gen_thumbnails_element("#{dir}/#{video}", xmldir, true, [ { 'filename' => thumbnail_dest_img, 'size' => $default_size['thumbnails'] } ])
+                gen_thumbnails_element("#{dir}/#{video}", elem, true, [ { 'filename' => thumbnail_dest_img, 'size' => $default_size['thumbnails'] } ])
             else
                 todo = []
                 for sizeobj in $images_size
@@ -1000,7 +1004,7 @@ def walk_source_dir
                     thumbnail_videos[sizeobj['name']] << File.basename(thumbnail_dest_img)
                     todo << { 'filename' => thumbnail_dest_img, 'size' => size_thumbnails }
                 end
-                gen_thumbnails_element("#{dir}/#{video}", xmldir, true, todo)
+                gen_thumbnails_element("#{dir}/#{video}", elem, true, todo)
 
                 if $transcode_videos
                     parts = $transcode_videos.split(':', 2)
@@ -1262,7 +1266,34 @@ def walk_source_dir
         msg 3, _("\tfixating configuration file...")
         $xmldoc.elements.each('//dir') { |element|
             path = captionpath = element.attributes['path']
-            descendant_element = element.elements['descendant::image'] || element.elements['descendant::video']
+            descendant_element = nil
+            #- search if there is at least one image or video down that dir; use workarounds to rexml slowness
+            #- first, look down only one level, very fast
+            first_desc = nil
+            element.elements.each { |elem|
+                if first_desc.nil?
+                    first_desc = elem
+                end
+                if elem.name == 'image' || elem.name == 'video'
+                    descendant_element = elem
+                    break
+                end
+            }
+            if descendant_element.nil?
+                #- if there was nothing or only directory down one level, look down the first subdir
+                if ! first_desc.nil?
+                    first_desc.elements.each { |elem|
+                        if elem.name == 'image' || elem.name == 'video'
+                            descendant_element = elem
+                            break
+                        end
+                    }
+                end
+                if descendant_element.nil?
+                    #- if there was still nothing found, use complete albeit slow method
+                    descendant_element = element.elements['descendant::image'] || element.elements['descendant::video']
+                end
+            end
             if !descendant_element
                 msg 3, _("\t\tremoving %s, no element in it") % path
                 element.remove  #- means we have a directory with nothing interesting in it
@@ -1297,7 +1328,7 @@ def walk_source_dir
     end
 
     if $forgui
-        msg 3, _(" completed necessary stuff for GUI, exiting.")
+        msg 3, _("completed necessary stuff for GUI, exiting.")
         return
     end