Bug 1582741 - Rewrite native allocations test as an xpcshell test; r=canaltinova
☠☠ backed out by 48f393dfe9ac ☠ ☠
authorGreg Tatum <gtatum@mozilla.com>
Tue, 12 Nov 2019 17:29:06 +0000
changeset 501609 b48b1fa02fccc7e29748bc406eb6dcae03996f4e
parent 501608 e9714539ae904f92182379decdbf66d0fcb5c13b
child 501610 cd7174320d45cc4d43412e9bc667d7a9bcc9559a
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscanaltinova
bugs1582741
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1582741 - Rewrite native allocations test as an xpcshell test; r=canaltinova The bloat log was not compatible with the native allocations, and is always on for debug builds of mochitests. We had no native allocation coverage on debug builds because of it. This commit rewrites the test as an xpcshell test which is both faster and simpler. I don't think we need the added complexity of running the test in the full browser environment. An xpcshell test fully excercises the code in a simpler fashion. Differential Revision: https://phabricator.services.mozilla.com/D51934
tools/profiler/tests/browser/browser.ini
tools/profiler/tests/browser/browser_test_feature_nativeallocations.js
tools/profiler/tests/shared-head.js
tools/profiler/tests/xpcshell/test_feature_nativeallocations.js
tools/profiler/tests/xpcshell/xpcshell.ini
--- a/tools/profiler/tests/browser/browser.ini
+++ b/tools/profiler/tests/browser/browser.ini
@@ -7,11 +7,10 @@ support-files =
   multi_frame.html
   simple.html
   single_frame.html
 
 [browser_test_feature_ipcmessages.js]
 [browser_test_feature_jsallocations.js]
 [browser_test_feature_nostacksampling.js]
 [browser_test_feature_preferencereads.js]
-[browser_test_feature_nativeallocations.js]
 [browser_test_profile_single_frame_page_info.js]
 [browser_test_profile_multi_frame_page_info.js]
deleted file mode 100644
--- a/tools/profiler/tests/browser/browser_test_feature_nativeallocations.js
+++ /dev/null
@@ -1,107 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Test the native allocations feature. This is done as a browser test to ensure
- * that we realistically try out how the native allocations are running. This
- * ensures that we are collecting allocations for the content process and the
- * parent process.
- */
-add_task(async function test_profile_feature_nativeallocations() {
-  if (!AppConstants.MOZ_GECKO_PROFILER) {
-    return;
-  }
-  Assert.ok(
-    !Services.profiler.IsActive(),
-    "The profiler is not currently active"
-  );
-
-  info("Start the profiler to test the native allocations.");
-  startProfiler({
-    features: ["threads", "leaf", "nativeallocations"],
-  });
-
-  const env = Cc["@mozilla.org/process/environment;1"].getService(
-    Ci.nsIEnvironment
-  );
-
-  if (env.get("XPCOM_MEM_BLOAT_LOG")) {
-    info("Native allocations do not currently work with the bloat log.");
-    // Stop the profiler and exit. Note that this happens after we have already
-    // turned on the profiler so that we can still test this code path.
-    Services.profiler.StopProfiler();
-    return;
-  }
-
-  info("Launch a new tab to kick off a content process.");
-
-  const url = BASE_URL + "do_work_500ms.html";
-  await BrowserTestUtils.withNewTab(url, async contentBrowser => {
-    const contentPid = await ContentTask.spawn(
-      contentBrowser,
-      null,
-      () => Services.appinfo.processID
-    );
-
-    info("Wait 100ms so that we know some work has been done.");
-    await wait(100);
-
-    info(
-      "Check that we can get some allocations when the feature is turned on."
-    );
-    {
-      const { parentThread, contentThread } = await stopProfilerAndGetThreads(
-        contentPid
-      );
-      Assert.greater(
-        getPayloadsOfType(parentThread, "Native allocation").length,
-        0,
-        "Allocations were recorded for the parent process' main thread when the " +
-          "Native Allocation feature was turned on."
-      );
-      Assert.greater(
-        getPayloadsOfType(contentThread, "Native allocation").length,
-        0,
-        "Allocations were recorded for the content process' main thread when the " +
-          "Native Allocation feature was turned on."
-      );
-    }
-
-    info(
-      "Flush out any straggling allocation markers that may have not been " +
-        "collected yet by starting and stopping the profiler once."
-    );
-    startProfiler({ features: ["threads", "leaf"] });
-    await stopProfilerAndGetThreads(contentPid);
-
-    info("Now reload the tab with a clean run.");
-    gBrowser.reload();
-    await wait(100);
-    startProfiler({ features: ["threads", "leaf"] });
-
-    info(
-      "Check that no allocations were recorded, and allocation tracking was " +
-        "correctly turned off."
-    );
-
-    {
-      const { parentThread, contentThread } = await stopProfilerAndGetThreads(
-        contentPid
-      );
-      Assert.equal(
-        getPayloadsOfType(parentThread, "Native allocation").length,
-        0,
-        "No allocations were recorded for the parent processes' main thread when " +
-          "Native allocation was not turned on."
-      );
-
-      Assert.equal(
-        getPayloadsOfType(contentThread, "Native allocation").length,
-        0,
-        "No allocations were recorded for the content processes' main thread when " +
-          "Native allocation was not turned on."
-      );
-    }
-  });
-});
--- a/tools/profiler/tests/shared-head.js
+++ b/tools/profiler/tests/shared-head.js
@@ -103,8 +103,20 @@ function captureAtLeastOneJsSample() {
   const sampleCount = getProfileSampleCount();
   // Create an infinite loop until a sample has been collected.
   while (true) {
     if (sampleCount < getProfileSampleCount()) {
       return sampleCount;
     }
   }
 }
+
+/**
+ * This function pauses the profiler before getting the profile. Then after the
+ * getting the data, the profiler is stopped, and all profiler data is removed.
+ * @returns {Promise<Profile>}
+ */
+async function stopAndGetProfile() {
+  Services.profiler.PauseSampling();
+  const profile = await Services.profiler.getProfileDataAsync();
+  Services.profiler.StopProfiler();
+  return profile;
+}
new file mode 100644
--- /dev/null
+++ b/tools/profiler/tests/xpcshell/test_feature_nativeallocations.js
@@ -0,0 +1,83 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+add_task(async () => {
+  if (!AppConstants.MOZ_GECKO_PROFILER) {
+    return;
+  }
+  Assert.ok(
+    !Services.profiler.IsActive(),
+    "The profiler is not currently active"
+  );
+
+  info(
+    "Test that the profiler can install memory hooks and collect native allocation " +
+      "information in the marker payloads."
+  );
+  {
+    info("Start the profiler.");
+    startProfiler({
+      // Increase the entries so we don't overflow the buffer.
+      entries: 1e8,
+      // Only instrument the main thread.
+      threads: ["GeckoMain"],
+      features: ["threads", "leaf", "nativeallocations"],
+    });
+
+    info(
+      "Do some JS work for a little bit. This will increase the amount of allocations " +
+        "that take place."
+    );
+    doWork();
+
+    info(
+      "Go ahead and wait for a periodic sample as well, in order to make sure that " +
+        "the native allocations play nicely with the rest of the profiler machinery."
+    );
+    await Services.profiler.waitOnePeriodicSampling();
+
+    info("Get the profile data and analyze it.");
+    const profile = await stopAndGetProfile();
+
+    const allocationPayloads = getPayloadsOfType(
+      profile.threads[0],
+      "Native allocation"
+    );
+
+    Assert.greater(
+      allocationPayloads.length,
+      0,
+      "Native allocation payloads were recorded for the parent process' main thread when " +
+        "the Native Allocation feature was turned on."
+    );
+  }
+
+  info("Restart the profiler, to ensure that we get no more allocations.");
+  {
+    startProfiler({ features: ["threads", "leaf"] });
+    info("Do some work again.");
+    doWork();
+    info("Wait for the periodic sampling.");
+    await Services.profiler.waitOnePeriodicSampling();
+
+    const profile = await stopAndGetProfile();
+    const allocationPayloads = getPayloadsOfType(
+      profile.threads[0],
+      "Native allocation"
+    );
+
+    Assert.equal(
+      allocationPayloads.length,
+      0,
+      "No native allocations were collected when the feature was disabled."
+    );
+  }
+});
+
+function doWork() {
+  this.n = 0;
+  for (let i = 0; i < 1e5; i++) {
+    this.n += Math.random();
+  }
+}
--- a/tools/profiler/tests/xpcshell/xpcshell.ini
+++ b/tools/profiler/tests/xpcshell/xpcshell.ini
@@ -17,16 +17,17 @@ skip-if = true
 skip-if = (os == "win" && processor == "aarch64") # aarch64 due to 1536652
 [test_enterjit_osr_disabling.js]
 skip-if = !debug
 [test_enterjit_osr_enabling.js]
 skip-if = !debug
 [test_asm.js]
 [test_feature_mainthreadio.js]
 skip-if = release_or_beta || (os == "win" && processor == "aarch64") # The IOInterposer is in an ifdef, aarch64 due to 1536657
+[test_feature_nativeallocations.js]
 
 # Native stackwalking is somewhat unreliable depending on the platform.
 #
 # We don't have frame pointers on macOS release and beta, so stack walking does not
 # work. See Bug 1571216 for more details.
 #
 # Linux can be very unreliable when native stackwalking through JavaScript code.
 # See Bug 1434402 for more details.