1 : <?php
2 :
3 : /**
4 : * XSLT Benchmarking
5 : * @link https://github.com/masicek/XSLT-Benchmarking
6 : * @author Viktor Mašíček <viktor@masicek.net>
7 : * @license "New" BSD License
8 : */
9 :
10 : namespace XSLTBenchmarking\TestsRunner;
11 :
12 : require_once __DIR__ . '/AMemoryUsageDriver.php';
13 : require_once ROOT . '/Exceptions.php';
14 : require_once LIBS . '/PhpPath/PhpPath.min.php';
15 :
16 : use PhpPath\P;
17 :
18 : /**
19 : * Windows driver for geting maximum memory usage of command excuteb by 'timemem.exe'
20 : *
21 : * @author Viktor Mašíček <viktor@masicek.net>
22 : */
23 : class WindowsMemoryUsageDriver extends AMemoryUsageDriver
24 : {
25 :
26 :
27 : /**
28 : * Path of log file for reporting measured PeakWorkingSetSize from '/usr/bin/time'
29 : *
30 : * @var string
31 : */
32 : private $logPath;
33 :
34 : /**
35 : * Path of command 'timemem.exe' for measure memory usage
36 : *
37 : * @var string
38 : */
39 : private $timememPath;
40 :
41 : /**
42 : * Helpful variable for saving path of file for redirecting stderr in input command
43 : *
44 : * @var string
45 : */
46 : private $errorOutputPath;
47 :
48 :
49 : /**
50 : * Construct path of main and end log files
51 : *
52 : * @param type $tmpDir Path of temporary directory
53 : */
54 : public function __construct($tmpDir)
55 : {
56 3 : parent::__construct($tmpDir);
57 :
58 3 : $this->logPath = P::m($this->tmpDir, 'windowsMemoryUsage.log');
59 3 : $this->timememPath = P::m(LIBS, 'Timemem', 'timemem.exe');
60 3 : }
61 :
62 :
63 : /**
64 : * Save command into scrit and return command for running set command and
65 : * checking its memory usage.
66 : *
67 : * @param string $command Checked command
68 : *
69 : * @throws \XSLTBenchmarking\InvalidArgumentException Log/Script file exist
70 : * @return string
71 : */
72 : public function run($command)
73 : {
74 3 : if (is_file($this->logPath))
75 3 : {
76 0 : throw new \XSLTBenchmarking\InvalidArgumentException('Windows memory usage log file exist.');
77 : }
78 :
79 : // error output
80 3 : preg_match('/2> *"([^"]*)"/', $command, $matches);
81 3 : $this->errorOutputPath = NULL;
82 3 : if (isset($matches[1]))
83 3 : {
84 1 : $command = str_replace($matches[0], '', $command);
85 1 : $this->errorOutputPath = $matches[1];
86 1 : }
87 : else
88 : {
89 2 : preg_match('/2> *([^ ]*)/', $command, $matches);
90 2 : if (isset($matches[1]))
91 2 : {
92 1 : $command = str_replace($matches[0], '', $command);
93 1 : $this->errorOutputPath = $matches[1];
94 1 : }
95 : }
96 :
97 3 : $command = str_replace('>', '^>', $command);
98 3 : $command = str_replace('"', '\\"', $command);
99 3 : $command = $this->timememPath . ' "' . $command . '" 2> ' . $this->logPath;
100 :
101 3 : return $command;
102 : }
103 :
104 :
105 : /**
106 : * Return maximum memory usage (in bytes) last checked command by self::run().
107 : *
108 : * @return integer
109 : */
110 : public function get()
111 : {
112 3 : $log = trim(file_get_contents($this->logPath));
113 :
114 : // error output of command
115 3 : $errorEndPos = strpos($log, 'Process ID:');
116 : if ($errorEndPos)
117 3 : {
118 2 : $error = substr($log, 0, $errorEndPos);
119 2 : $log = substr($log, $errorEndPos);
120 2 : file_put_contents($this->errorOutputPath, $error);
121 2 : }
122 :
123 3 : $log = preg_match('/Peak Working Set Size \(kbytes\): ([0-9]*)/', $log, $matches);
124 3 : $maxMemory = $matches[1];
125 :
126 3 : unlink($this->logPath);
127 :
128 : // units corrections (Kilobytes -> Bytes)
129 3 : $maxMemory = $maxMemory * 1000;
130 :
131 3 : return $maxMemory;
132 : }
133 :
134 :
135 : }
|