From 821583acae732ede6ee18e2128c49703e82fb47f Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Tue, 8 Mar 2011 18:48:07 -0500 Subject: [PATCH] Use gnome-shell-perf-helper to control windows during perf tests * Run gnome-shell-perf-helper during performance tests * Use MUTTER_WM_CLASS_FILTER to omit all other windows * Add new Scripting methods: createTestWindow, waitTestWindows, destroyTestWindows * Create a single 640x480 test window for testing overview animation performance. https://bugzilla.gnome.org/show_bug.cgi?id=644265 --- js/perf/core.js | 4 ++ js/ui/scripting.js | 99 ++++++++++++++++++++++++++++++++++++++ src/gnome-shell-jhbuild.in | 35 ++++++++++++++ 3 files changed, 138 insertions(+) diff --git a/js/perf/core.js b/js/perf/core.js index b7e64547e..1bbeab7ca 100644 --- a/js/perf/core.js +++ b/js/perf/core.js @@ -38,6 +38,10 @@ function run() { Scripting.scriptEvent('overviewShowDone'); }); + Scripting.destroyTestWindows(); + Scripting.createTestWindow(640, 480, false, false); + Scripting.waitTestWindows(); + yield Scripting.sleep(1000); yield Scripting.waitLeisure(); for (let i = 0; i < 2; i++) { diff --git a/js/ui/scripting.js b/js/ui/scripting.js index b2537f224..2e38d1087 100644 --- a/js/ui/scripting.js +++ b/js/ui/scripting.js @@ -1,5 +1,6 @@ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ +const DBus = imports.dbus; const Gio = imports.gi.Gio; const Mainloop = imports.mainloop; @@ -68,6 +69,104 @@ function waitLeisure() { }; } +const PerfHelperIface = { + name: 'org.gnome.Shell.PerfHelper', + methods: [{ name: 'CreateWindow', inSignature: 'iibb', outSignature: '' }, + { name: 'WaitWindows', inSignature: '', outSignature: '' }, + { name: 'DestroyWindows', inSignature: '', outSignature: ''}] +}; + +const PerfHelper = function () { + this._init(); +}; + +PerfHelper.prototype = { + _init: function() { + DBus.session.proxifyObject(this, 'org.gnome.Shell.PerfHelper', '/org/gnome/Shell/PerfHelper'); + } +}; + +DBus.proxifyPrototype(PerfHelper.prototype, PerfHelperIface); + +let _perfHelper = null; +function _getPerfHelper() { + if (_perfHelper == null) + _perfHelper = new PerfHelper(); + + return _perfHelper; +} + +/** + * createTestWindow: + * @width: width of window, in pixels + * @height: height of window, in pixels + * @alpha: whether the window should be alpha transparent + * @maximized: whethe the window should be created maximized + * + * Creates a window using gnome-shell-perf-helper for testing purposes. + * While this function can be used with yield in an automation + * script to pause until the D-Bus call to the helper process returns, + * because of the normal X asynchronous mapping process, to actually wait + * until the window has been mapped and exposed, use waitTestWindows(). + */ +function createTestWindow(width, height, alpha, maximized) { + let cb; + let perfHelper = _getPerfHelper(); + + perfHelper.CreateWindowRemote(width, height, alpha, maximized, + function(result, excp) { + if (cb) + cb(); + }); + + return function(callback) { + cb = callback; + }; +} + +/** + * waitTestWindows: + * + * Used within an automation script to pause until all windows previously + * created with createTestWindow have been mapped and exposed. + */ +function waitTestWindows() { + let cb; + let perfHelper = _getPerfHelper(); + + perfHelper.WaitWindowsRemote(function(result, excp) { + if (cb) + cb(); + }); + + return function(callback) { + cb = callback; + }; +} + +/** + * destroyTestWindows: + * + * Destroys all windows previously created with createTestWindow(). + * While this function can be used with yield in an automation + * script to pause until the D-Bus call to the helper process returns, + * this doesn't guarantee that Mutter has actually finished the destroy + * process because of normal X asynchronicity. + */ +function destroyTestWindows() { + let cb; + let perfHelper = _getPerfHelper(); + + perfHelper.DestroyWindowsRemote(function(result, excp) { + if (cb) + cb(); + }); + + return function(callback) { + cb = callback; + }; +} + /** * defineScriptEvent * @name: The event will be called script. diff --git a/src/gnome-shell-jhbuild.in b/src/gnome-shell-jhbuild.in index 54dfed862..1cc4ef4d3 100755 --- a/src/gnome-shell-jhbuild.in +++ b/src/gnome-shell-jhbuild.in @@ -169,6 +169,29 @@ def start_dconf_await_service(): wait_for_dbus_name (DCONF_NAME) +PERF_HELPER_NAME = "org.gnome.Shell.PerfHelper" +PERF_HELPER_IFACE = "org.gnome.Shell.PerfHelper" +PERF_HELPER_PATH = "/org/gnome/Shell/PerfHelper" + +def start_perf_helper(): + get_bus_iface() # connect to NameOwnerChanged signal + + self_dir = os.path.dirname(os.path.abspath(sys.argv[0])) + running_from_source_tree = os.path.exists(os.path.join(self_dir, 'gnome-shell-jhbuild.in')) + + if running_from_source_tree: + perf_helper_path = os.path.join(self_dir, "gnome-shell-perf-helper") + else: + perf_helper_path = "@libexecdir@/gnome-shell-perf-helper" + + subprocess.Popen([perf_helper_path]) + wait_for_dbus_name (PERF_HELPER_NAME) + +def stop_perf_helper(): + bus = get_bus() + proxy = bus.get_object(PERF_HELPER_NAME, PERF_HELPER_PATH) + proxy.Exit(dbus_interface=PERF_HELPER_IFACE) + def start_shell(perf_output=None): self_dir = os.path.dirname(os.path.abspath(sys.argv[0])) if os.path.exists(os.path.join(self_dir, 'gnome-shell-jhbuild.in')): @@ -212,6 +235,7 @@ def start_shell(perf_output=None): if options.perf is not None: env['SHELL_PERF_MODULE'] = options.perf + env['MUTTER_WM_CLASS_FILTER'] = 'Gnome-shell-perf-helper' if perf_output is not None: env['SHELL_PERF_OUTPUT'] = perf_output @@ -389,6 +413,8 @@ def run_performance_test(): logs = [] metric_summaries = {} + start_perf_helper() + for i in xrange(0, iters): # We create an empty temporary file that the shell will overwrite # with the contents. @@ -399,17 +425,24 @@ def run_performance_test(): normal_exit = False try: normal_exit = run_shell(perf_output=output_file) + except: + stop_perf_helper() + raise finally: if not normal_exit: os.remove(output_file) if not normal_exit: + stop_perf_helper() return False try: f = open(output_file) output = json.load(f) f.close() + except: + stop_perf_helper() + raise finally: os.remove(output_file) @@ -436,6 +469,8 @@ def run_performance_test(): logs.append(output['log']) + stop_perf_helper() + if options.perf_output or options.perf_upload: # Write a complete report, formatted as JSON. The Javascript/C code that # generates the individual reports we are summarizing here is very careful