Mikolaj Zalewski : speedup loadResource

Alexandre Julliard julliard at winehq.org
Fri Jun 19 08:36:17 CDT 2009


Module: tools
Branch: master
Commit: e6e69cc9b1628f9abc7f6602650109aa533e2014
URL:    http://source.winehq.org/git/tools.git/?a=commit;h=e6e69cc9b1628f9abc7f6602650109aa533e2014

Author: Mikolaj Zalewski <mikolajz at tygrys.dom>
Date:   Fri Feb 29 20:09:16 2008 +0100

speedup loadResource

---

 php/lib_res.php   |   98 ++++++++++++++++++++++++++++++++++++++++++++---------
 php/stopwatch.php |   46 +++++++++++++++++++++++++
 2 files changed, 128 insertions(+), 16 deletions(-)

diff --git a/php/lib_res.php b/php/lib_res.php
index 463073b..ff27c42 100644
--- a/php/lib_res.php
+++ b/php/lib_res.php
@@ -1,5 +1,7 @@
 <?php
 
+include_once("stopwatch.php");
+
 function get_word(&$data)
 {
     if (strlen($data)  < 2)
@@ -9,18 +11,32 @@ function get_word(&$data)
     return $cx["c"];
 }
 
-function get_stringorid(&$data)
+function get_stringorid($data, &$pos)
 {
-    $c1 = get_word($data);
-    if ($c1 == 0xffff)
-        return get_word($data);
+    $len = strlen($data);
+
+    if ((ord($data[$pos]) == 0xff) && (ord($data[$pos + 1]) == 0xff))
+    {
+        if ($len < 4)
+            die("not enough data");
+        $pos += 4;
+        return (ord($data[$pos - 2]) + (ord($data[$pos - 1]) << 8));
+    }
 
     $ret ="";
-    while ($c1)
+    for ($i = $pos; (ord($data[$i]) != 0) || (ord($data[$i+1]) != 0); $i += 2)
     {
-        $ret .= ($c1>=0x80 ? '?' : chr($c1));
-        $c1 = get_word($data);
+        if (ord($data[$i+1]))
+            $ret .= '?';
+        else
+            $ret .= (ord($data[$i])>=0x80 ? '?' : $data[$i]);
     }
+
+    $pos = $i + 2;
+
+    if ($pos >= $len)
+        die("not enough data");
+
     return $ret;
 }
 
@@ -60,11 +76,12 @@ class ResFile
         do {
             $data = fread($this->file, 8);
 
-            if (strlen($data) == 0)
+            $len = strlen($data);
+            if ($len == 0)
                 break;
-
-            if (strlen($data) < 8)
+            if ($len < 8)
                 die("Couldn't read header");
+
             $header = unpack("VresSize/VheaderSize", $data);
             assert($header["headerSize"] > 8);
 
@@ -73,10 +90,12 @@ class ResFile
             if (strlen($data) < $len)
                 die("Couldn't read header");
 
-            $header["type"] = get_stringorid($data);
-            $header["name"] = get_stringorid($data);
-            if (($len - strlen($data)) % 4)  /* WORD padding */
-                get_word($data);
+            $strpos = 0;
+            $header["type"] = get_stringorid($data, $strpos);
+            $header["name"] = get_stringorid($data, $strpos);
+            if ($strpos & 3)  /* DWORD padding */
+                $strpos += 2;
+            $data = substr($data, $strpos);
             $header += unpack("VdataVersion/vmemoryOptions/vlanguage/Vversion/Vcharacteristics", $data);
         
             $pos += ($header["headerSize"] + $header["resSize"] + 3) & 0xfffffffc;
@@ -103,11 +122,58 @@ class ResFile
 
     function loadResource($type, $name, $language, $ignore_sublang = FALSE)
     {
-        $out = NULL;
+//        $sw = new Stopwatch();
+/*      too slow
         if ($this->enumResources(array($this, 'load_resource_helper'), array($type, $name, $language, &$header, &$out, $ignore_sublang)))
         {
             return array($header, $out);
-        }
+        }*/
+        
+        fseek($this->file, 0);
+        $pos = 0;
+
+        do {
+            $data = fread($this->file, 512);
+
+            $len = strlen($data);
+            if ($len == 0)
+                break;
+            if ($len < 8)
+                die("Couldn't read header");
+
+            $header = unpack("Va/Vb", $data);
+            $resSize = $header["a"];
+            $headerSize = $header["b"];
+            assert($headerSize > 8 && $headerSize <= $len);
+
+            $strpos = 8;
+            $res_type = get_stringorid($data, $strpos);
+            if ($res_type == $type)
+            {
+                $res_name = get_stringorid($data, $strpos);
+                if ($res_name == $name)
+                {
+                    if ($strpos & 3)  /* DWORD padding */
+                        $strpos += 2;
+                    $data = substr($data, $strpos);
+                    $header = unpack("VdataVersion/vmemoryOptions/vlanguage/Vversion/Vcharacteristics", $data);
+
+                    $curr_lang = ($ignore_sublang ? ($header["language"] & 0x3ff) : $header["language"]); /* check the ignore_sublang */
+                    if ($curr_lang == $language)
+                    {
+                        fseek($this->file, $pos + $headerSize);
+                        $out = fread($this->file, $resSize);
+//                        $sw->stop();
+                        return array($header, $out);
+                    }
+                }
+            }
+            
+            $pos += ($headerSize + $resSize + 3) & 0xfffffffc;
+            
+            fseek($this->file, $pos);
+        } while (true);
+        
         return FALSE;
     }
 }
diff --git a/php/stopwatch.php b/php/stopwatch.php
new file mode 100644
index 0000000..ba227c9
--- /dev/null
+++ b/php/stopwatch.php
@@ -0,0 +1,46 @@
+<?php
+
+class Stopwatch
+{
+    function Stopwatch($name = "")
+    {
+        $this->time = 0;
+        $this->name = "";
+        $this->running = TRUE;
+        $this->time = $this->get_microtime();
+    }
+
+    function get_microtime()
+    {
+        $time = split(" ", microtime());
+        return $time[0] + $time[1];
+    }
+
+    function pause()
+    {
+        if (!$this->running)
+            die("illegal stopwatch stop");
+        $this->running = FALSE;
+        $this->time = $this->get_microtime() - $this->time;
+    }
+
+    function resume()
+    {
+        if ($this->running)
+            die("illegal stopwatch stop");
+        $this->running = TRUE;
+        $this->time = $this->get_microtime() - $this->time;
+    }
+
+    function stop()
+    {
+        $this->pause();
+        echo "Stopwatch ".$this->name." run for ".$this->time."<br/>";
+    }
+
+    var $time;
+    var $running;
+    var $name;
+}
+
+?>
\ No newline at end of file




More information about the wine-cvs mailing list