gecko-dev/toolkit/components/telemetry/tests/unit/test_TelemetryGC.js
Paul Bone eca8e2da04 Bug 1518713 - Make it easier to update the GC telemetry unit test r=florian
By refactoring this test code we can more easily adjust the number of fields
there are supposed to be in these objects.

--HG--
extra : source : 270b892f2c93aaed926c4ec70600f1c74b6325af
extra : histedit_source : 1e0d7ca3033dfb5aff8bd0e90b63d6ad23aea994
2019-01-07 22:19:13 +11:00

171 lines
5.2 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
ChromeUtils.import("resource://gre/modules/GCTelemetry.jsm", this);
function do_register_cleanup() {
GCTelemetry.shutdown();
}
/*
* These tests are very basic, my goal was to add enough testing to support
* a change made in Bug 1424760. TODO Bug 1429635 for adding more extensive
* tests and deleting this comment.
*/
function run_test() {
// The limit on the number of fields in a GCMajor object.
const limit = 24;
// The number of fields that the make_gc() test function generates.
const make_gc_fields = 19;
// Test initialisation
Assert.ok(GCTelemetry.init(), "Initialize success");
Assert.ok(!GCTelemetry.init(), "Wont initialize twice");
// Test the basic success path.
// There are currently no entries
assert_num_entries(0, false);
// Add an entry
GCTelemetry.observeRaw(make_gc());
// Get it back.
assert_num_entries(1, false);
Assert.equal(make_gc_fields, Object.keys(get_entry()).length);
// "true" will cause the entry to be clared.
assert_num_entries(1, true);
// There are currently no entries.
assert_num_entries(0, false);
// Test too many fields
let my_big_gc = make_gc();
for (let i = 0; i < 100; i++) {
my_big_gc["new_property_" + i] = "Data";
}
GCTelemetry.observeRaw(my_big_gc);
// Assert that it was recorded but has only 7 fields.
Assert.equal(7, Object.keys(get_entry()).length);
assert_num_entries(1, true);
assert_num_entries(0, false);
let my_gc_exact = make_gc();
Assert.equal(make_gc_fields, Object.keys(my_gc_exact).length);
for (let i = 0; i < limit - make_gc_fields; i++) {
my_gc_exact["new_property_" + i] = "Data";
}
GCTelemetry.observeRaw(my_gc_exact);
// Assert that it was recorded has all the fields.
Assert.equal(limit, Object.keys(get_entry()).length);
assert_num_entries(1, true);
assert_num_entries(0, false);
// Exactly too many fields.
let my_gc_too_many = make_gc();
for (let i = 0; i < limit - make_gc_fields + 1; i++) {
my_gc_too_many["new_property_" + i] = "Data";
}
GCTelemetry.observeRaw(my_gc_too_many);
// Assert that it was recorded but has only 7 fields.
Assert.equal(7, Object.keys(get_entry()).length);
assert_num_entries(1, true);
assert_num_entries(0, false);
}
function assert_num_entries(expect, clear) {
let entries = GCTelemetry.entries("main", clear);
Assert.equal(expect, entries.worst.length, expect + " worst entries");
// Randomly sampled GCs are only recorded for content processes
Assert.equal(0, entries.random.length, expect + " random entries");
}
function get_entry() {
let entries = GCTelemetry.entries("main", false);
Assert.ok(entries, "Got entries object");
Assert.ok(entries.random, "Has random property");
Assert.ok(entries.worst, "Has worst property");
let entry = entries.worst[0];
Assert.ok(entry, "Got worst entry");
return entry;
}
/*
* These events are not exactly well-formed, but good enough. For example
* there's no guantee that all the pause times add up to total time, or
* that max_pause is correct.
*/
function make_gc() {
// Timestamps are in milliseconds since startup. All the times here
// are wall-clock times, which may not be monotonically increasing.
let timestamp = Math.random() * 1000000;
let gc = {
"status": "completed",
"timestamp": timestamp,
// All durations are in milliseconds.
"max_pause": Math.random() * 95 + 5,
"total_time": Math.random() * 500 + 500, // Sum of all slice times.
"zones_collected": 9,
"total_zones": 9,
"total_compartments": 309,
"minor_gcs": 44,
"store_buffer_overflows": 19,
"mmu_20ms": 0,
"mmu_50ms": 0,
"nonincremental_reason": "GCBytesTrigger",
"allocated_bytes": 38853696, // in bytes
"added_chunks": 54,
"removed_chunks": 12,
"slices": 15,
"slice_number": 218, // The first slice number for this GC event.
"slices_list": [
{
"slice": 218, // The global index of this slice.
"pause": Math.random() * 2 + 28,
"reason": "SET_NEW_DOCUMENT",
"initial_state": "NotActive",
"final_state": "Mark",
"budget": "10ms",
"page_faults": 1,
"start_timestamp": timestamp + Math.random() * 50000,
"times": {
"wait_background_thread": 0.012,
"mark_discard_code": 2.845,
"purge": 0.723,
"mark": 9.831,
"mark_roots": 0.102,
"buffer_gray_roots": 3.095,
"mark_cross_compartment_wrappers": 0.039,
"mark_c_and_js_stacks": 0.005,
"mark_runtime_wide_data": 2.313,
"mark_embedding": 0.117,
"mark_compartments": 2.27,
"unmark": 1.063,
"minor_gcs_to_evict_nursery": 8.701,
},
},
],
"totals": {
"wait_background_thread": 0.012,
"mark_discard_code": 2.845,
"purge": 0.723,
"mark": 9.831,
"mark_roots": 0.102,
"buffer_gray_roots": 3.095,
"mark_cross_compartment_wrappers": 0.039,
"mark_c_and_js_stacks": 0.005,
"mark_runtime_wide_data": 2.313,
"mark_embedding": 0.117,
"mark_compartments": 2.27,
"unmark": 1.063,
"minor_gcs_to_evict_nursery": 8.701,
},
};
return gc;
}