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