diff --git a/taskcluster/taskgraph/decision.py b/taskcluster/taskgraph/decision.py index 4f1d3c37dc74..e79db912e7a1 100644 --- a/taskcluster/taskgraph/decision.py +++ b/taskcluster/taskgraph/decision.py @@ -119,6 +119,10 @@ try_task_config_schema = Schema( Optional("disable-pgo"): bool, Optional("env"): {text_type: text_type}, Optional("gecko-profile"): bool, + Optional("gecko-profile-interval"): float, + Optional("gecko-profile-entries"): int, + Optional("gecko-profile-features"): text_type, + Optional("gecko-profile-threads"): text_type, Optional( "perftest-options", description="Options passed from `mach perftest` to try.", diff --git a/taskcluster/taskgraph/transforms/tests.py b/taskcluster/taskgraph/transforms/tests.py index 1ac60d23fbed..0fe2996b448c 100644 --- a/taskcluster/taskgraph/transforms/tests.py +++ b/taskcluster/taskgraph/transforms/tests.py @@ -1715,11 +1715,23 @@ def set_retry_exit_status(config, tasks): @transforms.add def set_profile(config, tasks): """Set profiling mode for tests.""" - profile = config.params["try_task_config"].get("gecko-profile", False) + ttconfig = config.params["try_task_config"] + profile = ttconfig.get("gecko-profile", False) + settings = ( + "gecko-profile-interval", + "gecko-profile-entries", + "gecko-profile-threads", + "gecko-profile-features", + ) for task in tasks: if profile and task["suite"] in ["talos", "raptor"]: - task["mozharness"]["extra-options"].append("--gecko-profile") + extras = task["mozharness"]["extra-options"] + extras.append("--gecko-profile") + for setting in settings: + value = ttconfig.get(setting) + if value is not None: + extras.append("--" + setting + "=" + str(value)) yield task diff --git a/testing/mozharness/mozharness/mozilla/testing/raptor.py b/testing/mozharness/mozharness/mozilla/testing/raptor.py index d1025eeb7a45..708a6adff408 100644 --- a/testing/mozharness/mozharness/mozilla/testing/raptor.py +++ b/testing/mozharness/mozharness/mozilla/testing/raptor.py @@ -258,6 +258,14 @@ class Raptor( "help": argparse.SUPPRESS, }, ], + [ + ["--geckoProfileFeatures"], + { + "dest": "gecko_profile_features", + "type": "str", + "help": argparse.SUPPRESS, + }, + ], [ ["--gecko-profile"], { @@ -283,6 +291,22 @@ class Raptor( "help": "How many samples to take with the profiler.", }, ], + [ + ["--gecko-profile-threads"], + { + "dest": "gecko_profile_threads", + "type": "str", + "help": "Comma-separated list of threads to sample.", + }, + ], + [ + ["--gecko-profile-features"], + { + "dest": "gecko_profile_features", + "type": "str", + "help": "Features to enable in the profiler.", + }, + ], [ ["--page-cycles"], { @@ -587,6 +611,8 @@ class Raptor( ) or "--geckoProfile" in self.config.get("raptor_cmd_line_args", []) self.gecko_profile_interval = self.config.get("gecko_profile_interval") self.gecko_profile_entries = self.config.get("gecko_profile_entries") + self.gecko_profile_threads = self.config.get("gecko_profile_threads") + self.gecko_profile_features = self.config.get("gecko_profile_features") self.test_packages_url = self.config.get("test_packages_url") self.test_url_params = self.config.get("test_url_params") self.host = self.config.get("host") @@ -631,14 +657,22 @@ class Raptor( gecko_results = [] # If gecko_profile is set, we add that to Raptor's options if self.gecko_profile: - gecko_results.append("--geckoProfile") + gecko_results.append("--gecko-profile") if self.gecko_profile_interval: gecko_results.extend( - ["--geckoProfileInterval", str(self.gecko_profile_interval)] + ["--gecko-profile-interval", str(self.gecko_profile_interval)] ) if self.gecko_profile_entries: gecko_results.extend( - ["--geckoProfileEntries", str(self.gecko_profile_entries)] + ["--gecko-profile-entries", str(self.gecko_profile_entries)] + ) + if self.gecko_profile_features: + gecko_results.extend( + ["--gecko-profile-features", self.gecko_profile_features] + ) + if self.gecko_profile_threads: + gecko_results.extend( + ["--gecko-profile-threads", self.gecko_profile_threads] ) return gecko_results diff --git a/testing/mozharness/mozharness/mozilla/testing/talos.py b/testing/mozharness/mozharness/mozilla/testing/talos.py index 88281a5fd81a..ea5414c61c8c 100755 --- a/testing/mozharness/mozharness/mozilla/testing/talos.py +++ b/testing/mozharness/mozharness/mozilla/testing/talos.py @@ -60,6 +60,13 @@ TalosErrorList = PythonErrorList + [ }, ] +GeckoProfilerSettings = ( + "gecko_profile_interval", + "gecko_profile_entries", + "gecko_profile_features", + "gecko_profile_threads", +) + # TODO: check for running processes on script invocation @@ -167,6 +174,31 @@ class Talos( "help": "The interval between samples taken by the profiler (milliseconds)", }, ], + [ + ["--gecko-profile-entries"], + { + "dest": "gecko_profile_entries", + "type": "int", + "help": "How many samples to take with the profiler", + }, + ], + [ + ["--gecko-profile-features"], + { + "dest": "gecko_profile_features", + "type": "str", + "default": None, + "help": "The features to enable in the profiler (comma-separated)", + }, + ], + [ + ["--gecko-profile-threads"], + { + "dest": "gecko_profile_threads", + "type": "str", + "help": "Comma-separated list of threads to sample.", + }, + ], [ ["--disable-e10s"], { @@ -246,10 +278,22 @@ class Talos( self.repo_path = self.config.get("repo_path") self.obj_path = self.config.get("obj_path") self.tests = None - self.gecko_profile = self.config.get( - "gecko_profile" - ) or "--gecko-profile" in self.config.get("talos_extra_options", []) - self.gecko_profile_interval = self.config.get("gecko_profile_interval") + extra_opts = self.config.get("talos_extra_options", []) + self.gecko_profile = ( + self.config.get("gecko_profile") or "--gecko-profile" in extra_opts + ) + for setting in GeckoProfilerSettings: + value = self.config.get(setting) + arg = "--" + setting.replace("_", "-") + if value is None: + try: + value = extra_opts[extra_opts.index(arg) + 1] + except ValueError: + pass # Not found + setattr(self, setting, value) + if not self.gecko_profile: + self.warning("enabling Gecko profiler for %s setting" % setting) + self.gecko_profile = True self.pagesets_name = None self.benchmark_zip = None self.webextensions_zip = None @@ -263,10 +307,11 @@ class Talos( # finally, if gecko_profile is set, we add that to the talos options if self.gecko_profile: gecko_results.append("--gecko-profile") - if self.gecko_profile_interval: - gecko_results.extend( - ["--gecko-profile-interval", str(self.gecko_profile_interval)] - ) + for setting in GeckoProfilerSettings: + value = getattr(self, setting, None) + if value: + arg = "--" + setting.replace("_", "-") + gecko_results.extend([arg, str(value)]) return gecko_results def query_abs_dirs(self): diff --git a/testing/raptor/raptor/browsertime/base.py b/testing/raptor/raptor/browsertime/base.py index 88c9bce4fb3f..6c6ab7a43005 100644 --- a/testing/raptor/raptor/browsertime/base.py +++ b/testing/raptor/raptor/browsertime/base.py @@ -308,20 +308,37 @@ class Browsertime(Perftest): ] = self.results_handler.result_dir_for_test(test) self._init_gecko_profiling(test) browsertime_options.append("--firefox.geckoProfiler") - browsertime_options.extend( - [ + for option, browser_time_option, default in ( + ( + "gecko_profile_features", "--firefox.geckoProfilerParams.features", "js,leaf,stackwalk,cpu,threads", - ] - ) - - for option, browser_time_option in ( - ("gecko_profile_interval", "--firefox.geckoProfilerParams.interval"), - ("gecko_profile_entries", "--firefox.geckoProfilerParams.bufferSize"), + ), + ( + "gecko_profile_threads", + "--firefox.geckoProfilerParams.threads", + "GeckoMain,Compositor", + ), + ( + "gecko_profile_interval", + "--firefox.geckoProfilerParams.interval", + None, + ), + ( + "gecko_profile_entries", + "--firefox.geckoProfilerParams.bufferSize", + None, + ), ): + # 0 is a valid value. The setting may be present but set to None. value = self.config.get(option) if value is None: value = test.get(option) + if value is None: + value = default + if option == "gecko_profile_threads": + extra = self.config.get("gecko_profile_extra_threads", []) + value = ",".join(value.split(",") + extra) if value is not None: browsertime_options.extend([browser_time_option, str(value)]) diff --git a/testing/raptor/raptor/cmdline.py b/testing/raptor/raptor/cmdline.py index 13aade4567ba..f33fda825852 100644 --- a/testing/raptor/raptor/cmdline.py +++ b/testing/raptor/raptor/cmdline.py @@ -199,10 +199,23 @@ def create_parser(mach_interface=False): ) add_arg( "--gecko-profile-thread", - dest="gecko_profile_threads", + dest="gecko_profile_extra_threads", + default=[], action="append", help="Name of the extra thread to be profiled", ) + add_arg( + "--gecko-profile-threads", + dest="gecko_profile_threads", + type=str, + help="Comma-separated list of all threads to sample", + ) + add_arg( + "--gecko-profile-features", + dest="gecko_profile_features", + type=str, + help="What features to enable in the profiler", + ) add_arg( "--symbolsPath", dest="symbols_path", diff --git a/testing/raptor/raptor/manifest.py b/testing/raptor/raptor/manifest.py index 63979c8ed9f7..7ffe3ae7c2bd 100644 --- a/testing/raptor/raptor/manifest.py +++ b/testing/raptor/raptor/manifest.py @@ -266,6 +266,10 @@ def write_test_settings_json(args, test_details, oskey): } ) + features = test_details.get("gecko_profile_features") + if features: + test_settings["raptor-options"]["gecko_profile_features"] = features + if test_details.get("newtab_per_cycle", None) is not None: test_settings["raptor-options"]["newtab_per_cycle"] = bool( test_details["newtab_per_cycle"] @@ -396,17 +400,27 @@ def get_raptor_test_list(args, oskey): threads = list( filter(None, next_test.get("gecko_profile_threads", "").split(",")) ) - threads.extend(args.gecko_profile_threads) + threads.extend(args.gecko_profile_threads.split(",")) + if ( + "gecko_profile_extra_threads" in args + and args.gecko_profile_extra_threads is not None + ): + threads.extend(getattr(args, "gecko_profile_extra_threads", [])) next_test["gecko_profile_threads"] = ",".join(threads) - LOG.info( - "gecko-profiling extra threads %s" % args.gecko_profile_threads - ) + LOG.info("gecko-profiling threads %s" % args.gecko_profile_threads) + if ( + "gecko_profile_features" in args + and args.gecko_profile_features is not None + ): + next_test["gecko_profile_features"] = args.gecko_profile_features + LOG.info("gecko-profiling features %s" % args.gecko_profile_features) else: - # if the gecko profiler is not enabled, ignore all of it's settings + # if the gecko profiler is not enabled, ignore all of its settings next_test.pop("gecko_profile_entries", None) next_test.pop("gecko_profile_interval", None) next_test.pop("gecko_profile_threads", None) + next_test.pop("gecko_profile_features", None) if args.debug_mode is True: next_test["debug_mode"] = True diff --git a/testing/raptor/raptor/perftest.py b/testing/raptor/raptor/perftest.py index ea5e62193488..665e984cfe7c 100644 --- a/testing/raptor/raptor/perftest.py +++ b/testing/raptor/raptor/perftest.py @@ -77,6 +77,9 @@ class Perftest(object): gecko_profile=False, gecko_profile_interval=None, gecko_profile_entries=None, + gecko_profile_extra_threads=None, + gecko_profile_threads=None, + gecko_profile_features=None, symbols_path=None, host=None, power_test=False, @@ -118,6 +121,9 @@ class Perftest(object): "gecko_profile": gecko_profile, "gecko_profile_interval": gecko_profile_interval, "gecko_profile_entries": gecko_profile_entries, + "gecko_profile_extra_threads": gecko_profile_extra_threads, + "gecko_profile_threads": gecko_profile_threads, + "gecko_profile_features": gecko_profile_features, "symbols_path": symbols_path, "host": host, "power_test": power_test, diff --git a/testing/raptor/raptor/raptor.py b/testing/raptor/raptor/raptor.py index 4a53a3d4fd16..e406f8106704 100644 --- a/testing/raptor/raptor/raptor.py +++ b/testing/raptor/raptor/raptor.py @@ -124,6 +124,9 @@ def main(args=sys.argv[1:]): gecko_profile=args.gecko_profile, gecko_profile_interval=args.gecko_profile_interval, gecko_profile_entries=args.gecko_profile_entries, + gecko_profile_extra_threads=args.gecko_profile_extra_threads, + gecko_profile_threads=args.gecko_profile_threads, + gecko_profile_features=args.gecko_profile_features, symbols_path=args.symbols_path, host=args.host, power_test=args.power_test, diff --git a/testing/raptor/test/test_manifest.py b/testing/raptor/test/test_manifest.py index 46c2eb0650f5..ae71f2be35ca 100644 --- a/testing/raptor/test/test_manifest.py +++ b/testing/raptor/test/test_manifest.py @@ -210,6 +210,7 @@ def test_get_raptor_test_list_gecko_profiling_enabled(create_args): assert test_list[0].get("gecko_profile_entries") == "14000000" assert test_list[0].get("gecko_profile_interval") == "1" assert test_list[0].get("gecko_profile_threads") is None + assert test_list[0].get("gecko_profile_features") is None def test_get_raptor_test_list_gecko_profiling_enabled_args_override(create_args): @@ -218,7 +219,8 @@ def test_get_raptor_test_list_gecko_profiling_enabled_args_override(create_args) gecko_profile=True, gecko_profile_entries=42, gecko_profile_interval=100, - gecko_profile_threads=["Foo"], + gecko_profile_threads="Foo", + gecko_profile_features="Mood,UserNetWorth", browser_cycles=1, ) @@ -229,6 +231,27 @@ def test_get_raptor_test_list_gecko_profiling_enabled_args_override(create_args) assert test_list[0]["gecko_profile_entries"] == "42" assert test_list[0]["gecko_profile_interval"] == "100" assert test_list[0]["gecko_profile_threads"] == "Foo" + assert test_list[0]["gecko_profile_features"] == "Mood,UserNetWorth" + + +def test_get_raptor_test_list_gecko_profiling_enabled_extra_args_override(create_args): + args = create_args( + test="amazon", + gecko_profile=True, + gecko_profile_entries=42, + gecko_profile_interval=100, + gecko_profile_extra_threads=["Foo", "Oof"], + gecko_profile_threads="String,Rope", + browser_cycles=1, + ) + + test_list = get_raptor_test_list(args, mozinfo.os) + assert len(test_list) == 1 + assert test_list[0]["name"] == "amazon" + assert test_list[0]["gecko_profile"] is True + assert test_list[0]["gecko_profile_entries"] == "42" + assert test_list[0]["gecko_profile_interval"] == "100" + assert test_list[0]["gecko_profile_threads"] == "String,Rope,Foo,Oof" def test_get_raptor_test_list_gecko_profiling_disabled(create_args): @@ -238,6 +261,7 @@ def test_get_raptor_test_list_gecko_profiling_disabled(create_args): gecko_profile_entries=42, gecko_profile_interval=100, gecko_profile_threads=["Foo"], + gecko_profile_features=["Temperature"], browser_cycles=1, ) @@ -248,6 +272,7 @@ def test_get_raptor_test_list_gecko_profiling_disabled(create_args): assert test_list[0].get("gecko_profile_entries") is None assert test_list[0].get("gecko_profile_interval") is None assert test_list[0].get("gecko_profile_threads") is None + assert test_list[0].get("gecko_profile_features") is None def test_get_raptor_test_list_gecko_profiling_disabled_args_override(create_args): @@ -257,6 +282,7 @@ def test_get_raptor_test_list_gecko_profiling_disabled_args_override(create_args gecko_profile_entries=42, gecko_profile_interval=100, gecko_profile_threads=["Foo"], + gecko_profile_features=["Temperature"], browser_cycles=1, ) @@ -267,6 +293,7 @@ def test_get_raptor_test_list_gecko_profiling_disabled_args_override(create_args assert test_list[0].get("gecko_profile_entries") is None assert test_list[0].get("gecko_profile_interval") is None assert test_list[0].get("gecko_profile_threads") is None + assert test_list[0].get("gecko_profile_features") is None def test_get_raptor_test_list_debug_mode(create_args): diff --git a/testing/raptor/webext/raptor/runner.js b/testing/raptor/webext/raptor/runner.js index cbffabe444b2..6870e72fd772 100644 --- a/testing/raptor/webext/raptor/runner.js +++ b/testing/raptor/webext/raptor/runner.js @@ -70,6 +70,7 @@ var geckoProfiling = false; var geckoInterval = 1; var geckoEntries = 1000000; var geckoThreads = []; +var geckoFeatures = null; var debugMode = 0; var screenCapture = false; @@ -136,6 +137,7 @@ async function getTestSettings() { geckoEntries = settings.gecko_profile_entries; geckoInterval = settings.gecko_profile_interval; geckoThreads = settings.gecko_profile_threads; + geckoFeatures = settings.gecko_profile_features; } if (settings.screen_capture !== undefined) { @@ -378,10 +380,13 @@ async function startGeckoProfiling() { "status", `starting Gecko profiling for threads: ${geckoThreads}` ); + const features = geckoFeatures + ? geckoFeatures.split(",") + : ["js", "leaf", "stackwalk", "cpu", "threads", "responsiveness"]; await ext.geckoProfiler.start({ bufferSize: geckoEntries, interval: geckoInterval, - features: ["js", "leaf", "stackwalk", "cpu", "threads", "responsiveness"], + features, threads: geckoThreads.split(","), }); } diff --git a/testing/talos/talos/cmdline.py b/testing/talos/talos/cmdline.py index 125c44eec6ea..c297241504ce 100644 --- a/testing/talos/talos/cmdline.py +++ b/testing/talos/talos/cmdline.py @@ -160,6 +160,18 @@ def create_parser(mach_interface=False): type=int, help="How many samples to take with the profiler", ) + add_arg( + "--gecko-profile-features", + dest="gecko_profile_features", + type=str, + help="Comma-separated list of features to enable in the profiler", + ) + add_arg( + "--gecko-profile-threads", + dest="gecko_profile_threads", + type=str, + help="Comma-separated list of threads to sample", + ) add_arg( "--extension", dest="extensions", diff --git a/testing/talos/talos/config.py b/testing/talos/talos/config.py index 35ef31ed31ad..2703c34df9a5 100644 --- a/testing/talos/talos/config.py +++ b/testing/talos/talos/config.py @@ -23,7 +23,8 @@ DEFAULTS = dict( buildid="testbuildid", init_url="getInfo.html", env={"NO_EM_RESTART": "1"}, - # base data for all tests + # base data for all tests. Note that any None here will end up converted to + # an empty string in useBaseTestDefaults. basetest=dict( cycles=1, profile_path="${talos}/base_profile", @@ -67,6 +68,8 @@ GLOBAL_OVERRIDES = ( "gecko_profile", "gecko_profile_interval", "gecko_profile_entries", + "gecko_profile_features", + "gecko_profile_threads", "tpcycles", "tppagecycles", "tpmanifest", diff --git a/testing/talos/talos/gecko_profile.py b/testing/talos/talos/gecko_profile.py index 98a1c2148233..e4c6fa7e6482 100644 --- a/testing/talos/talos/gecko_profile.py +++ b/testing/talos/talos/gecko_profile.py @@ -38,7 +38,12 @@ class GeckoProfile(object): gecko_profile_interval = test_config.get("gecko_profile_interval", 1) gecko_profile_entries = test_config.get("gecko_profile_entries", 1000000) - gecko_profile_threads = "GeckoMain,Compositor" + gecko_profile_features = test_config.get( + "gecko_profile_features", "js,leaf,stackwalk,cpu,threads" + ) + gecko_profile_threads = test_config.get( + "gecko_profile_threads", "GeckoMain,Compositor" + ) if browser_config["enable_webrender"]: gecko_profile_threads += ",WR,Renderer" @@ -67,6 +72,7 @@ class GeckoProfile(object): "gecko_profile_interval": gecko_profile_interval, "gecko_profile_entries": gecko_profile_entries, "gecko_profile_dir": gecko_profile_dir, + "gecko_profile_features": gecko_profile_features, "gecko_profile_threads": gecko_profile_threads, } @@ -90,6 +96,7 @@ class GeckoProfile(object): "MOZ_PROFILER_STARTUP_NO_BASE": "1", "MOZ_PROFILER_STARTUP_INTERVAL": str(self.option("interval")), "MOZ_PROFILER_STARTUP_ENTRIES": str(self.option("entries")), + "MOZ_PROFILER_STARTUP_FEATURES": str(self.option("features")), "MOZ_PROFILER_STARTUP_FILTERS": str(self.option("threads")), } ) diff --git a/testing/talos/talos/pageloader/chrome/Profiler.js b/testing/talos/talos/pageloader/chrome/Profiler.js index ada561b43053..5c515f14815c 100644 --- a/testing/talos/talos/pageloader/chrome/Profiler.js +++ b/testing/talos/talos/pageloader/chrome/Profiler.js @@ -31,7 +31,11 @@ var Profiler; var currentTest = ""; // Profiling settings. - var profiler_interval, profiler_entries, profiler_threadsArray, profiler_dir; + var profiler_interval, + profiler_entries, + profiler_threadsArray, + profiler_featuresArray, + profiler_dir; /* eslint-disable mozilla/use-chromeutils-import */ try { @@ -62,6 +66,7 @@ var Profiler; * The following properties on the object are respected: * - gecko_profile_interval * - gecko_profile_entries + * - gecko_profile_features * - gecko_profile_threads * - gecko_profile_dir */ @@ -74,11 +79,14 @@ var Profiler; Number.isFinite(obj.gecko_profile_interval * 1) && "gecko_profile_entries" in obj && Number.isFinite(obj.gecko_profile_entries * 1) && + "gecko_profile_features" in obj && + typeof obj.gecko_profile_features == "string" && "gecko_profile_threads" in obj && typeof obj.gecko_profile_threads == "string" ) { profiler_interval = obj.gecko_profile_interval; profiler_entries = obj.gecko_profile_entries; + profiler_featuresArray = obj.gecko_profile_features.split(","); profiler_threadsArray = obj.gecko_profile_threads.split(","); profiler_dir = obj.gecko_profile_dir; enabled = true; @@ -95,7 +103,7 @@ var Profiler; _profiler.StartProfiler( profiler_entries, profiler_interval, - ["js", "leaf", "stackwalk", "threads", "cpu"], + profiler_featuresArray, profiler_threadsArray ); _profiler.PauseSampling(); diff --git a/testing/talos/talos/talos-powers/api.js b/testing/talos/talos/talos-powers/api.js index fdc64f3cba04..c38f45b0fae4 100644 --- a/testing/talos/talos/talos-powers/api.js +++ b/testing/talos/talos/talos-powers/api.js @@ -119,7 +119,7 @@ TalosPowersService.prototype = { Services.profiler.StartProfiler( data.entries, data.interval, - ["js", "leaf", "stackwalk", "threads", "cpu"], + data.featuresArray, data.threadsArray ); diff --git a/testing/talos/talos/talos-powers/content/TalosContentProfiler.js b/testing/talos/talos/talos-powers/content/TalosContentProfiler.js index f82c46df1f08..7d13601d5d13 100644 --- a/testing/talos/talos/talos-powers/content/TalosContentProfiler.js +++ b/testing/talos/talos/talos-powers/content/TalosContentProfiler.js @@ -32,7 +32,7 @@ var TalosContentProfiler; var currentTest = "unknown"; // Profiler settings. - var interval, entries, threadsArray, profileDir; + var interval, entries, featuresArray, threadsArray, profileDir; /** * Emits a TalosContentProfiler prefixed event and then returns a Promise @@ -123,6 +123,7 @@ var TalosContentProfiler; * The following properties on the object are respected: * gecko_profile_interval (int) * gecko_profile_entries (int) + * gecko_profile_features (string, comma separated list of features to enable) * gecko_profile_threads (string, comma separated list of threads to filter with) * gecko_profile_dir (string) */ @@ -135,11 +136,14 @@ var TalosContentProfiler; Number.isFinite(obj.gecko_profile_interval * 1) && "gecko_profile_entries" in obj && Number.isFinite(obj.gecko_profile_entries * 1) && + "gecko_profile_features" in obj && + typeof obj.gecko_profile_features == "string" && "gecko_profile_threads" in obj && typeof obj.gecko_profile_threads == "string" ) { interval = obj.gecko_profile_interval; entries = obj.gecko_profile_entries; + featuresArray = obj.gecko_profile_features.split(","); threadsArray = obj.gecko_profile_threads.split(","); profileDir = obj.gecko_profile_dir; initted = true; @@ -180,6 +184,7 @@ var TalosContentProfiler; return sendEventAndWait("Profiler:Begin", { interval, entries, + featuresArray, threadsArray, }); } diff --git a/testing/talos/talos/talos-powers/content/TalosParentProfiler.jsm b/testing/talos/talos/talos-powers/content/TalosParentProfiler.jsm index 5c7a49b7a534..080fa310dc80 100644 --- a/testing/talos/talos/talos-powers/content/TalosParentProfiler.jsm +++ b/testing/talos/talos/talos-powers/content/TalosParentProfiler.jsm @@ -29,6 +29,7 @@ const TalosParentProfiler = { // Profiler settings. interval: undefined, entries: undefined, + featuresArray: undefined, threadsArray: undefined, profileDir: undefined, @@ -47,6 +48,7 @@ const TalosParentProfiler = { * The following properties on the object are respected: * gecko_profile_interval (int) * gecko_profile_entries (int) + * gecko_profile_features (string, comma separated list of features to enable) * gecko_profile_threads (string, comma separated list of threads to filter with) * gecko_profile_dir (string) */ @@ -59,11 +61,14 @@ const TalosParentProfiler = { Number.isFinite(obj.gecko_profile_interval * 1) && "gecko_profile_entries" in obj && Number.isFinite(obj.gecko_profile_entries * 1) && + "gecko_profile_features" in obj && + typeof obj.gecko_profile_features == "string" && "gecko_profile_threads" in obj && typeof obj.gecko_profile_threads == "string" ) { this.interval = obj.gecko_profile_interval; this.entries = obj.gecko_profile_entries; + this.featuresArray = obj.gecko_profile_features.split(","); this.threadsArray = obj.gecko_profile_threads.split(","); this.profileDir = obj.gecko_profile_dir; this.initted = true; @@ -122,6 +127,7 @@ const TalosParentProfiler = { this.TalosPowers.profilerBegin({ entries: this.entries, interval: this.interval, + featuresArray: this.featuresArray, threadsArray: this.threadsArray, }); } else { diff --git a/testing/talos/talos/test.py b/testing/talos/talos/test.py index 5aabcd4a28e1..f78ad3b08d1d 100644 --- a/testing/talos/talos/test.py +++ b/testing/talos/talos/test.py @@ -108,6 +108,8 @@ class TsBase(Test): "gecko_profile", "gecko_profile_interval", "gecko_profile_entries", + "gecko_profile_features", + "gecko_profile_threads", "gecko_profile_startup", "preferences", "xperf_counters", @@ -336,6 +338,8 @@ class PageloaderTest(Test): "gecko_profile", "gecko_profile_interval", "gecko_profile_entries", + "gecko_profile_features", + "gecko_profile_threads", "tptimeout", "win_counters", "w7_counters", diff --git a/testing/talos/talos/tests/tart/addon/content/Profiler.js b/testing/talos/talos/tests/tart/addon/content/Profiler.js index fe599f7e8f4a..145b87f542dd 100644 --- a/testing/talos/talos/tests/tart/addon/content/Profiler.js +++ b/testing/talos/talos/tests/tart/addon/content/Profiler.js @@ -31,7 +31,11 @@ var Profiler; var currentTest = ""; // Profiling settings. - var profiler_interval, profiler_entries, profiler_threadsArray, profiler_dir; + var profiler_interval, + profiler_entries, + profiler_featuresArray, + profiler_threadsArray, + profiler_dir; try { // eslint-disable-next-line mozilla/use-services @@ -61,6 +65,7 @@ var Profiler; * The following properties on the object are respected: * - gecko_profile_interval * - gecko_profile_entries + * - gecko_profile_features * - gecko_profile_threads * - gecko_profile_dir */ @@ -73,11 +78,14 @@ var Profiler; Number.isFinite(obj.gecko_profile_interval * 1) && "gecko_profile_entries" in obj && Number.isFinite(obj.gecko_profile_entries * 1) && + "gecko_profile_features" in obj && + typeof obj.gecko_profile_features == "string" && "gecko_profile_threads" in obj && typeof obj.gecko_profile_threads == "string" ) { profiler_interval = obj.gecko_profile_interval; profiler_entries = obj.gecko_profile_entries; + profiler_featuresArray = obj.gecko_profile_features.split(","); profiler_threadsArray = obj.gecko_profile_threads.split(","); profiler_dir = obj.gecko_profile_dir; enabled = true; @@ -94,7 +102,7 @@ var Profiler; _profiler.StartProfiler( profiler_entries, profiler_interval, - ["js", "leaf", "stackwalk", "threads", "cpu"], + profiler_featuresArray, profiler_threadsArray ); _profiler.PauseSampling(); diff --git a/testing/talos/talos/tests/tresize/addon/content/Profiler.js b/testing/talos/talos/tests/tresize/addon/content/Profiler.js index f40bc139a92a..f6d907a4468e 100644 --- a/testing/talos/talos/tests/tresize/addon/content/Profiler.js +++ b/testing/talos/talos/tests/tresize/addon/content/Profiler.js @@ -31,7 +31,11 @@ var Profiler; var currentTest = ""; // Profiling settings. - var profiler_interval, profiler_entries, profiler_threadsArray, profiler_dir; + var profiler_interval, + profiler_entries, + profiler_featuresArray, + profiler_threadsArray, + profiler_dir; try { // eslint-disable-next-line mozilla/use-services @@ -61,6 +65,7 @@ var Profiler; * The following properties on the object are respected: * - gecko_profile_interval * - gecko_profile_entries + * - gecko_profile_features * - gecko_profile_threads * - gecko_profile_dir */ @@ -73,11 +78,14 @@ var Profiler; Number.isFinite(obj.gecko_profile_interval * 1) && "gecko_profile_entries" in obj && Number.isFinite(obj.gecko_profile_entries * 1) && + "gecko_profile_features" in obj && + typeof obj.gecko_profile_features == "string" && "gecko_profile_threads" in obj && typeof obj.gecko_profile_threads == "string" ) { profiler_interval = obj.gecko_profile_interval; profiler_entries = obj.gecko_profile_entries; + profiler_featuresArray = obj.gecko_profile_features.split(","); profiler_threadsArray = obj.gecko_profile_threads.split(","); profiler_dir = obj.gecko_profile_dir; enabled = true; @@ -94,7 +102,7 @@ var Profiler; _profiler.StartProfiler( profiler_entries, profiler_interval, - ["js", "leaf", "stackwalk", "threads", "cpu"], + profiler_featuresArray, profiler_threadsArray ); _profiler.PauseSampling(); diff --git a/tools/tryselect/task_config.py b/tools/tryselect/task_config.py index 0cf8f5f96766..8cc76100019b 100644 --- a/tools/tryselect/task_config.py +++ b/tools/tryselect/task_config.py @@ -328,6 +328,39 @@ class GeckoProfile(TryConfig): "help": "Create and upload a gecko profile during talos/raptor tasks.", }, ], + [ + ["--gecko-profile-interval"], + { + "dest": "gecko_profile_interval", + "type": float, + "help": "How frequently to take samples (ms)", + }, + ], + [ + ["--gecko-profile-entries"], + { + "dest": "gecko_profile_entries", + "type": int, + "help": "How many samples to take with the profiler", + }, + ], + [ + ["--gecko-profile-features"], + { + "dest": "gecko_profile_features", + "type": str, + "default": None, + "help": "Set the features enabled for the profiler.", + }, + ], + [ + ["--gecko-profile-threads"], + { + "dest": "gecko_profile_threads", + "type": str, + "help": "Comma-separated list of threads to sample.", + }, + ], # For backwards compatibility [ ["--talos-profile"], @@ -350,10 +383,25 @@ class GeckoProfile(TryConfig): ], ] - def try_config(self, profile, **kwargs): - if profile: + def try_config( + self, + profile, + gecko_profile_interval, + gecko_profile_entries, + gecko_profile_features, + gecko_profile_threads, + **kwargs + ): + if profile or not all( + kwargs.get(s) is None + for s in (gecko_profile_features, gecko_profile_threads) + ): return { "gecko-profile": True, + "gecko-profile-interval": gecko_profile_interval, + "gecko-profile-entries": gecko_profile_entries, + "gecko-profile-features": gecko_profile_features, + "gecko-profile-threads": gecko_profile_threads, }