@vpalmisano/webrtcperf 4.4.1 → 4.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app.min.js +1 -1
- package/build/src/config.d.ts +1 -0
- package/build/src/config.js +11 -1
- package/build/src/config.js.map +1 -1
- package/build/src/docker.js +1 -1
- package/build/src/docker.js.map +1 -1
- package/build/src/session.d.ts +6 -1
- package/build/src/session.js +128 -79
- package/build/src/session.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +22 -22
- package/src/config.ts +11 -1
- package/src/docker.ts +1 -1
- package/src/session.ts +124 -72
package/build/src/session.js
CHANGED
|
@@ -99,6 +99,8 @@ class Session extends events_1.default {
|
|
|
99
99
|
id;
|
|
100
100
|
/** The throttle configuration index assigned to the session. */
|
|
101
101
|
throttleIndex;
|
|
102
|
+
/** If true, the network will be throttled using the browser internal throttling mechanism. */
|
|
103
|
+
useBrowserThrottling;
|
|
102
104
|
/** The test page url. */
|
|
103
105
|
url;
|
|
104
106
|
/** The url query. */
|
|
@@ -152,7 +154,7 @@ class Session extends events_1.default {
|
|
|
152
154
|
});
|
|
153
155
|
constructor({ chromiumUrl, chromiumPath, chromiumFieldTrials, windowWidth, windowHeight, deviceScaleFactor, display,
|
|
154
156
|
/* audioRedForOpus, */
|
|
155
|
-
url, urlQuery, customUrlHandler, customUrlHandlerFn, mediaPath, videoWidth, videoHeight, videoFramerate, useFakeMedia, enableGpu, enableBrowserLogging, startTimestamp, sessions, tabsPerSession, spawnPeriod, statsInterval, disabledVideoCodecs, localStorage, sessionStorage, clearCookies, scriptPath, showPageLog, pageLogFilter, pageLogPath, userAgent, id, throttleIndex, evaluateAfter, exposedFunctions, scriptParams, blockedUrls, extraHeaders, responseModifiers, downloadResponses, extraCSS, cookies, overridePermissions, hardwareConcurrency, debuggingPort, debuggingAddress, randomAudioPeriod, maxVideoDecoders, maxVideoDecodersRange, incognito, serverPort, serverSecret, serverUseHttps, emulateCpuThrottling, }) {
|
|
157
|
+
url, urlQuery, customUrlHandler, customUrlHandlerFn, mediaPath, videoWidth, videoHeight, videoFramerate, useFakeMedia, enableGpu, enableBrowserLogging, startTimestamp, sessions, tabsPerSession, spawnPeriod, statsInterval, disabledVideoCodecs, localStorage, sessionStorage, clearCookies, scriptPath, showPageLog, pageLogFilter, pageLogPath, userAgent, id, throttleIndex, useBrowserThrottling, evaluateAfter, exposedFunctions, scriptParams, blockedUrls, extraHeaders, responseModifiers, downloadResponses, extraCSS, cookies, overridePermissions, hardwareConcurrency, debuggingPort, debuggingAddress, randomAudioPeriod, maxVideoDecoders, maxVideoDecodersRange, incognito, serverPort, serverSecret, serverUseHttps, emulateCpuThrottling, }) {
|
|
156
158
|
super();
|
|
157
159
|
log.debug('constructor', { id });
|
|
158
160
|
this.id = id;
|
|
@@ -230,6 +232,7 @@ class Session extends events_1.default {
|
|
|
230
232
|
this.serverUseHttps = serverUseHttps;
|
|
231
233
|
this.emulateCpuThrottling = emulateCpuThrottling;
|
|
232
234
|
this.throttleIndex = throttleIndex;
|
|
235
|
+
this.useBrowserThrottling = useBrowserThrottling;
|
|
233
236
|
this.evaluateAfter = evaluateAfter || [];
|
|
234
237
|
this.exposedFunctions = exposedFunctions || {};
|
|
235
238
|
if (scriptParams) {
|
|
@@ -601,6 +604,8 @@ webrtcperf.config.AUDIO_URL = "http${this.serverUseHttps ? 's' : ''}://localhost
|
|
|
601
604
|
await this.context.overridePermissions(new URL(url).origin, this.overridePermissions);
|
|
602
605
|
}
|
|
603
606
|
const page = await this.getNewPage(tabIndex);
|
|
607
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
608
|
+
const pageCDPSession = page._client();
|
|
604
609
|
await page.setBypassCSP(true);
|
|
605
610
|
if (this.userAgent) {
|
|
606
611
|
await page.setUserAgent(this.userAgent);
|
|
@@ -632,8 +637,7 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
|
|
|
632
637
|
// Clear cookies.
|
|
633
638
|
if (this.clearCookies) {
|
|
634
639
|
try {
|
|
635
|
-
|
|
636
|
-
await client.send('Network.clearBrowserCookies');
|
|
640
|
+
await pageCDPSession.send('Network.clearBrowserCookies');
|
|
637
641
|
}
|
|
638
642
|
catch (err) {
|
|
639
643
|
log.error(`clearCookies error: ${err.stack}`);
|
|
@@ -671,8 +675,6 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
|
|
|
671
675
|
});
|
|
672
676
|
// Enable request interception.
|
|
673
677
|
let setRequestInterceptionState = true;
|
|
674
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
675
|
-
const pageCDPSession = page._client();
|
|
676
678
|
await pageCDPSession.send('Network.setBypassServiceWorker', {
|
|
677
679
|
bypass: true,
|
|
678
680
|
});
|
|
@@ -857,20 +859,25 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
|
|
|
857
859
|
await page.emulateCPUThrottling(this.emulateCpuThrottling);
|
|
858
860
|
}
|
|
859
861
|
// PeerConnectionExternal
|
|
860
|
-
await page.exposeFunction(
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
862
|
+
/* await page.exposeFunction(
|
|
863
|
+
'createPeerConnectionExternal',
|
|
864
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
865
|
+
async (options: any) => {
|
|
866
|
+
const pc = new PeerConnectionExternal(options)
|
|
867
|
+
return { id: pc.id }
|
|
868
|
+
},
|
|
869
|
+
)
|
|
870
|
+
|
|
871
|
+
await page.exposeFunction(
|
|
872
|
+
'callPeerConnectionExternalMethod',
|
|
873
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
874
|
+
async (id: number, name: PeerConnectionExternalMethod, arg: any) => {
|
|
875
|
+
const pc = PeerConnectionExternal.get(id)
|
|
870
876
|
if (pc) {
|
|
871
|
-
|
|
877
|
+
return pc[name](arg)
|
|
872
878
|
}
|
|
873
|
-
|
|
879
|
+
},
|
|
880
|
+
)*/
|
|
874
881
|
// Simulate keypress
|
|
875
882
|
await page.exposeFunction('keypressText', async (selector, text, delay = 20) => {
|
|
876
883
|
await page.type(selector, text, { delay });
|
|
@@ -1010,73 +1017,28 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
|
|
|
1010
1017
|
await page.evaluate(() => webrtcperf.stopFakeScreenshare());
|
|
1011
1018
|
}
|
|
1012
1019
|
});
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
sentBytes: 0,
|
|
1016
|
-
recvBytes: 0,
|
|
1017
|
-
recvLatency: new stats_1.FastStats({ store_data: false }),
|
|
1018
|
-
wsSentBytes: 0,
|
|
1019
|
-
wsRecvBytes: 0,
|
|
1020
|
-
wsRecvLatency: new stats_1.FastStats({ store_data: false }),
|
|
1021
|
-
};
|
|
1022
|
-
this.httpResourcesStats.set(index, resourcesStats);
|
|
1023
|
-
const pendingRequests = new Map();
|
|
1024
|
-
pageCDPSession.on('Network.requestWillBeSent', event => {
|
|
1025
|
-
if (event.request.url.startsWith('data:'))
|
|
1026
|
-
return;
|
|
1027
|
-
const { requestId, request, timestamp } = event;
|
|
1028
|
-
const sentBytes = request.postDataEntries?.reduce((acc, entry) => acc + (entry.bytes?.length || 0), 0);
|
|
1029
|
-
//log.log('Network.requestWillBeSent', event.type, request.url, sentBytes)
|
|
1030
|
-
if (sentBytes)
|
|
1031
|
-
resourcesStats.sentBytes += sentBytes;
|
|
1032
|
-
pendingRequests.set(requestId, { url: request.url, timestamp });
|
|
1033
|
-
});
|
|
1034
|
-
pageCDPSession.on('Network.responseReceived', event => {
|
|
1035
|
-
const request = pendingRequests.get(event.requestId);
|
|
1036
|
-
if (!request)
|
|
1037
|
-
return;
|
|
1038
|
-
const { response } = event;
|
|
1039
|
-
if (response.fromDiskCache) {
|
|
1040
|
-
pendingRequests.delete(event.requestId);
|
|
1041
|
-
return;
|
|
1042
|
-
}
|
|
1043
|
-
resourcesStats.recvBytes += response.encodedDataLength;
|
|
1044
|
-
});
|
|
1045
|
-
pageCDPSession.on('Network.dataReceived', event => {
|
|
1046
|
-
const request = pendingRequests.get(event.requestId);
|
|
1047
|
-
if (!request)
|
|
1048
|
-
return;
|
|
1049
|
-
resourcesStats.recvBytes += event.encodedDataLength;
|
|
1050
|
-
});
|
|
1051
|
-
pageCDPSession.on('Network.loadingFinished', event => {
|
|
1052
|
-
const request = pendingRequests.get(event.requestId);
|
|
1053
|
-
if (!request)
|
|
1054
|
-
return;
|
|
1055
|
-
pendingRequests.delete(event.requestId);
|
|
1056
|
-
const { timestamp } = event;
|
|
1057
|
-
resourcesStats.recvLatency.push(timestamp - request.timestamp);
|
|
1020
|
+
await page.exposeFunction('webrtcperf_reload', () => {
|
|
1021
|
+
return page.reload();
|
|
1058
1022
|
});
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
pageCDPSession.on('Network.webSocketHandshakeResponseReceived', event => {
|
|
1063
|
-
const request = pendingRequests.get(event.requestId);
|
|
1064
|
-
if (!request)
|
|
1065
|
-
return;
|
|
1066
|
-
pendingRequests.delete(event.requestId);
|
|
1067
|
-
resourcesStats.wsRecvLatency.push((Date.now() - request.timestamp) / 1000);
|
|
1068
|
-
});
|
|
1069
|
-
pageCDPSession.on('Network.webSocketFrameSent', event => {
|
|
1070
|
-
resourcesStats.wsSentBytes += event.response.payloadData.length;
|
|
1071
|
-
});
|
|
1072
|
-
pageCDPSession.on('Network.webSocketFrameReceived', event => {
|
|
1073
|
-
resourcesStats.wsRecvBytes += event.response.payloadData.length;
|
|
1074
|
-
});
|
|
1075
|
-
// hardware concurrency
|
|
1023
|
+
// HTTP stats.
|
|
1024
|
+
this.setupPageNetworkStats(pageCDPSession, index);
|
|
1025
|
+
// Hardware concurrency.
|
|
1076
1026
|
if (this.hardwareConcurrency) {
|
|
1077
1027
|
const plugin = NavigatorHardwareConcurrency({ hardwareConcurrency: this.hardwareConcurrency });
|
|
1078
1028
|
await plugin.onPageCreated(page);
|
|
1079
1029
|
}
|
|
1030
|
+
// Network throttling.
|
|
1031
|
+
if (this.throttleIndex > -1 && (process.platform !== 'linux' || this.useBrowserThrottling)) {
|
|
1032
|
+
log.debug(`Using internal network throttling`);
|
|
1033
|
+
await pageCDPSession.send('Network.emulateNetworkConditions', {
|
|
1034
|
+
offline: false,
|
|
1035
|
+
uploadThroughput: 100000000 / 8,
|
|
1036
|
+
downloadThroughput: 100000000 / 8,
|
|
1037
|
+
latency: 0,
|
|
1038
|
+
packetLoss: 0,
|
|
1039
|
+
packetQueueLength: 0,
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1080
1042
|
// Load page script.
|
|
1081
1043
|
{
|
|
1082
1044
|
const filePath = (0, utils_1.resolvePackagePath)('node_modules/@vpalmisano/webrtcperf-js/dist/webrtcperf.js');
|
|
@@ -1134,6 +1096,12 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
|
|
|
1134
1096
|
}
|
|
1135
1097
|
// add to pages map
|
|
1136
1098
|
this.pages.set(index, page);
|
|
1099
|
+
if (this.throttleIndex > -1 && (process.platform !== 'linux' || this.useBrowserThrottling)) {
|
|
1100
|
+
await this.applyNetworkThrottling(pageCDPSession);
|
|
1101
|
+
throttler_1.throttleNotifier.on('change', async () => {
|
|
1102
|
+
await this.applyNetworkThrottling(pageCDPSession);
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1137
1105
|
log.debug(`Page ${index + 1} "${url}" loaded in ${(Date.now() - pageLoadTime) / 1000}s`);
|
|
1138
1106
|
for (let i = 0; i < this.evaluateAfter.length; i++) {
|
|
1139
1107
|
await page.evaluate(
|
|
@@ -1141,6 +1109,87 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
|
|
|
1141
1109
|
this.evaluateAfter[i].pageFunction, ...this.evaluateAfter[i].args);
|
|
1142
1110
|
}
|
|
1143
1111
|
}
|
|
1112
|
+
setupPageNetworkStats(pageCDPSession, index) {
|
|
1113
|
+
const resourcesStats = {
|
|
1114
|
+
sentBytes: 0,
|
|
1115
|
+
recvBytes: 0,
|
|
1116
|
+
recvLatency: new stats_1.FastStats({ store_data: false }),
|
|
1117
|
+
wsSentBytes: 0,
|
|
1118
|
+
wsRecvBytes: 0,
|
|
1119
|
+
wsRecvLatency: new stats_1.FastStats({ store_data: false }),
|
|
1120
|
+
};
|
|
1121
|
+
this.httpResourcesStats.set(index, resourcesStats);
|
|
1122
|
+
const pendingRequests = new Map();
|
|
1123
|
+
pageCDPSession.on('Network.requestWillBeSent', event => {
|
|
1124
|
+
if (event.request.url.startsWith('data:'))
|
|
1125
|
+
return;
|
|
1126
|
+
const { requestId, request, timestamp } = event;
|
|
1127
|
+
const sentBytes = request.postDataEntries?.reduce((acc, entry) => acc + (entry.bytes?.length || 0), 0);
|
|
1128
|
+
//log.log('Network.requestWillBeSent', event.type, request.url, sentBytes)
|
|
1129
|
+
if (sentBytes)
|
|
1130
|
+
resourcesStats.sentBytes += sentBytes;
|
|
1131
|
+
pendingRequests.set(requestId, { url: request.url, timestamp });
|
|
1132
|
+
});
|
|
1133
|
+
pageCDPSession.on('Network.responseReceived', event => {
|
|
1134
|
+
const request = pendingRequests.get(event.requestId);
|
|
1135
|
+
if (!request)
|
|
1136
|
+
return;
|
|
1137
|
+
const { response } = event;
|
|
1138
|
+
if (response.fromDiskCache) {
|
|
1139
|
+
pendingRequests.delete(event.requestId);
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
resourcesStats.recvBytes += response.encodedDataLength;
|
|
1143
|
+
});
|
|
1144
|
+
pageCDPSession.on('Network.dataReceived', event => {
|
|
1145
|
+
const request = pendingRequests.get(event.requestId);
|
|
1146
|
+
if (!request)
|
|
1147
|
+
return;
|
|
1148
|
+
resourcesStats.recvBytes += event.encodedDataLength;
|
|
1149
|
+
});
|
|
1150
|
+
pageCDPSession.on('Network.loadingFinished', event => {
|
|
1151
|
+
const request = pendingRequests.get(event.requestId);
|
|
1152
|
+
if (!request)
|
|
1153
|
+
return;
|
|
1154
|
+
pendingRequests.delete(event.requestId);
|
|
1155
|
+
const { timestamp } = event;
|
|
1156
|
+
resourcesStats.recvLatency.push(timestamp - request.timestamp);
|
|
1157
|
+
});
|
|
1158
|
+
pageCDPSession.on('Network.webSocketCreated', event => {
|
|
1159
|
+
pendingRequests.set(event.requestId, { url: event.url, timestamp: Date.now() });
|
|
1160
|
+
});
|
|
1161
|
+
pageCDPSession.on('Network.webSocketHandshakeResponseReceived', event => {
|
|
1162
|
+
const request = pendingRequests.get(event.requestId);
|
|
1163
|
+
if (!request)
|
|
1164
|
+
return;
|
|
1165
|
+
pendingRequests.delete(event.requestId);
|
|
1166
|
+
resourcesStats.wsRecvLatency.push((Date.now() - request.timestamp) / 1000);
|
|
1167
|
+
});
|
|
1168
|
+
pageCDPSession.on('Network.webSocketFrameSent', event => {
|
|
1169
|
+
resourcesStats.wsSentBytes += event.response.payloadData.length;
|
|
1170
|
+
});
|
|
1171
|
+
pageCDPSession.on('Network.webSocketFrameReceived', event => {
|
|
1172
|
+
resourcesStats.wsRecvBytes += event.response.payloadData.length;
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
async applyNetworkThrottling(pageCDPSession) {
|
|
1176
|
+
const throttleUpValues = (0, throttler_1.getSessionThrottleValues)(this.throttleIndex, 'up');
|
|
1177
|
+
const throttleDownValues = (0, throttler_1.getSessionThrottleValues)(this.throttleIndex, 'down');
|
|
1178
|
+
const params = {
|
|
1179
|
+
offline: false,
|
|
1180
|
+
uploadThroughput: throttleUpValues.rate || -1,
|
|
1181
|
+
downloadThroughput: throttleDownValues.rate || -1,
|
|
1182
|
+
latency: Math.max(throttleUpValues.delay || 0, throttleDownValues.delay || 0),
|
|
1183
|
+
packetLoss: Math.max(throttleUpValues.loss || 0, throttleDownValues.loss || 0),
|
|
1184
|
+
packetQueueLength: Math.max(throttleUpValues.queue || 0, throttleDownValues.queue || 0),
|
|
1185
|
+
};
|
|
1186
|
+
log.debug(`Apply internal network throttling: ${JSON.stringify(params)}`);
|
|
1187
|
+
await pageCDPSession.send('Network.emulateNetworkConditions', {
|
|
1188
|
+
...params,
|
|
1189
|
+
uploadThroughput: params.uploadThroughput !== -1 ? params.uploadThroughput / 8 : -1,
|
|
1190
|
+
downloadThroughput: params.downloadThroughput !== -1 ? params.downloadThroughput / 8 : -1,
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1144
1193
|
async getNewPage(tabIndex) {
|
|
1145
1194
|
log.debug(`getNewPage ${tabIndex}`);
|
|
1146
1195
|
(0, assert_1.default)(this.context, 'NoBrowserContextCreated');
|