Skip to content
This repository was archived by the owner on Jun 24, 2025. It is now read-only.

Commit 1b49d6b

Browse files
committed
Initial commit
0 parents  commit 1b49d6b

File tree

29 files changed

+6059
-0
lines changed

29 files changed

+6059
-0
lines changed

.editorconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
10+
11+
[*.txt]
12+
indent_size = 0
13+
insert_final_newline = false

.eslintrc.cjs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module.exports = {
2+
'env': {
3+
'node': true,
4+
'es2021': true,
5+
},
6+
'extends': ['eslint:recommended', 'plugin:prettier/recommended'],
7+
'overrides': [],
8+
'parserOptions': {
9+
'ecmaVersion': 'latest',
10+
'sourceType': 'module',
11+
},
12+
'plugins': ['prettier'],
13+
'rules': {
14+
'prettier/prettier': 'error',
15+
},
16+
};

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
node_modules/
2+
.DS_Store/
3+
4+
# Ignore all files within a directory
5+
output/current/idle/**
6+
output/current/idleWithBrowser/**
7+
output/current/withGhostery/**
8+
output/current/withoutGhostery/**
9+
output/time/withGhostery/**
10+
output/time/withoutGhostery/**
11+
profiles/withGhostery/**
12+
profiles/withoutGhostery/**
13+
14+
# Do not ignore a special file name
15+
!.gitkeep

.prettierrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"semi": true,
3+
"useTabs": false,
4+
"singleQuote": true,
5+
"trailingComma": "all",
6+
"bracketSpacing": true,
7+
"arrowParens": "always",
8+
"quoteProps": "preserve"
9+
}

.tool-versions

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nodejs 20.2.0

README.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# Ghostery Benchmarks
2+
3+
## How to start?
4+
5+
Install dependencies
6+
7+
```
8+
npm ci
9+
```
10+
11+
To run main script which opens 360 websites one by one please follow commands below. Websites are picked based on https://github.com/whotracksme/whotracks.me
12+
13+
Start benchmarks
14+
15+
```
16+
npm start
17+
```
18+
19+
Usage:
20+
21+
```
22+
--US site list for US region
23+
--EU site list for European region
24+
--with-ghostery load Ghostery extension
25+
```
26+
27+
Example output:
28+
```
29+
LOG: Addon temp path:
30+
LOG: Downloading addon
31+
LOG: Unpacking addon
32+
LOG: Addon path:
33+
INFO: Open websites from for region: EU.
34+
LOG={"index":1,"url":"https://kingoloto.com/subscribe.html","loadTime":955,"loadedAt":"2023-05-19T02:20:32.748Z"}
35+
LOG={"index":2,"url":"https://bananalotto.fr/subscribe.html","loadTime":860,"loadedAt":"2023-05-19T02:20:35.739Z"}
36+
LOG={"index":359,"url":"https://krunker.io/","loadTime":2635,"loadedAt":"2023-05-19T02:48:12.686Z"}
37+
LOG={"index":360,"url":"https://www.virgilio.it/","loadTime":1433,"loadedAt":"2023-05-19T02:48:17.331Z"}
38+
39+
```
40+
41+
## Convert the current to power based on the measurements taken from the benchmark
42+
43+
To measure AC current, Gravity Analog AC Current Sensor was used. All the code to gather current value is available on https://wiki.dfrobot.com/Gravity_Analog_AC_Current_Sensor__SKU_SEN0211_
44+
45+
46+
Start calculate
47+
48+
```
49+
npm run -- currentToPower
50+
```
51+
52+
53+
Example input:
54+
```
55+
10:11:50.121 0.091
56+
10:11:50.121 0.112
57+
10:11:50.121 0.104
58+
10:11:50.125 0.104
59+
10:11:50.135 0.098
60+
10:11:50.152 0.097
61+
10:11:50.152 0.095
62+
```
63+
64+
65+
Example output:
66+
```
67+
[
68+
{
69+
dataSet: 1,
70+
fileName: 'idle/Idle_Set1_ 2023-05-17 22-00-33.txt',
71+
AVG: 9.829,
72+
AVG_CTP: 9.826,
73+
INTEGRAL: 9.829,
74+
INTEGRAL_CTP: 9.826,
75+
durationInMin: 59.98
76+
},
77+
{
78+
dataSet: 2,
79+
fileName: 'idle/Idle_Set2_ 2023-05-17 22-00-33.txt',
80+
AVG: 9.004,
81+
AVG_CTP: 9.004,
82+
INTEGRAL: 9.004,
83+
INTEGRAL_CTP: 9.004,
84+
durationInMin: 60.00
85+
},
86+
{
87+
dataSet: 28,
88+
fileName: 'withoutGhostery/Without_Set8_2023-05-18 20-17-08.txt',
89+
AVG: 22.353,
90+
AVG_CTP: 15.852,
91+
INTEGRAL: 22.353,
92+
INTEGRAL_CTP: 15.852,
93+
durationInMin: 42.55
94+
}
95+
]
96+
```
97+
98+
99+
100+
101+
## Based on the collected data from the benchmark, calculate the average time to load URLs
102+
103+
Start read time
104+
105+
```
106+
npm run -- readTime
107+
```
108+
109+
Usage:
110+
111+
```
112+
--US site list for US region
113+
--EU site list for European region
114+
```
115+
116+
Example output:
117+
```
118+
With Ghostery
119+
Average urls load time:
120+
{
121+
'https://kingoloto.com/subscribe.html': 1242.125,
122+
'https://bananalotto.fr/subscribe.html': 1619,
123+
'https://www.vogue.com/': 2542.125,
124+
'https://krunker.io/': 2627.625,
125+
'https://www.virgilio.it/': 1555.75,
126+
'https://velvet.hu/': null
127+
}
128+
Duration of urls load time for specific set of measurements:
129+
[
130+
'Set withGhostery/2023-05-19T02_20_04.734Z.txt: Load time duration: 27.74 min.',
131+
'Set withGhostery/2023-05-19T09_03_26.047Z.txt: Load time duration: 26.93 min.'
132+
]
133+
Urls which are broken or not loaded:
134+
[
135+
{ url: 'https://gooutdoors.co.uk/', loadTime: null },
136+
{ url: 'https://dyson.fr/', loadTime: null },
137+
{ url: 'https://velvet.hu/', loadTime: null }
138+
]
139+
140+
Without Ghostery
141+
Average urls load time:
142+
{
143+
'https://kingoloto.com/subscribe.html': 3554.889,
144+
'https://bananalotto.fr/subscribe.html': 2802.333,
145+
'https://satkurier.pl/': 5574.571,
146+
'https://www.wexphotovideo.com/': 3290.778,
147+
'https://velvet.hu/': null
148+
}
149+
Duration of urls load time for specific set of measurements:
150+
[
151+
'Set withoutGhostery/2023-05-18T18_17_18.025Z.txt: Load time duration: 40.98 min.',
152+
'Set withoutGhostery/2023-05-19T01_10_12.807Z.txt: Load time duration: 41.84 min.'
153+
]
154+
Urls which are broken or not loaded:
155+
[
156+
{ url: 'https://agar.io/', loadTime: -1684434429752 },
157+
{ url: 'https://velvet.hu/', loadTime: null }
158+
]
159+
```
160+
161+
## Resolve redirect
162+
163+
Many website will redirect when their TLD is entered to the browser. We use simple curl script to resolve most of the redirects:
164+
165+
```sh
166+
cat domains.txt | ./resolve-links.sh
167+
```

index.js

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import { Builder, Browser, By, until } from 'selenium-webdriver';
2+
import firefox from 'selenium-webdriver/firefox.js';
3+
import fs from 'fs';
4+
import { downloadAddon, sleep, switchToWindowWithUrl } from './helpers.js';
5+
6+
const timestamp = new Date().toISOString();
7+
const isGhosteryEnabled = Boolean(
8+
process.argv.find((arg) => arg === '--with-ghostery'),
9+
);
10+
const isRegionEU = Boolean(process.argv.find((arg) => arg === '--EU'));
11+
const isRegionUS = Boolean(process.argv.find((arg) => arg === '--US'));
12+
13+
let region = 'GLOBAL';
14+
let outputPath = 'output/time';
15+
let n = 1;
16+
17+
if (isRegionEU && isRegionUS) {
18+
throw new Error('Cannot use more than one region at the same time.');
19+
} else if (isRegionUS) {
20+
region = 'US';
21+
} else if (isRegionEU) {
22+
region = 'EU';
23+
}
24+
25+
const urls = fs
26+
.readFileSync(`input/${region}/urls.txt`, { encoding: 'utf8' })
27+
.split(/\r?\n/)
28+
.map((l) => `${l}`);
29+
30+
const addonUUID = 'd56a5b99-51b6-4e83-ab23-796216679614';
31+
32+
const options = new firefox.Options();
33+
options.setPreference(
34+
'extensions.webextensions.uuids',
35+
`{"[email protected]": "${addonUUID}"}`,
36+
);
37+
// options.addArguments("--headless");
38+
39+
if (isGhosteryEnabled) {
40+
options.addArguments('-profile', 'profiles/withGhostery');
41+
outputPath += '/withGhostery';
42+
} else {
43+
options.addArguments('-profile', 'profiles/withoutGhostery');
44+
outputPath += '/withoutGhostery';
45+
}
46+
47+
const outputStream = fs.createWriteStream(`${outputPath}/${timestamp}.txt`);
48+
49+
const driver = await new Builder()
50+
.forBrowser(Browser.FIREFOX)
51+
.setFirefoxOptions(options)
52+
.build();
53+
54+
driver.manage().setTimeouts({ pageLoad: 20000 });
55+
56+
console.log = function (msg) {
57+
outputStream.write(`${msg}\n`);
58+
};
59+
60+
const logPageLoadTime = async (n, url, now) => {
61+
const navigationStart = await driver.executeScript(
62+
'return window.performance.timing.navigationStart',
63+
);
64+
const domComplete = await driver.executeScript(
65+
'return window.performance.timing.domComplete',
66+
);
67+
const totalTime = domComplete - navigationStart;
68+
console.log(
69+
`LOG=${JSON.stringify({
70+
index: n,
71+
url,
72+
loadTime: totalTime,
73+
loadedAt: now,
74+
})}`,
75+
);
76+
};
77+
78+
try {
79+
if (isGhosteryEnabled) {
80+
const addon = await downloadAddon(
81+
'https://github.com/ghostery/ghostery-extension/releases/download/v8.9.15/ghostery-firefox-v8.9.15.zip',
82+
);
83+
84+
await driver.installAddon(addon, true);
85+
86+
if (!fs.existsSync('profiles/withGhostery/onboarded')) {
87+
await driver.wait(
88+
async () => (await driver.getAllWindowHandles()).length === 2,
89+
);
90+
console.log('INFO: Ghostery onboarding opened.');
91+
92+
await switchToWindowWithUrl(
93+
driver,
94+
`moz-extension://${addonUUID}/app/templates/onboarding.html`,
95+
);
96+
await (
97+
await driver.wait(until.elementLocated(By.css('ui-button button')))
98+
).click();
99+
await driver.wait(
100+
until.elementLocated(
101+
By.css('ui-onboarding-outro-success-view section'),
102+
),
103+
);
104+
console.log('INFO: Ghostery onboarding completed.');
105+
106+
await driver.get(
107+
`moz-extension://${addonUUID}/app/templates/autoconsent.html`,
108+
);
109+
await driver
110+
.wait(until.elementLocated(By.css('input[type=radio]:not(:checked)')))
111+
.click();
112+
await driver
113+
.wait(
114+
until.elementLocated(
115+
By.css('ui-autoconsent-views-home ui-button[type=primary]'),
116+
),
117+
)
118+
.click();
119+
await driver
120+
.wait(
121+
until.elementLocated(
122+
By.css('ui-autoconsent-views-confirm ui-button[type=primary]'),
123+
),
124+
)
125+
.click();
126+
console.log('INFO: Never-Consent enabled for all pages.');
127+
128+
fs.writeFileSync('profiles/withGhostery/onboarded', '');
129+
}
130+
}
131+
132+
console.log(`INFO: Open websites from for region: ${region}.`);
133+
134+
if (isGhosteryEnabled) {
135+
// Wait for Ghostery extension to download fresh Ad-blocking filters
136+
await sleep(1000 * 20);
137+
}
138+
139+
for (const url of urls) {
140+
const now = new Date().toISOString();
141+
try {
142+
await driver.get(url);
143+
logPageLoadTime(n, url, now);
144+
145+
await sleep(1000 * 2);
146+
} catch (error) {
147+
console.error(`LOG=${JSON.stringify({ index: n, url })}`);
148+
console.error(error);
149+
}
150+
151+
n++;
152+
}
153+
} finally {
154+
await driver.quit();
155+
outputStream.close();
156+
}

0 commit comments

Comments
 (0)