Skip to content

Commit 681e87b

Browse files
Performance monitoring (#396)
* Performance monitoring * Refactor class use and add basic sanity check * Rename measure on PerformanceMonitor to measureAll
1 parent d900958 commit 681e87b

File tree

5 files changed

+127
-1
lines changed

5 files changed

+127
-1
lines changed

integration-test/test-performance.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Tests for basic performance
3+
*/
4+
import { setup } from './helpers/harness.js'
5+
6+
describe('Runtime checks: should check basic performance', () => {
7+
let browser
8+
let server
9+
let teardown
10+
let setupServer
11+
let gotoAndWait
12+
beforeAll(async () => {
13+
({ browser, setupServer, teardown, gotoAndWait } = await setup({ withExtension: true }))
14+
server = setupServer()
15+
})
16+
afterAll(async () => {
17+
await server?.close()
18+
await teardown()
19+
})
20+
21+
it('Should perform within a resonable timeframe', async () => {
22+
const port = server.address().port
23+
const page = await browser.newPage()
24+
await gotoAndWait(page, `http://localhost:${port}/blank.html`, {
25+
debug: true,
26+
site: {
27+
enabledFeatures: ['runtimeChecks', 'fingerprintingCanvas']
28+
},
29+
featureSettings: {
30+
runtimeChecks: {
31+
taintCheck: 'enabled',
32+
matchAllDomains: 'enabled',
33+
matchAllStackDomains: 'disabled',
34+
overloadInstanceOf: 'enabled',
35+
stackDomains: [
36+
{
37+
domain: 'localhost'
38+
}
39+
]
40+
}
41+
}
42+
})
43+
const perfResult = await page.evaluate(
44+
() => {
45+
return {
46+
load: performance.getEntriesByName('load')[0].duration,
47+
init: performance.getEntriesByName('init')[0].duration,
48+
runtimeChecks: performance.getEntriesByName('runtimeChecksCallInit')[0].duration
49+
}
50+
})
51+
expect(perfResult.runtimeChecks).toBeLessThan(2)
52+
expect(perfResult.load).toBeLessThan(3)
53+
expect(perfResult.init).toBeLessThan(15)
54+
})
55+
})

src/content-feature.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { camelcase, matchHostname, processAttr } from './utils.js'
22
import { immutableJSONPatch } from 'immutable-json-patch'
3+
import { PerformanceMonitor } from './performance.js'
34

45
export default class ContentFeature {
56
constructor (featureName) {
67
this.name = featureName
78
this._args = null
9+
this.monitor = new PerformanceMonitor()
810
}
911

1012
/**
@@ -86,18 +88,29 @@ export default class ContentFeature {
8688
}
8789

8890
callInit (args) {
91+
const mark = this.monitor.mark(this.name + 'CallInit')
8992
this._args = args
9093
this.platform = args.platform
9194
this.init(args)
95+
mark.end()
96+
this.measure()
9297
}
9398

9499
load (args) {
95100
}
96101

97102
callLoad (args) {
103+
const mark = this.monitor.mark(this.name + 'CallLoad')
98104
this._args = args
99105
this.platform = args.platform
100106
this.load(args)
107+
mark.end()
108+
}
109+
110+
measure () {
111+
if (this._args.debug) {
112+
this.monitor.measureAll()
113+
}
101114
}
102115

103116
update () {

src/content-scope-features.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* global mozProxies */
22
import { initStringExemptionLists, isFeatureBroken, registerMessageSecret, getInjectionElement } from './utils'
33
import { featureNames } from './features'
4+
import { PerformanceMonitor } from './performance'
45
// @ts-expect-error Special glob import for injected features see scripts/utils/build.js
56
import injectedFeaturesCode from 'ddg:runtimeInjects'
67

@@ -20,6 +21,7 @@ let initArgs = null
2021
const updates = []
2122
const features = []
2223
const alwaysInitFeatures = new Set(['cookie'])
24+
const performanceMonitor = new PerformanceMonitor()
2325

2426
/**
2527
* @typedef {object} LoadArgs
@@ -34,6 +36,7 @@ const alwaysInitFeatures = new Set(['cookie'])
3436
* @param {LoadArgs} args
3537
*/
3638
export async function load (args) {
39+
const mark = performanceMonitor.mark('load')
3740
if (!shouldRun()) {
3841
return
3942
}
@@ -52,6 +55,7 @@ export async function load (args) {
5255
})
5356
features.push(feature)
5457
}
58+
mark.end()
5559
}
5660

5761
/**
@@ -105,6 +109,7 @@ function supportsInjectedFeatures () {
105109
}
106110

107111
export async function init (args) {
112+
const mark = performanceMonitor.mark('init')
108113
initArgs = args
109114
if (!shouldRun()) {
110115
return
@@ -125,6 +130,10 @@ export async function init (args) {
125130
const update = updates.pop()
126131
await updateFeaturesInner(update)
127132
}
133+
mark.end()
134+
if (args.debug) {
135+
performanceMonitor.measureAll()
136+
}
128137
}
129138

130139
export async function update (args) {

src/performance.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Performance monitor, holds reference to PerformanceMark instances.
3+
*/
4+
export class PerformanceMonitor {
5+
constructor () {
6+
this.marks = []
7+
}
8+
9+
/**
10+
* Create performance marker
11+
* @param {string} name
12+
* @returns {PerformanceMark}
13+
*/
14+
mark (name) {
15+
const mark = new PerformanceMark(name)
16+
this.marks.push(mark)
17+
return mark
18+
}
19+
20+
/**
21+
* Measure all performance markers
22+
*/
23+
measureAll () {
24+
this.marks.forEach((mark) => {
25+
mark.measure()
26+
})
27+
}
28+
}
29+
30+
/**
31+
* Tiny wrapper around performance.mark and performance.measure
32+
*/
33+
export class PerformanceMark {
34+
/**
35+
* @param {string} name
36+
*/
37+
constructor (name) {
38+
this.name = name
39+
performance.mark(this.name + 'Start')
40+
}
41+
42+
end () {
43+
performance.mark(this.name + 'End')
44+
}
45+
46+
measure () {
47+
performance.measure(this.name, this.name + 'Start', this.name + 'End')
48+
}
49+
}

unit-test/verify-artifacts.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { cwd } from '../scripts/script-utils.js'
66
const ROOT = join(cwd(import.meta.url), '..')
77
const BUILD = join(ROOT, 'build')
88
const APPLE_BUILD = join(ROOT, 'Sources/ContentScopeScripts/dist')
9-
const CSS_OUTPUT_SIZE = 530000
9+
const CSS_OUTPUT_SIZE = 550000
1010
const CSS_OUTPUT_SIZE_CHROME = CSS_OUTPUT_SIZE * 1.45 // 45% larger for Chrome MV2 due to base64 encoding
1111

1212
const checks = {

0 commit comments

Comments
 (0)