Merge lp:~vanvugt/mir/system-performance into lp:mir
- system-performance
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Daniel van Vugt |
Approved revision: | no longer in the source branch. |
Merged at revision: | 3708 |
Proposed branch: | lp:~vanvugt/mir/system-performance |
Merge into: | lp:mir |
Diff against target: |
478 lines (+253/-164) 4 files modified
tests/performance-tests/CMakeLists.txt (+5/-0) tests/performance-tests/system_performance_test.cpp (+191/-0) tests/performance-tests/system_performance_test.h (+46/-0) tests/performance-tests/test_compositor.cpp (+11/-164) |
To merge this branch: | bzr merge lp:~vanvugt/mir/system-performance |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Cemil Azizoglu (community) | Approve | ||
Review via email: mp+305923@code.launchpad.net |
Commit message
Generalise CompositorTest into "SystemPerforma
it for non-compositor system performance testing.
Description of the change
Mir CI Bot (mir-ci-bot) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Daniel van Vugt (vanvugt) wrote : | # |
^^^
Bug 1523621, unrelated.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Daniel van Vugt (vanvugt) wrote : | # |
^^^
Bug 1616312 now
Mir CI Bot (mir-ci-bot) : | # |
Preview Diff
1 | === modified file 'tests/performance-tests/CMakeLists.txt' |
2 | --- tests/performance-tests/CMakeLists.txt 2016-08-24 02:09:08 +0000 |
3 | +++ tests/performance-tests/CMakeLists.txt 2016-09-16 10:11:25 +0000 |
4 | @@ -27,11 +27,16 @@ |
5 | ${GTEST_BOTH_LIBRARIES} |
6 | ) |
7 | |
8 | +add_library(mir_system_performance_test STATIC |
9 | + system_performance_test.cpp |
10 | +) |
11 | + |
12 | mir_add_wrapped_executable(mir_compositor_performance_test |
13 | test_compositor.cpp |
14 | ) |
15 | target_link_libraries(mir_compositor_performance_test |
16 | ${GTEST_BOTH_LIBRARIES} |
17 | + mir_system_performance_test |
18 | ) |
19 | |
20 | mir_add_wrapped_executable(mir_client_startup_performance_test |
21 | |
22 | === added file 'tests/performance-tests/system_performance_test.cpp' |
23 | --- tests/performance-tests/system_performance_test.cpp 1970-01-01 00:00:00 +0000 |
24 | +++ tests/performance-tests/system_performance_test.cpp 2016-09-16 10:11:25 +0000 |
25 | @@ -0,0 +1,191 @@ |
26 | +/* |
27 | + * Copyright © 2016 Canonical Ltd. |
28 | + * |
29 | + * This program is free software: you can redistribute it and/or modify it |
30 | + * under the terms of the GNU General Public License version 3, |
31 | + * as published by the Free Software Foundation. |
32 | + * |
33 | + * This program is distributed in the hope that it will be useful, |
34 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
35 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
36 | + * GNU General Public License for more details. |
37 | + * |
38 | + * You should have received a copy of the GNU General Public License |
39 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
40 | + * |
41 | + * Author: Daniel van Vugt <daniel.van.vugt@canonical.com> |
42 | + */ |
43 | + |
44 | +#include "system_performance_test.h" |
45 | +#include <cstdio> |
46 | +#include <cstdlib> |
47 | +#include <cstring> |
48 | +#include <unistd.h> |
49 | +#include <string> |
50 | +#include <thread> |
51 | + |
52 | +using namespace std::literals::chrono_literals; |
53 | + |
54 | +namespace |
55 | +{ |
56 | + |
57 | +std::string mir_bin_dir() |
58 | +{ |
59 | + char path[256]; |
60 | + auto len = readlink("/proc/self/exe", path, sizeof(path)-1); |
61 | + if (len < 0) |
62 | + len = 0; |
63 | + path[len] = '\0'; |
64 | + if (auto slash = strrchr(path, '/')) |
65 | + *slash = '\0'; |
66 | + return path; |
67 | +} |
68 | + |
69 | +void kill_nicely(pid_t pid) |
70 | +{ |
71 | + if (kill(pid, SIGTERM) < 0) |
72 | + return; |
73 | + int const timeout = 5; |
74 | + int status, count = 0; |
75 | + while (0 == waitpid(pid, &status, WNOHANG) && count < timeout) |
76 | + { |
77 | + sleep(1); |
78 | + ++count; |
79 | + } |
80 | + kill(pid, SIGKILL); |
81 | +} |
82 | + |
83 | +int exec_cmd(char const* cmd) |
84 | +{ |
85 | + auto buf = strdup(cmd); |
86 | + size_t argc = 1; |
87 | + char* argv[256] = {buf}; |
88 | + char *c = buf; |
89 | + while (*c) |
90 | + { |
91 | + if (*c == ' ') |
92 | + { |
93 | + *c = '\0'; |
94 | + if (argc < (sizeof(argv)/sizeof(argv[0]) - 1)) |
95 | + { |
96 | + argv[argc] = c + 1; |
97 | + ++argc; |
98 | + } |
99 | + } |
100 | + ++c; |
101 | + } |
102 | + argv[argc] = NULL; |
103 | + return execv(argv[0], argv); |
104 | +} |
105 | + |
106 | +FILE* popen_with_pid(char const* cmd, pid_t& pid) |
107 | +{ |
108 | + int pipefd[2]; |
109 | + if (pipe(pipefd)) |
110 | + return NULL; |
111 | + |
112 | + int const& pipe_out = pipefd[0]; |
113 | + int const& pipe_in = pipefd[1]; |
114 | + |
115 | + pid = fork(); |
116 | + if (pid < 0) |
117 | + { |
118 | + close(pipe_in); |
119 | + close(pipe_out); |
120 | + return NULL; |
121 | + } |
122 | + else if (pid == 0) |
123 | + { |
124 | + close(pipe_out); |
125 | + dup2(pipe_in, 1); // Child stdout goes into pipe_in |
126 | + close(pipe_in); |
127 | + exec_cmd(cmd); |
128 | + exit(errno); |
129 | + } |
130 | + else |
131 | + { |
132 | + close(pipe_in); |
133 | + } |
134 | + |
135 | + return fdopen(pipe_out, "r"); |
136 | +} |
137 | + |
138 | +bool spawn_and_forget(char const* cmd) |
139 | +{ |
140 | + int pid = fork(); |
141 | + if (pid == 0) |
142 | + { |
143 | + // Silence stdout/stderr |
144 | + close(1); |
145 | + close(2); |
146 | + exec_cmd(cmd); |
147 | + exit(errno); |
148 | + } |
149 | + return (pid > 0); |
150 | +} |
151 | + |
152 | +bool spawn_and_forget(std::string const& cmd) |
153 | +{ |
154 | + return spawn_and_forget(cmd.c_str()); |
155 | +} |
156 | + |
157 | +bool wait_for_file(char const* path, std::chrono::seconds timeout) |
158 | +{ |
159 | + struct stat s; |
160 | + int count = 0, max = timeout.count(); |
161 | + int ret; |
162 | + while ((ret = stat(path, &s)) < 0 && errno == ENOENT && count < max) |
163 | + { |
164 | + ++count; |
165 | + std::this_thread::sleep_for(1s); |
166 | + } |
167 | + return ret == 0; |
168 | +} |
169 | + |
170 | +} // anonymous namespace |
171 | + |
172 | +namespace mir { namespace test { |
173 | + |
174 | +SystemPerformanceTest::SystemPerformanceTest() : bin_dir{mir_bin_dir()} |
175 | +{ |
176 | +} |
177 | + |
178 | +void SystemPerformanceTest::SetUp(std::string const server_args) |
179 | +{ |
180 | + auto const mir_sock = "/tmp/mir_test_socket_"+std::to_string(getpid()); |
181 | + auto const server_cmd = |
182 | + bin_dir+"/mir_demo_server -f "+mir_sock+" "+server_args; |
183 | + |
184 | + server_output = popen_with_pid(server_cmd.c_str(), server_pid); |
185 | + ASSERT_TRUE(server_output) << server_cmd; |
186 | + ASSERT_TRUE(wait_for_file(mir_sock.c_str(), 5s)) << server_cmd; |
187 | + setenv("MIR_SOCKET", mir_sock.c_str(), 1); |
188 | +} |
189 | + |
190 | +void SystemPerformanceTest::TearDown() |
191 | +{ |
192 | + kill_nicely(server_pid); |
193 | + fclose(server_output); |
194 | +} |
195 | + |
196 | +void SystemPerformanceTest::spawn_clients(std::initializer_list<std::string> clients) |
197 | +{ |
198 | + for (auto& client : clients) |
199 | + { |
200 | + spawn_and_forget(bin_dir+"/"+client); |
201 | + std::this_thread::sleep_for(100ms); |
202 | + } |
203 | +} |
204 | + |
205 | +void SystemPerformanceTest::run_server_for(std::chrono::seconds timeout) |
206 | +{ |
207 | + pid_t pid = server_pid; |
208 | + std::thread killer([timeout,pid]() |
209 | + { |
210 | + std::this_thread::sleep_for(timeout); |
211 | + kill_nicely(pid); |
212 | + }); |
213 | + killer.detach(); |
214 | +} |
215 | + |
216 | +} } // namespace mir::test |
217 | |
218 | === added file 'tests/performance-tests/system_performance_test.h' |
219 | --- tests/performance-tests/system_performance_test.h 1970-01-01 00:00:00 +0000 |
220 | +++ tests/performance-tests/system_performance_test.h 2016-09-16 10:11:25 +0000 |
221 | @@ -0,0 +1,46 @@ |
222 | +/* |
223 | + * Copyright © 2016 Canonical Ltd. |
224 | + * |
225 | + * This program is free software: you can redistribute it and/or modify it |
226 | + * under the terms of the GNU General Public License version 3, |
227 | + * as published by the Free Software Foundation. |
228 | + * |
229 | + * This program is distributed in the hope that it will be useful, |
230 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
231 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
232 | + * GNU General Public License for more details. |
233 | + * |
234 | + * You should have received a copy of the GNU General Public License |
235 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
236 | + * |
237 | + * Author: Daniel van Vugt <daniel.van.vugt@canonical.com> |
238 | + */ |
239 | + |
240 | +#ifndef MIR_TEST_SYSTEM_PERFORMANCE_TEST_H_ |
241 | +#define MIR_TEST_SYSTEM_PERFORMANCE_TEST_H_ |
242 | + |
243 | +#include <gtest/gtest.h> |
244 | +#include <string> |
245 | +#include <chrono> |
246 | +#include <initializer_list> |
247 | + |
248 | +namespace mir { namespace test { |
249 | + |
250 | +class SystemPerformanceTest : public testing::Test |
251 | +{ |
252 | +protected: |
253 | + SystemPerformanceTest(); |
254 | + void SetUp(std::string const server_args); |
255 | + void TearDown() override; |
256 | + void spawn_clients(std::initializer_list<std::string> clients); |
257 | + void run_server_for(std::chrono::seconds timeout); |
258 | + |
259 | + FILE* server_output; |
260 | +private: |
261 | + std::string const bin_dir; |
262 | + pid_t server_pid = 0; |
263 | +}; |
264 | + |
265 | +} } // namespace mir::test |
266 | + |
267 | +#endif // MIR_TEST_SYSTEM_PERFORMANCE_TEST_H_ |
268 | |
269 | === modified file 'tests/performance-tests/test_compositor.cpp' |
270 | --- tests/performance-tests/test_compositor.cpp 2016-05-09 02:49:10 +0000 |
271 | +++ tests/performance-tests/test_compositor.cpp 2016-09-16 10:11:25 +0000 |
272 | @@ -16,174 +16,23 @@ |
273 | * Author: Daniel van Vugt <daniel.van.vugt@canonical.com> |
274 | */ |
275 | |
276 | -#include <gtest/gtest.h> |
277 | -#include <cstdio> |
278 | -#include <cstdlib> |
279 | -#include <cstring> |
280 | -#include <unistd.h> |
281 | -#include <string> |
282 | -#include <thread> |
283 | -#include <initializer_list> |
284 | +#include "system_performance_test.h" |
285 | |
286 | using namespace std::literals::chrono_literals; |
287 | +using namespace mir::test; |
288 | |
289 | namespace |
290 | { |
291 | - |
292 | -std::string mir_bin_dir() |
293 | -{ |
294 | - char path[256]; |
295 | - auto len = readlink("/proc/self/exe", path, sizeof(path)-1); |
296 | - if (len < 0) |
297 | - len = 0; |
298 | - path[len] = '\0'; |
299 | - if (auto slash = strrchr(path, '/')) |
300 | - *slash = '\0'; |
301 | - return path; |
302 | -} |
303 | - |
304 | -void kill_nicely(pid_t pid) |
305 | -{ |
306 | - if (kill(pid, SIGTERM) < 0) |
307 | - return; |
308 | - int const timeout = 5; |
309 | - int status, count = 0; |
310 | - while (0 == waitpid(pid, &status, WNOHANG) && count < timeout) |
311 | - { |
312 | - sleep(1); |
313 | - ++count; |
314 | - } |
315 | - kill(pid, SIGKILL); |
316 | -} |
317 | - |
318 | -int exec_cmd(char const* cmd) |
319 | -{ |
320 | - auto buf = strdup(cmd); |
321 | - size_t argc = 1; |
322 | - char* argv[256] = {buf}; |
323 | - char *c = buf; |
324 | - while (*c) |
325 | - { |
326 | - if (*c == ' ') |
327 | - { |
328 | - *c = '\0'; |
329 | - if (argc < (sizeof(argv)/sizeof(argv[0]) - 1)) |
330 | - { |
331 | - argv[argc] = c + 1; |
332 | - ++argc; |
333 | - } |
334 | - } |
335 | - ++c; |
336 | - } |
337 | - argv[argc] = NULL; |
338 | - return execv(argv[0], argv); |
339 | -} |
340 | - |
341 | -FILE* popen_with_pid(char const* cmd, pid_t& pid) |
342 | -{ |
343 | - int pipefd[2]; |
344 | - if (pipe(pipefd)) |
345 | - return NULL; |
346 | - |
347 | - int const& pipe_out = pipefd[0]; |
348 | - int const& pipe_in = pipefd[1]; |
349 | - |
350 | - pid = fork(); |
351 | - if (pid < 0) |
352 | - { |
353 | - close(pipe_in); |
354 | - close(pipe_out); |
355 | - return NULL; |
356 | - } |
357 | - else if (pid == 0) |
358 | - { |
359 | - close(pipe_out); |
360 | - dup2(pipe_in, 1); // Child stdout goes into pipe_in |
361 | - close(pipe_in); |
362 | - exec_cmd(cmd); |
363 | - exit(errno); |
364 | - } |
365 | - else |
366 | - { |
367 | - close(pipe_in); |
368 | - } |
369 | - |
370 | - return fdopen(pipe_out, "r"); |
371 | -} |
372 | - |
373 | -bool spawn_and_forget(char const* cmd) |
374 | -{ |
375 | - int pid = fork(); |
376 | - if (pid == 0) |
377 | - { |
378 | - // Silence stdout/stderr |
379 | - close(1); |
380 | - close(2); |
381 | - exec_cmd(cmd); |
382 | - exit(errno); |
383 | - } |
384 | - return (pid > 0); |
385 | -} |
386 | - |
387 | -bool spawn_and_forget(std::string const& cmd) |
388 | -{ |
389 | - return spawn_and_forget(cmd.c_str()); |
390 | -} |
391 | - |
392 | -bool wait_for_file(char const* path, std::chrono::seconds timeout) |
393 | -{ |
394 | - struct stat s; |
395 | - int count = 0, max = timeout.count(); |
396 | - int ret; |
397 | - while ((ret = stat(path, &s)) < 0 && errno == ENOENT && count < max) |
398 | - { |
399 | - ++count; |
400 | - std::this_thread::sleep_for(1s); |
401 | - } |
402 | - return ret == 0; |
403 | -} |
404 | - |
405 | -struct CompositorPerformance : testing::Test |
406 | +struct CompositorPerformance : SystemPerformanceTest |
407 | { |
408 | void SetUp() override |
409 | { |
410 | compositor_fps = compositor_render_time = -1.0f; |
411 | - |
412 | - auto const mir_sock = "/tmp/mir_test_socket_"+std::to_string(getpid()); |
413 | - auto const server_cmd = |
414 | - bin_dir+"/mir_demo_server --compositor-report=log -f "+mir_sock; |
415 | - |
416 | - server_output = popen_with_pid(server_cmd.c_str(), server_pid); |
417 | - ASSERT_TRUE(server_output) << server_cmd; |
418 | - ASSERT_TRUE(wait_for_file(mir_sock.c_str(), 5s)) << server_cmd; |
419 | - setenv("MIR_SOCKET", mir_sock.c_str(), 1); |
420 | - } |
421 | - |
422 | - void TearDown() override |
423 | - { |
424 | - kill_nicely(server_pid); |
425 | - fclose(server_output); |
426 | - } |
427 | - |
428 | - void spawn_clients(std::initializer_list<std::string> clients) |
429 | - { |
430 | - for (auto& client : clients) |
431 | - { |
432 | - spawn_and_forget(bin_dir+"/"+client); |
433 | - std::this_thread::sleep_for(100ms); |
434 | - } |
435 | - } |
436 | - |
437 | - void wait_for_server(std::chrono::seconds timeout) |
438 | - { |
439 | - pid_t pid = server_pid; |
440 | - std::thread killer([timeout,pid]() |
441 | - { |
442 | - std::this_thread::sleep_for(timeout); |
443 | - kill_nicely(pid); |
444 | - }); |
445 | - killer.detach(); |
446 | - |
447 | + SystemPerformanceTest::SetUp("--compositor-report=log"); |
448 | + } |
449 | + |
450 | + void read_compositor_report() |
451 | + { |
452 | char line[256]; |
453 | while (fgets(line, sizeof(line), server_output)) |
454 | { |
455 | @@ -200,12 +49,8 @@ |
456 | } |
457 | } |
458 | |
459 | - std::string const bin_dir{mir_bin_dir()}; |
460 | - pid_t server_pid = 0; |
461 | - FILE* server_output; |
462 | float compositor_fps, compositor_render_time; |
463 | }; |
464 | - |
465 | } // anonymous namespace |
466 | |
467 | TEST_F(CompositorPerformance, regression_test_1563287) |
468 | @@ -216,7 +61,9 @@ |
469 | "mir_demo_client_scroll", |
470 | "mir_demo_client_egltriangle -b0.5", |
471 | "mir_demo_client_multiwin"}); |
472 | - wait_for_server(10s); |
473 | + run_server_for(10s); |
474 | + |
475 | + read_compositor_report(); |
476 | EXPECT_GE(compositor_fps, 58.0f); |
477 | EXPECT_LT(compositor_render_time, 17.0f); |
478 | } |
PASSED: Continuous integration, rev:3707 /mir-jenkins. ubuntu. com/job/ mir-ci/ 1744/ /mir-jenkins. ubuntu. com/job/ build-mir/ 2184 /mir-jenkins. ubuntu. com/job/ build-0- fetch/2247 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 2238 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 2238 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= yakkety/ 2238 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= yakkety/ 2212 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= yakkety/ 2212/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2212 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2212/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= yakkety/ 2212 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= yakkety/ 2212/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 2212 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 2212/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2212 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2212/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 1744/rebuild
https:/