Merge lp:~gordallott/unity/perf-logger into lp:unity

Proposed by Gord Allott
Status: Merged
Merged at revision: 687
Proposed branch: lp:~gordallott/unity/perf-logger
Merge into: lp:unity
Diff against target: 626 lines (+151/-92)
7 files modified
CMakeLists.txt (+1/-0)
libunity/CMakeLists.txt (+1/-0)
libunity/perf-logger-utility.h (+34/-0)
libunity/perf-logger.vala (+30/-27)
src/unity.cpp (+49/-29)
tools/CMakeLists.txt (+1/-1)
tools/makebootchart.py (+35/-35)
To merge this branch: bzr merge lp:~gordallott/unity/perf-logger
Reviewer Review Type Date Requested Status
Jason Smith (community) Approve
Review via email: mp+42594@code.launchpad.net

Description of the change

Adds updates the performance logging code for unity

To post a comment you must log in.
Revision history for this message
Jason Smith (jassmith) wrote :

+1 code looks good, everything seems to be in order

review: Approve
Revision history for this message
Jason Smith (jassmith) wrote :

It does have a merge conflict with latest trunk however

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2010-11-30 15:44:05 +0000
3+++ CMakeLists.txt 2010-12-03 08:41:48 +0000
4@@ -82,6 +82,7 @@
5 PKGDEPS ${UNITY_PLUGIN_DEPS}
6 PLUGINDEPS composite opengl
7 CFLAGSADD "-DINSTALLPREFIX='\"${CMAKE_INSTALL_PREFIX}\"' -DPKGDATADIR='\"${CMAKE_INSTALL_PREFIX}/share/unity/3\"' -I${CMAKE_BINARY_DIR}"
8+ LIBRARIES "unity"
9 )
10
11 #
12
13=== modified file 'libunity/CMakeLists.txt'
14--- libunity/CMakeLists.txt 2010-11-25 12:08:52 +0000
15+++ libunity/CMakeLists.txt 2010-12-03 08:41:48 +0000
16@@ -50,6 +50,7 @@
17 vala_precompile (VALA_C unity-place-activation.vala
18 unity-place-browser.vala
19 unity-place.vala
20+ perf-logger.vala
21 PACKAGES gtk+-2.0 gio-2.0 glib-2.0 gobject-2.0 gee-1.0 dbus-glib-1 gio-unix-2.0
22 OPTIONS --thread
23 CUSTOM_VAPIS ../vapi/dee-1.0.vapi ../vapi/config.vapi
24
25=== added file 'libunity/perf-logger-utility.h'
26--- libunity/perf-logger-utility.h 1970-01-01 00:00:00 +0000
27+++ libunity/perf-logger-utility.h 2010-12-03 08:41:48 +0000
28@@ -0,0 +1,34 @@
29+/*
30+ * Copyright (C) 2009-2010 Canonical Ltd
31+ *
32+ * This program is free software: you can redistribute it and/or modify
33+ * it under the terms of the GNU General Public License version 3 as
34+ * published by the Free Software Foundation.
35+ *
36+ * This program is distributed in the hope that it will be useful,
37+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
38+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39+ * GNU General Public License for more details.
40+ *
41+ * You should have received a copy of the GNU General Public License
42+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
43+ *
44+ * Authored by Gordon Allott <gord.allott@canonical.com>
45+ *
46+ */
47+#ifndef _PERF_LOGGER_H_
48+#define _PERF_LOGGER_H_
49+
50+#include <libunity/unity.h>
51+
52+#define START_FUNCTION() G_STMT_START { \
53+ perf_timeline_logger_start_process (perf_timeline_logger_get_default(), G_STRFUNC);\
54+ } G_STMT_END
55+#define LOGGER_START_PROCESS(process) { perf_timeline_logger_start_process (perf_timeline_logger_get_default(), process);}
56+
57+#define END_FUNCTION() G_STMT_START { \
58+ perf_timeline_logger_end_process (perf_timeline_logger_get_default(), G_STRFUNC);\
59+ } G_STMT_END
60+#define LOGGER_END_PROCESS(process) { perf_timeline_logger_end_process (perf_timeline_logger_get_default(), process);}
61+
62+#endif /* PERF_LOGGER_H */
63
64=== renamed file 'unity-private/testing/perf-logger.vala' => 'libunity/perf-logger.vala'
65--- unity-private/testing/perf-logger.vala 2010-04-07 14:46:55 +0000
66+++ libunity/perf-logger.vala 2010-12-03 08:41:48 +0000
67@@ -1,5 +1,5 @@
68 /*
69- * Copyright (C) 2009 Canonical Ltd
70+ * Copyright (C) 2009-2010 Canonical Ltd
71 *
72 * This program is free software: you can redistribute it and/or modify
73 * it under the terms of the GNU General Public License version 3 as
74@@ -17,9 +17,8 @@
75 *
76 */
77
78-namespace Unity
79+namespace Perf
80 {
81-
82 public class ProcessInfo
83 {
84 public ProcessInfo (string name)
85@@ -32,82 +31,86 @@
86 public double start;
87 public double end;
88 }
89-
90+
91 public static TimelineLogger? timeline_singleton;
92- public static bool is_logging;
93-
94+ public static bool is_logging;
95+
96 public class TimelineLogger : Object
97 {
98 private Timer global_timer;
99 private Gee.HashMap<string, ProcessInfo> process_map;
100-
101- public static unowned Unity.TimelineLogger get_default ()
102+
103+ public static unowned Perf.TimelineLogger get_default ()
104 {
105- if (Unity.timeline_singleton == null)
106+ if (Perf.timeline_singleton == null)
107 {
108- Unity.timeline_singleton = new Unity.TimelineLogger ();
109+ Perf.timeline_singleton = new Perf.TimelineLogger ();
110 }
111-
112- return Unity.timeline_singleton;
113+
114+ return Perf.timeline_singleton;
115 }
116-
117+
118 construct
119 {
120 this.process_map = new Gee.HashMap<string, ProcessInfo> ();
121- this.global_timer = new Timer ();
122+ this.global_timer = new Timer ();
123 this.global_timer.start ();
124 }
125-
126+
127 public void start_process (string name)
128 {
129+ debug ("shoop de whoop");
130 if (name in this.process_map.keys)
131 {
132 warning ("already started process: %s", name);
133 return;
134 }
135-
136+
137 var info = new ProcessInfo (name);
138 this.process_map[name] = info;
139 info.start = this.global_timer.elapsed ();
140 }
141-
142+
143 public void end_process (string name)
144 {
145+ debug ("shonk le donk");
146 double end_time = this.global_timer.elapsed ();
147-
148+ print ("the end time is %f", end_time);
149+
150 if (name in this.process_map.keys)
151 {
152 this.process_map[name].end = end_time;
153 }
154- else
155+ else
156 {
157 warning ("process %s not started", name);
158 }
159 }
160-
161+
162 public void write_log (string filename)
163 {
164 debug ("Writing performance log file: %s...", filename);
165 var log_file = File.new_for_path (filename);
166 FileOutputStream file_stream;
167- try
168+ try
169 {
170 if (!log_file.query_exists (null)) {
171 file_stream = log_file.create (FileCreateFlags.NONE, null);
172 }
173- else
174+ else
175 {
176 file_stream = log_file.replace (null, false, FileCreateFlags.NONE, null);
177 }
178-
179+
180 var output_stream = new DataOutputStream (file_stream);
181-
182+
183 foreach (ProcessInfo info in this.process_map.values)
184 {
185- string outline = "%s, %f, %f\n".printf(info.name, info.start, info.end);
186- output_stream.put_string (outline, null);
187+ string name = info.name.replace (",", ";");
188+ string outline = "%s, %f, %f\n".printf(name, info.start, info.end);
189+ output_stream.put_string (outline, null);
190 }
191-
192+
193 file_stream.close (null);
194 } catch (Error e)
195 {
196
197=== modified file 'src/unity.cpp'
198--- src/unity.cpp 2010-11-26 09:11:52 +0000
199+++ src/unity.cpp 2010-12-03 08:41:48 +0000
200@@ -39,6 +39,8 @@
201
202 #include <core/atoms.h>
203
204+#include "../libunity/perf-logger-utility.h"
205+
206 /* Set up vtable symbols */
207 COMPIZ_PLUGIN_20090315 (unityshell, UnityPluginVTable);
208
209@@ -49,10 +51,10 @@
210 {
211 /* reset matrices */
212 glPushAttrib (GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
213-
214+
215 glMatrixMode (GL_PROJECTION);
216 glPushMatrix ();
217-
218+
219 glMatrixMode (GL_MODELVIEW);
220 glPushMatrix ();
221
222@@ -139,19 +141,19 @@
223 std::vector<nux::Geometry>::iterator it;
224 std::vector<nux::Geometry> dirty = wt->GetDrawList ();
225 nux::Geometry geo;
226-
227+
228 for (it = dirty.begin (); it != dirty.end (); it++)
229 {
230 geo = *it;
231 cScreen->damageRegion (CompRegion (geo.x, geo.y, geo.width, geo.height));
232 }
233-
234+
235 geo = wt->GetWindowCompositor ().GetTooltipMainWindowGeometry();
236 cScreen->damageRegion (CompRegion (geo.x, geo.y, geo.width, geo.height));
237 cScreen->damageRegion (CompRegion (lastTooltipArea.x, lastTooltipArea.y, lastTooltipArea.width, lastTooltipArea.height));
238-
239+
240 lastTooltipArea = geo;
241-
242+
243 wt->ClearDrawList ();
244 }
245
246@@ -165,7 +167,7 @@
247 {
248 wt->ProcessForeignEvent (event, NULL);
249 }
250-}
251+}
252
253
254 gboolean
255@@ -258,7 +260,7 @@
256 * stacked on top of one of the nux input windows
257 * and if so paint nux and stop us from painting
258 * other windows or on top of the whole screen */
259-bool
260+bool
261 UnityWindow::glDraw (const GLMatrix &matrix,
262 GLFragment::Attrib &attrib,
263 const CompRegion &region,
264@@ -278,7 +280,7 @@
265 }
266
267 bool ret = gWindow->glDraw (matrix, attrib, region, mask);
268-
269+
270 return ret;
271 }
272
273@@ -293,7 +295,7 @@
274 }
275
276 /* Configure callback for the launcher window */
277-void
278+void
279 UnityScreen::launcherWindowConfigureCallback(int WindowWidth, int WindowHeight, nux::Geometry& geo, void *user_data)
280 {
281 int OurWindowHeight = WindowHeight - 24;
282@@ -301,23 +303,25 @@
283 }
284
285 /* Configure callback for the panel window */
286-void
287+void
288 UnityScreen::panelWindowConfigureCallback(int WindowWidth, int WindowHeight, nux::Geometry& geo, void *user_data)
289 {
290 geo = nux::Geometry(0, 0, WindowWidth, 24);
291 }
292
293 /* Start up nux after OpenGL is initialized */
294-void
295+void
296 UnityScreen::initUnity(nux::NThread* thread, void* InitData)
297 {
298+ START_FUNCTION ();
299 initLauncher(thread, InitData);
300-
301+
302 nux::ColorLayer background(nux::Color(0x00000000));
303 static_cast<nux::WindowThread*>(thread)->SetWindowBackgroundPaintLayer(&background);
304+ END_FUNCTION ();
305 }
306
307-void
308+void
309 UnityScreen::onRedrawRequested ()
310 {
311 damageNuxRegions ();
312@@ -342,6 +346,13 @@
313 }
314 }
315
316+static gboolean
317+write_logger_data_to_disk (gpointer data)
318+{
319+ perf_timeline_logger_write_log (perf_timeline_logger_get_default (), "/tmp/unity-perf.log");
320+ return FALSE;
321+}
322+
323 UnityScreen::UnityScreen (CompScreen *screen) :
324 PluginClassHandler <UnityScreen, CompScreen> (screen),
325 screen (screen),
326@@ -349,35 +360,37 @@
327 gScreen (GLScreen::get (screen)),
328 doShellRepaint (false)
329 {
330+ START_FUNCTION ();
331 int (*old_handler) (Display *, XErrorEvent *);
332 old_handler = XSetErrorHandler (NULL);
333-
334+
335 g_thread_init (NULL);
336 dbus_g_thread_init ();
337 gtk_init (NULL, NULL);
338-
339+
340 XSetErrorHandler (old_handler);
341
342 /* Wrap compiz interfaces */
343 ScreenInterface::setHandler (screen);
344 CompositeScreenInterface::setHandler (cScreen);
345 GLScreenInterface::setHandler (gScreen);
346-
347+
348 StartupNotifyService::Default ()->SetSnDisplay (screen->snDisplay (), screen->screenNum ());
349
350 nux::NuxInitialize (0);
351- wt = nux::CreateFromForeignWindow (cScreen->output (),
352- glXGetCurrentContext (),
353+ wt = nux::CreateFromForeignWindow (cScreen->output (),
354+ glXGetCurrentContext (),
355 &UnityScreen::initUnity,
356 this);
357-
358+
359 wt->RedrawRequested.connect (sigc::mem_fun (this, &UnityScreen::onRedrawRequested));
360-
361+ END_FUNCTION ();
362+ g_timeout_add (10, write_logger_data_to_disk, NULL);
363 wt->Run (NULL);
364 uScreen = this;
365
366 debugger = new IntrospectionDBusInterface (this);
367-
368+
369 PluginAdapter::Initialize (screen);
370
371 optionSetLauncherAutohideNotify (boost::bind (&UnityScreen::optionChanged, this, _1, _2));
372@@ -393,25 +406,28 @@
373 /* Can't create windows until after we have initialized everything */
374 gboolean UnityScreen::strutHackTimeout (gpointer data)
375 {
376- UnityScreen *self = (UnityScreen*) data;
377-
378+ UnityScreen *self = (UnityScreen*) data;
379+
380 if (!self->launcher->AutohideEnabled ())
381 {
382 self->launcherWindow->InputWindowEnableStruts(false);
383 self->launcherWindow->InputWindowEnableStruts(true);
384 }
385-
386+
387 self->panelWindow->InputWindowEnableStruts(false);
388 self->panelWindow->InputWindowEnableStruts(true);
389-
390+
391 return FALSE;
392 }
393
394 /* Start up the launcher */
395 void UnityScreen::initLauncher (nux::NThread* thread, void* InitData)
396 {
397+ START_FUNCTION ();
398+
399 UnityScreen *self = (UnityScreen*) InitData;
400-
401+
402+ LOGGER_START_PROCESS ("initLauncher-Launcher");
403 self->launcherWindow = new nux::BaseWindow(TEXT(""));
404 self->launcher = new Launcher(self->launcherWindow);
405 self->AddChild (self->launcher);
406@@ -434,8 +450,10 @@
407 self->launcherWindow->InputWindowEnableStruts(true);
408
409 self->launcher->SetIconSize (54, 48);
410+ LOGGER_END_PROCESS ("initLauncher-Launcher");
411
412 /* Setup panel */
413+ LOGGER_START_PROCESS ("initLauncher-Panel");
414 self->panelView = new PanelView ();
415 self->AddChild (self->panelView);
416
417@@ -454,10 +472,12 @@
418 self->panelWindow->SetBackgroundColor(nux::Color(0x00000000));
419 self->panelWindow->SetBlurredBackground(false);
420 self->panelWindow->ShowWindow(true);
421- self->panelWindow->EnableInputWindow(true);
422+ self->panelWindow->EnableInputWindow(true);
423 self->panelWindow->InputWindowEnableStruts(true);
424-
425+ LOGGER_END_PROCESS ("initLauncher-Panel");
426 g_timeout_add (2000, &UnityScreen::strutHackTimeout, self);
427+
428+ END_FUNCTION ();
429 }
430
431 /* Window init */
432
433=== modified file 'tools/CMakeLists.txt'
434--- tools/CMakeLists.txt 2010-11-25 15:56:14 +0000
435+++ tools/CMakeLists.txt 2010-12-03 08:41:48 +0000
436@@ -1,5 +1,5 @@
437 #
438 # Some unity tools
439 #
440-install(FILES migrate_favorites.py PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/unity/)
441+install(FILES makebootchart.py migrate_favorites.py PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/unity/)
442
443
444=== modified file 'tools/makebootchart.py'
445--- tools/makebootchart.py 2010-01-15 12:28:51 +0000
446+++ tools/makebootchart.py 2010-12-03 08:41:48 +0000
447@@ -24,8 +24,8 @@
448 import math
449 import random
450 from string import Template
451-from socket import gethostname
452-from datetime import datetime
453+from socket import gethostname
454+from datetime import datetime
455 import re
456 import subprocess
457
458@@ -39,22 +39,22 @@
459 if x["start"] - y["start"] < 0:
460 return -1
461 else:
462- return +1
463-
464+ return +1
465+
466 def gatherinfo (filename):
467 date = datetime.fromtimestamp(os.path.getmtime(filename))
468-
469+
470 cpufile = open ("/proc/cpuinfo")
471 cpuinfo = cpufile.read (10024)
472 cpure = re.search (r"^model name\s*: (.*$)", cpuinfo, re.MULTILINE)
473 cpu = cpure.group(1)
474-
475+
476 gpu_prog = subprocess.Popen("glxinfo", stdout=subprocess.PIPE)
477- gpu_prog.wait ()
478+ gpu_prog.wait ()
479 gpuinfo = gpu_prog.stdout.read (10024)
480 gpure = re.search (r"^OpenGL renderer string: (.*$)", gpuinfo, re.MULTILINE)
481 gpu = gpure.group (1)
482-
483+
484 return {"hostname":gethostname(),
485 "date": date.strftime("%A, %d. %B %Y %I:%M%p"),
486 "uname": " ".join (os.uname ()),
487@@ -67,14 +67,14 @@
488 bar_height = 16
489
490 def draw_bg_graph (ctx, seconds, height):
491-
492+
493 total_width = seconds * width_multiplier
494 ctx.set_source_rgba (0.0, 0.0, 0.0, 0.25)
495-
496+
497 ctx.move_to (0, 0)
498 ctx.line_to (total_width, 0)
499 ctx.stroke ()
500-
501+
502 per_ten = 0
503 for pos in xrange (0, int(total_width), int (0.01 * width_multiplier)):
504 ctx.set_line_width (1)
505@@ -90,67 +90,67 @@
506 ctx.move_to (pos, 0)
507 ctx.line_to (pos, height)
508 ctx.stroke ()
509-
510+
511 per_ten += 1
512 per_ten %= 10
513
514 def build_graph (data, filename, info):
515-
516+
517 padding_left = 6
518 padding_right = 100
519 padding_top = 6
520 padding_bottom = 6
521-
522+
523 total_size = 0.0
524 for item in data:
525 if item['end'] > total_size:
526 total_size = item['end']
527-
528+
529 width = total_size * width_multiplier + padding_left + padding_right
530 height = (len(data) * (bar_height)) + 80 + padding_bottom + padding_top
531- surface = cairo.SVGSurface(filename, width, height)
532-
533+ surface = cairo.SVGSurface(filename, max (width, 800), max (height, 600))
534+
535 ctx = cairo.Context (surface)
536
537 #fill background
538 ctx.set_source_rgb (1, 1, 1)
539- ctx.rectangle (0, 0, width, height)
540+ ctx.rectangle (0, 0, max (width, 800), max (height, 600))
541 ctx.fill ()
542-
543+
544 #print header
545 info['total_time'] = "%s secs" % total_size
546 sheader = header.substitute(info)
547-
548+
549 ctx.translate (padding_left, padding_top)
550 ctx.set_source_rgb (0, 0, 0)
551 for line in sheader.split("\n"):
552 ctx.translate (0, 12)
553 ctx.show_text (line)
554 ctx.fill ()
555-
556- ctx.translate (0, 12)
557-
558- draw_bg_graph (ctx, total_size, len (data) * bar_height + 16)
559-
560+
561+ ctx.translate (6, 12)
562+
563+ draw_bg_graph (ctx, total_size + 0.5, max (len (data) * bar_height + 64, 500))
564+
565 ctx.set_line_width (1)
566 for item in data:
567 x = item['start'] * width_multiplier
568 x1 = (item['end'] - item['start']) * width_multiplier
569 ctx.translate (x, 0)
570-
571+
572 ctx.set_source_rgba (0.35, 0.65, 0.8, 0.5)
573 ctx.rectangle (0, 0, x1, 16)
574 ctx.fill ()
575-
576+
577 ctx.set_source_rgba (0.35, 0.65, 0.8, 1.0)
578 ctx.rectangle (0, 0, x1, 16)
579 ctx.stroke ()
580-
581+
582 ctx.translate (8, 10)
583 ctx.set_source_rgb (0.0, 0.0, 0.0)
584- ctx.show_text ("%s %.2f seconds" % (item['name'], round (item["end"] - item["start"], 2)))
585+ ctx.show_text ("%s %.4f seconds" % (item['name'], item["end"] - item["start"]))
586 ctx.fill()
587-
588+
589 ctx.translate (-x-8, 6)
590
591 def build_data_structure (input):
592@@ -162,13 +162,13 @@
593 start = float(row[1])
594 end = float(row[2])
595 structure.append ({"name": name, "start": start, "end": end})
596-
597+
598 structure.sort (sort_by_domain)
599 return structure
600-
601+
602
603 def usage():
604- print "use --input=filename.log and --output=filename.svg :)"
605+ print "use --input=filename.log and --output=filename.svg :)"
606
607 def main():
608
609@@ -179,7 +179,7 @@
610 print str(err) # will print something like "option -a not recognized"
611 usage()
612 sys.exit(2)
613-
614+
615 output = None
616 input = None
617 for o, a in opts:
618@@ -196,7 +196,7 @@
619 if (not output or not input):
620 usage()
621 sys.exit()
622-
623+
624 data = build_data_structure (input)
625 info = gatherinfo (input)
626 build_graph (data, output, info)