@microsoft/applicationinsights-core-js 2.7.2-nightly.2111-08 → 2.7.2-nightly.2111-09

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.
Files changed (69) hide show
  1. package/CONTRIBUTING.md +14 -0
  2. package/Tests/Perf/src/CorePerfCheck.Tests.ts +828 -0
  3. package/Tests/Perf/src/aiperftests.ts +6 -0
  4. package/Tests/Perf/tsconfig.json +17 -0
  5. package/Tests/PerfTests.html +54 -0
  6. package/Tests/Unit/src/AppInsightsCoreSize.Tests.ts +59 -0
  7. package/Tests/Unit/src/ApplicationInsightsCore.Tests.ts +1015 -0
  8. package/Tests/Unit/src/CookieManager.Tests.ts +477 -0
  9. package/Tests/Unit/src/HelperFunc.Tests.ts +59 -0
  10. package/Tests/Unit/src/aiunittests.ts +13 -0
  11. package/Tests/UnitTests.html +48 -0
  12. package/Tests/tsconfig.json +17 -0
  13. package/api-extractor.json +361 -0
  14. package/applicationinsights-core-js.build.error.log +205 -0
  15. package/applicationinsights-core-js.build.log +612 -0
  16. package/browser/applicationinsights-core-js.integrity.json +9 -9
  17. package/browser/applicationinsights-core-js.js +1 -1
  18. package/browser/applicationinsights-core-js.js.map +1 -1
  19. package/browser/applicationinsights-core-js.min.js +1 -1
  20. package/browser/applicationinsights-core-js.min.js.map +1 -1
  21. package/dist/applicationinsights-core-js.api.json +1 -1
  22. package/dist/applicationinsights-core-js.d.ts +1 -1
  23. package/dist/applicationinsights-core-js.js +1 -1
  24. package/dist/applicationinsights-core-js.js.map +1 -1
  25. package/dist/applicationinsights-core-js.min.js +1 -1
  26. package/dist/applicationinsights-core-js.min.js.map +1 -1
  27. package/dist/applicationinsights-core-js.rollup.d.ts +1 -1
  28. package/dist-esm/JavaScriptSDK/AppInsightsCore.js +1 -1
  29. package/dist-esm/JavaScriptSDK/BaseCore.js +1 -1
  30. package/dist-esm/JavaScriptSDK/BaseTelemetryPlugin.js +1 -1
  31. package/dist-esm/JavaScriptSDK/ChannelController.js +1 -1
  32. package/dist-esm/JavaScriptSDK/Constants.js +1 -1
  33. package/dist-esm/JavaScriptSDK/CookieMgr.js +1 -1
  34. package/dist-esm/JavaScriptSDK/CoreUtils.js +1 -1
  35. package/dist-esm/JavaScriptSDK/DiagnosticLogger.js +1 -1
  36. package/dist-esm/JavaScriptSDK/EnvUtils.js +1 -1
  37. package/dist-esm/JavaScriptSDK/HelperFuncs.js +1 -1
  38. package/dist-esm/JavaScriptSDK/InstrumentHooks.js +1 -1
  39. package/dist-esm/JavaScriptSDK/NotificationManager.js +1 -1
  40. package/dist-esm/JavaScriptSDK/PerfManager.js +1 -1
  41. package/dist-esm/JavaScriptSDK/ProcessTelemetryContext.js +1 -1
  42. package/dist-esm/JavaScriptSDK/RandomHelper.js +1 -1
  43. package/dist-esm/JavaScriptSDK/TelemetryHelpers.js +1 -1
  44. package/dist-esm/JavaScriptSDK/TelemetryPluginChain.js +1 -1
  45. package/dist-esm/JavaScriptSDK.Enums/EventsDiscardedReason.js +1 -1
  46. package/dist-esm/JavaScriptSDK.Enums/LoggingEnums.js +1 -1
  47. package/dist-esm/JavaScriptSDK.Enums/SendRequestReason.js +1 -1
  48. package/dist-esm/JavaScriptSDK.Interfaces/IAppInsightsCore.js +1 -1
  49. package/dist-esm/JavaScriptSDK.Interfaces/IChannelControls.js +1 -1
  50. package/dist-esm/JavaScriptSDK.Interfaces/IConfiguration.js +1 -1
  51. package/dist-esm/JavaScriptSDK.Interfaces/ICookieMgr.js +1 -1
  52. package/dist-esm/JavaScriptSDK.Interfaces/IDiagnosticLogger.js +1 -1
  53. package/dist-esm/JavaScriptSDK.Interfaces/IInstrumentHooks.js +1 -1
  54. package/dist-esm/JavaScriptSDK.Interfaces/INotificationListener.js +1 -1
  55. package/dist-esm/JavaScriptSDK.Interfaces/INotificationManager.js +1 -1
  56. package/dist-esm/JavaScriptSDK.Interfaces/IPerfEvent.js +1 -1
  57. package/dist-esm/JavaScriptSDK.Interfaces/IPerfManager.js +1 -1
  58. package/dist-esm/JavaScriptSDK.Interfaces/IProcessTelemetryContext.js +1 -1
  59. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryItem.js +1 -1
  60. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPlugin.js +1 -1
  61. package/dist-esm/JavaScriptSDK.Interfaces/ITelemetryPluginChain.js +1 -1
  62. package/dist-esm/applicationinsights-core-js.js +1 -1
  63. package/microsoft-applicationinsights-core-js-2.7.2-nightly.2111-09.tgz +0 -0
  64. package/package.json +1 -1
  65. package/rollup.config.js +138 -0
  66. package/src/applicationinsights-core-js.ts +59 -0
  67. package/temp/applicationinsights-core-js.api.md +934 -0
  68. package/tslint.json +5 -0
  69. package/types/tsdoc-metadata.json +1 -1
@@ -0,0 +1,828 @@
1
+ import { Assert, AITestClass } from "@microsoft/ai-test-framework";
2
+ import { ITestContext, StepResult } from "@microsoft/ai-test-framework/dist-esm/src/TestCase";
3
+ import { _InternalMessageId, LoggingSeverity } from "../../../src/JavaScriptSDK.Enums/LoggingEnums";
4
+ import { _InternalLogMessage, DiagnosticLogger } from "../../../src/JavaScriptSDK/DiagnosticLogger";
5
+ import { isObject, objForEachKey, objKeys, optimizeObject, setValue } from "../../../src/JavaScriptSDK/HelperFuncs";
6
+
7
+ interface PerfMeasurements {
8
+ duration: number;
9
+ iteration: number;
10
+ avgIteration: number;
11
+ avgDuration: number;
12
+ maxDuration: number;
13
+ total: number;
14
+ attempts: number;
15
+ deviation: number;
16
+ };
17
+
18
+ export class CorePerfCheckTests extends AITestClass {
19
+
20
+ public testInitialize() {
21
+ super.testInitialize();
22
+ }
23
+
24
+ public testCleanup() {
25
+ super.testCleanup();
26
+ }
27
+
28
+ public registerTests() {
29
+
30
+ this.testCase({
31
+ name: "PerfChecks: isObject",
32
+ test: () => {
33
+ let testObject = {
34
+ test: "Value"
35
+ };
36
+ let iterations = 500000;
37
+ let checks = 0;
38
+ let duration = this._runPerfTest("isObject", () => {
39
+ if (isObject(testObject)) {
40
+ checks++;
41
+ }
42
+ }, 10, iterations, 0.00001);
43
+
44
+ Assert.equal(iterations * duration.attempts, checks, "Make sure we hit all of them");
45
+ }
46
+ });
47
+
48
+ /**
49
+ * This test always currently fails on chromium based browsers due to the way that chromium provides super
50
+ * fast internal private classes for fixed objects and using the optimizeObject() creates a non-optimized
51
+ * dynamic class -- so commenting out for future validation and local runs on Firefox
52
+ */
53
+ // this.testCase({
54
+ // name: "PerfChecks: objForEachKey fixed large object",
55
+ // test: () => {
56
+ // let iterations = 100000;
57
+ // let baseTestObject = {
58
+ // "test.value0": "Test Value 0",
59
+ // "test.value1": "Test Value 1",
60
+ // "test.value2": "Test Value 2",
61
+ // "test.value3": "Test Value 3",
62
+ // "test.value4": "Test Value 4",
63
+ // "test.value5": "Test Value 5",
64
+ // "test.value6": "Test Value 6",
65
+ // "test.value7": "Test Value 7",
66
+ // "test.value8": "Test Value 8",
67
+ // "test.value9": "Test Value 9",
68
+ // "test.value10": "Test Value 10",
69
+ // "test.value11": "Test Value 11",
70
+ // "test.value12": "Test Value 12",
71
+ // "test.value13": "Test Value 13",
72
+ // "test.value14": "Test Value 14",
73
+ // "test.value15": "Test Value 15",
74
+ // "test.value16": "Test Value 16",
75
+ // "test.value17": "Test Value 17",
76
+ // "test.value18": "Test Value 18",
77
+ // "test.value19": "Test Value 19",
78
+ // "test.value20": "Test Value 20",
79
+ // "test.value21": "Test Value 21",
80
+ // "test.value22": "Test Value 22",
81
+ // "test.value23": "Test Value 23",
82
+ // "test.value24": "Test Value 24",
83
+ // "test.value25": "Test Value 25",
84
+ // "test.value26": "Test Value 26",
85
+ // "test.value27": "Test Value 27",
86
+ // "test.value28": "Test Value 28",
87
+ // "test.value29": "Test Value 29",
88
+ // "test.value30": "Test Value 30",
89
+ // "test.value31": "Test Value 31",
90
+ // "test.value32": "Test Value 32",
91
+ // "test.value33": "Test Value 33",
92
+ // "test.value34": "Test Value 34",
93
+ // "test.value35": "Test Value 35",
94
+ // "test.value36": "Test Value 36",
95
+ // "test.value37": "Test Value 37",
96
+ // "test.value38": "Test Value 38",
97
+ // "test.value39": "Test Value 39"
98
+ // } as any;
99
+ // let objectFields = Object["keys"](baseTestObject).length;
100
+
101
+ // // JIT Optimization if we know we are playing with a dynamic object
102
+ // let optTestObject = optimizeObject(baseTestObject);
103
+
104
+ // let testObject6 = Object["assign"]({}, baseTestObject);
105
+ // testObject6["_dummy"] = 0;
106
+ // testObject6 = Object["assign"]({}, testObject6);
107
+ // delete testObject6["_dummy"];
108
+ // let adjOptTestObject = optimizeObject(testObject6);
109
+
110
+ // let checks = 0;
111
+ // let baseDuration = this._runPerfTest("baseTestObject", () => {
112
+ // objForEachKey(baseTestObject, (name, value) => {
113
+ // checks++;
114
+ // });
115
+ // }, 200, iterations, 0.003, 20);
116
+
117
+ // Assert.equal(iterations * objectFields * baseDuration.attempts, checks, "Make sure we hit all of them");
118
+
119
+ // checks = 0;
120
+ // let optDuration1 = this._runPerfTest("optTestObject", () => {
121
+ // objForEachKey(optTestObject, (name, value) => {
122
+ // checks++;
123
+ // });
124
+ // }, 300, iterations, 0.003, 20);
125
+
126
+ // Assert.equal(iterations * objectFields * optDuration1.attempts, checks, "Make sure we hit all of them");
127
+ // this._checkRun(baseDuration, optDuration1);
128
+
129
+ // checks = 0;
130
+ // let optDuration2 = this._runPerfTest("adjOptTestObject", () => {
131
+ // objForEachKey(adjOptTestObject, (name, value) => {
132
+ // checks++;
133
+ // });
134
+ // }, 300, iterations, 0.003, 20);
135
+
136
+ // Assert.equal(iterations * objectFields * optDuration2.attempts, checks, "Make sure we hit all of them");
137
+
138
+ // this._checkRun(baseDuration, optDuration2);
139
+ // }
140
+ // });
141
+
142
+ this.testCase({
143
+ name: "PerfChecks: objForEachKey dynamic large (40 fields) object",
144
+ timeout: 60000,
145
+ test: () => {
146
+ let iterations = 100000;
147
+ let baseTestObject = { };
148
+ for (let lp = 0; lp < 40; lp++) {
149
+ baseTestObject["test.value" + lp] = "Test Value " + lp;
150
+ }
151
+ let objectFields = Object["keys"](baseTestObject).length;
152
+
153
+ // JIT Optimization if we know we are playing with a dynamic object
154
+ let optTestObject = optimizeObject(baseTestObject);
155
+
156
+ let checks = 0;
157
+ return this._runPerfTestAsync("baseTestObject", () => {
158
+ objForEachKey(baseTestObject, (name, value) => {
159
+ checks++;
160
+ });
161
+ }, 400, iterations, 0.003).then((baseDuration) => {
162
+ Assert.equal(iterations * objectFields * baseDuration.attempts, checks, "Make sure we hit all of them");
163
+
164
+ checks = 0;
165
+ return this._runPerfTestAsync("optTestObject", () => {
166
+ objForEachKey(optTestObject, (name, value) => {
167
+ checks++;
168
+ });
169
+ }, 400, iterations, 0.003, baseDuration).then((optDuration1) => {
170
+ Assert.equal(iterations * objectFields * optDuration1.attempts, checks, "Make sure we hit all of them");
171
+ this._checkRun(baseDuration, optDuration1);
172
+ }).catch((reason) => {
173
+ Assert.ok(false, "Promise rejected - " + reason);
174
+ });
175
+ }).catch((reason) => {
176
+ Assert.ok(false, "Promise rejected - " + reason);
177
+ });
178
+ }
179
+ });
180
+
181
+ this.testCase({
182
+ name: "PerfChecks: objForEachKey complete small (<20 fields) dynamic object",
183
+ timeout: 60000,
184
+ test: () => {
185
+ let iterations = 100000;
186
+ let baseTestObject = { } as any;
187
+ let objectFields = 19; // There is a JIT optimization for objects with <= 19 fields
188
+ for (let lp = 0; lp < objectFields; lp++) {
189
+ setValue(baseTestObject, "test.value." + lp, "Test Value " + lp);
190
+ }
191
+
192
+ // JIT Optimization if we know we are playing with a dynamic object
193
+ let optTestObject = optimizeObject(baseTestObject);
194
+
195
+ let checks = 0;
196
+ return this._runPerfTestAsync("baseTestObject", () => {
197
+ objForEachKey(baseTestObject, (name, value) => {
198
+ checks++;
199
+ });
200
+ }, 400, iterations, 0.0015).then((baseDuration) => {
201
+ Assert.equal(iterations * objectFields * baseDuration.attempts, checks, "Make sure we hit all of them");
202
+
203
+ checks = 0;
204
+ return this._runPerfTestAsync("optTestObject", () => {
205
+ objForEachKey(optTestObject, (name, value) => {
206
+ checks++;
207
+ });
208
+ }, 400, iterations, 0.001, baseDuration).then((optDuration) => {
209
+ Assert.equal(iterations * objectFields * optDuration.attempts, checks, "Make sure we hit all of them");
210
+
211
+ this._checkRun(baseDuration, optDuration);
212
+ }).catch((reason) => {
213
+ Assert.ok(false, "Promise rejected - " + reason);
214
+ });
215
+ }).catch((reason) => {
216
+ Assert.ok(false, "Promise rejected - " + reason);
217
+ });
218
+ }
219
+ });
220
+
221
+ this.testCase({
222
+ name: "PerfChecks: objForEachKey complete large (>= 20 fields) dynamic object",
223
+ timeout: 60000,
224
+ test: () => {
225
+ let iterations = 100000;
226
+ let baseTestObject = { } as any;
227
+ let objectFields = 21; // There is a JIT optimization for objects with <= 19 fields
228
+ for (let lp = 0; lp < objectFields; lp++) {
229
+ setValue(baseTestObject, "test.value." + lp, "Test Value " + lp);
230
+ }
231
+
232
+ // JIT Optimization if we know we are playing with a dynamic object
233
+ let optTestObject = optimizeObject(baseTestObject);
234
+
235
+ let checks = 0;
236
+ return this._runPerfTestAsync("baseTestObject", () => {
237
+ objForEachKey(baseTestObject, (name, value) => {
238
+ checks++;
239
+ });
240
+ }, 400, iterations, 0.002).then((baseDuration) => {
241
+ Assert.equal(iterations * objectFields * baseDuration.attempts, checks, "Make sure we hit all of them");
242
+
243
+ checks = 0;
244
+ return this._runPerfTestAsync("optTestObject", () => {
245
+ objForEachKey(optTestObject, (name, value) => {
246
+ checks++;
247
+ });
248
+ }, 400, iterations, 0.002, baseDuration).then((optDuration) => {
249
+ Assert.equal(iterations * objectFields * optDuration.attempts, checks, "Make sure we hit all of them");
250
+
251
+ this._checkRun(baseDuration, optDuration);
252
+ }).catch((reason) => {
253
+ Assert.ok(false, "Promise rejected - " + reason);
254
+ });
255
+ }).catch((reason) => {
256
+ Assert.ok(false, "Promise rejected - " + reason);
257
+ });
258
+ }
259
+ });
260
+
261
+ this.testCase({
262
+ name: "PerfChecks: objForEachKey with small (<20 fields) extended dynamic object",
263
+ timeout: 60000,
264
+ test: () => {
265
+ let iterations = 100000;
266
+ let baseTestObject = {
267
+ a: 1
268
+ } as any;
269
+ let objectFields = 18;
270
+ for (let lp = 0; lp < objectFields - 1; lp++) {
271
+ setValue(baseTestObject, "test.value." + lp, "Test Value " + lp);
272
+ }
273
+
274
+ // JIT Optimization if we know we are playing with a dynamic object
275
+ let optTestObject = optimizeObject(baseTestObject);
276
+
277
+ let checks = 0;
278
+ return this._runPerfTestAsync("baseTestObject", () => {
279
+ objForEachKey(baseTestObject, (name, value) => {
280
+ checks++;
281
+ });
282
+ }, 400, iterations, 0.0015).then((baseDuration) => {
283
+ Assert.equal(iterations * objectFields * baseDuration.attempts, checks, "Make sure we hit all of them");
284
+
285
+ checks = 0;
286
+ return this._runPerfTestAsync("optTestObject", () => {
287
+ objForEachKey(optTestObject, (name, value) => {
288
+ checks++;
289
+ });
290
+ }, 400, iterations, 0.001, baseDuration).then((optDuration) => {
291
+ Assert.equal(iterations * objectFields * optDuration.attempts, checks, "Make sure we hit all of them");
292
+
293
+ this._checkRun(baseDuration, optDuration);
294
+ }).catch((reason) => {
295
+ Assert.ok(false, "Promise rejected - " + reason);
296
+ });
297
+ }).catch((reason) => {
298
+ Assert.ok(false, "Promise rejected - " + reason);
299
+ });
300
+ }
301
+ });
302
+
303
+ this.testCase({
304
+ name: "PerfChecks: objForEachKey with large (>=20 fields) extended dynamic object",
305
+ timeout: 60000,
306
+ test: () => {
307
+ let iterations = 100000;
308
+ let baseTestObject = {
309
+ a: 1
310
+ } as any;
311
+ let objectFields = 20;
312
+ for (let lp = 0; lp < objectFields - 1; lp++) {
313
+ setValue(baseTestObject, "test.value." + lp, "Test Value " + lp);
314
+ }
315
+
316
+ // JIT Optimization if we know we are playing with a dynamic object
317
+ let optTestObject = optimizeObject(baseTestObject);
318
+
319
+ let checks = 0;
320
+ return this._runPerfTestAsync("baseTestObject", () => {
321
+ objForEachKey(baseTestObject, (name, value) => {
322
+ checks++;
323
+ });
324
+ }, 400, iterations, 0.0015).then((baseDuration) => {
325
+ Assert.equal(iterations * objectFields * baseDuration.attempts, checks, "Make sure we hit all of them");
326
+
327
+ checks = 0;
328
+ return this._runPerfTestAsync("optTestObject", () => {
329
+ objForEachKey(optTestObject, (name, value) => {
330
+ checks++;
331
+ });
332
+ }, 400, iterations, 0.0015, baseDuration).then((optDuration) => {
333
+ Assert.equal(iterations * objectFields * optDuration.attempts, checks, "Make sure we hit all of them");
334
+
335
+ this._checkRun(baseDuration, optDuration);
336
+ }).catch((reason) => {
337
+ Assert.ok(false, "Promise rejected - " + reason);
338
+ });
339
+ }).catch((reason) => {
340
+ Assert.ok(false, "Promise rejected - " + reason);
341
+ });
342
+ }
343
+ });
344
+
345
+ /**
346
+ * This test always currently fails on chromium based browsers due to the way that chromium provides super
347
+ * fast internal private classes for fixed objects and using the optimizeObject() creates a non-optimized
348
+ * dynamic class -- so commenting out for future validation and local runs on Firefox
349
+ */
350
+ // this.testCase({
351
+ // name: "PerfChecks: json.stringify fixed large (40 fields) object",
352
+ // test: () => {
353
+ // let iterations = 100000;
354
+ // let baseTestObject = {
355
+ // "test.value0": "Test Value 0",
356
+ // "test.value1": "Test Value 1",
357
+ // "test.value2": "Test Value 2",
358
+ // "test.value3": "Test Value 3",
359
+ // "test.value4": "Test Value 4",
360
+ // "test.value5": "Test Value 5",
361
+ // "test.value6": "Test Value 6",
362
+ // "test.value7": "Test Value 7",
363
+ // "test.value8": "Test Value 8",
364
+ // "test.value9": "Test Value 9",
365
+ // "test.value10": "Test Value 10",
366
+ // "test.value11": "Test Value 11",
367
+ // "test.value12": "Test Value 12",
368
+ // "test.value13": "Test Value 13",
369
+ // "test.value14": "Test Value 14",
370
+ // "test.value15": "Test Value 15",
371
+ // "test.value16": "Test Value 16",
372
+ // "test.value17": "Test Value 17",
373
+ // "test.value18": "Test Value 18",
374
+ // "test.value19": "Test Value 19",
375
+ // "test.value20": "Test Value 20",
376
+ // "test.value21": "Test Value 21",
377
+ // "test.value22": "Test Value 22",
378
+ // "test.value23": "Test Value 23",
379
+ // "test.value24": "Test Value 24",
380
+ // "test.value25": "Test Value 25",
381
+ // "test.value26": "Test Value 26",
382
+ // "test.value27": "Test Value 27",
383
+ // "test.value28": "Test Value 28",
384
+ // "test.value29": "Test Value 29",
385
+ // "test.value30": "Test Value 30",
386
+ // "test.value31": "Test Value 31",
387
+ // "test.value32": "Test Value 32",
388
+ // "test.value33": "Test Value 33",
389
+ // "test.value34": "Test Value 34",
390
+ // "test.value35": "Test Value 35",
391
+ // "test.value36": "Test Value 36",
392
+ // "test.value37": "Test Value 37",
393
+ // "test.value38": "Test Value 38",
394
+ // "test.value39": "Test Value 39"
395
+ // } as any;
396
+
397
+ // let optTestObject = optimizeObject(baseTestObject);
398
+ // Assert.equal(JSON.stringify(baseTestObject), JSON.stringify(optTestObject), "Make sure the new assigned object is the same");
399
+
400
+ // let checks = 0;
401
+ // let baseDuration = this._runPerfTest("baseTestObject", () => {
402
+ // JSON.stringify(baseTestObject);
403
+ // }, 550, iterations, 0.005);
404
+
405
+ // checks = 0;
406
+ // let optDuration = this._runPerfTest("optTestObject", () => {
407
+ // JSON.stringify(optTestObject);
408
+ // }, 550, iterations, 0.005);
409
+
410
+ // this._checkRun(baseDuration, optDuration);
411
+ // }
412
+ // });
413
+
414
+ this.testCase({
415
+ name: "PerfChecks: json.stringify dynamic large (40 fields) object",
416
+ timeout: 120000,
417
+ test: () => {
418
+ let iterations = 10000;
419
+ let baseTestObject = { };
420
+ for (let lp = 0; lp < 40; lp++) {
421
+ baseTestObject["test.value" + lp] = "Test Value " + lp;
422
+ }
423
+
424
+ let optTestObject = optimizeObject(baseTestObject);
425
+ Assert.equal(JSON.stringify(baseTestObject), JSON.stringify(optTestObject), "Make sure the new assigned object is the same");
426
+
427
+ let checks = 0;
428
+ return this._runPerfTestAsync("baseTestObject", () => {
429
+ JSON.stringify(baseTestObject);
430
+ }, 150, iterations, 0.015).then((baseDuration) => {
431
+ checks = 0;
432
+ return this._runPerfTestAsync("optTestObject", () => {
433
+ JSON.stringify(optTestObject);
434
+ }, 150, iterations, 0.015, baseDuration).then((optDuration) => {
435
+ this._checkRun(baseDuration, optDuration);
436
+ }).catch((reason) => {
437
+ Assert.ok(false, "Promise rejected - " + reason);
438
+ });
439
+ }).catch((reason) => {
440
+ Assert.ok(false, "Promise rejected - " + reason);
441
+ });
442
+ }
443
+ });
444
+
445
+ this.testCase({
446
+ name: "PerfChecks: json.stringify complete small (<20 fields) dynamic object",
447
+ timeout: 120000,
448
+ test: () => {
449
+ let iterations = 10000;
450
+ let baseTestObject = { } as any;
451
+ let objectFields = 19; // There is a JIT optimization for objects with <= 19 fields
452
+ for (let lp = 0; lp < objectFields; lp++) {
453
+ setValue(baseTestObject, "test.value." + lp, "Test Value " + lp);
454
+ }
455
+
456
+ let optTestObject = optimizeObject(baseTestObject);
457
+ Assert.equal(JSON.stringify(baseTestObject), JSON.stringify(optTestObject), "Make sure the new assigned object is the same");
458
+
459
+ let checks = 0;
460
+ return this._runPerfTestAsync("baseTestObject", () => {
461
+ JSON.stringify(baseTestObject);
462
+ }, 50, iterations, 0.005).then((baseDuration) => {
463
+ checks = 0;
464
+ return this._runPerfTestAsync("optTestObject", () => {
465
+ JSON.stringify(optTestObject);
466
+ }, 50, iterations, 0.005, baseDuration).then((optDuration) => {
467
+ this._checkRun(baseDuration, optDuration);
468
+ }).catch((reason) => {
469
+ Assert.ok(false, "Promise rejected - " + reason);
470
+ });
471
+ }).catch((reason) => {
472
+ Assert.ok(false, "Promise rejected - " + reason);
473
+ });
474
+ }
475
+ });
476
+
477
+ this.testCase({
478
+ name: "PerfChecks: json.stringify with small (<20 fields) extended dynamic object",
479
+ timeout: 120000,
480
+ test: () => {
481
+ let iterations = 10000;
482
+ let baseTestObject = {
483
+ a: 1
484
+ } as any;
485
+ let objectFields = 19;
486
+ for (let lp = 0; lp < objectFields - 1; lp++) {
487
+ setValue(baseTestObject, "test.value." + lp, "Test Value " + lp);
488
+ }
489
+
490
+ // Jit Optimization!!!
491
+ let optTestObject = optimizeObject(baseTestObject);
492
+
493
+ Assert.equal(JSON.stringify(baseTestObject), JSON.stringify(optTestObject), "Make sure the new assigned object is the same");
494
+
495
+ return this._runPerfTestAsync("baseTestObject", () => {
496
+ JSON.stringify(baseTestObject);
497
+ }, 50, iterations, 0.005).then((baseDuration) => {
498
+ return this._runPerfTestAsync("optTestObject", () => {
499
+ JSON.stringify(optTestObject);
500
+ }, 50, iterations, 0.003, baseDuration).then((optDuration) => {
501
+ this._checkRun(baseDuration, optDuration);
502
+ }).catch((reason) => {
503
+ Assert.ok(false, "Promise rejected - " + reason);
504
+ });
505
+ }).catch((reason) => {
506
+ Assert.ok(false, "Promise rejected - " + reason);
507
+ });
508
+ }
509
+ });
510
+
511
+ this.testCase({
512
+ name: "PerfChecks: json.stringify with large (>= 20 fields) extended dynamic object",
513
+ timeout: 60000,
514
+ test: () => {
515
+ let iterations = 10000;
516
+ let baseTestObject = {
517
+ a: 1
518
+ } as any;
519
+ let objectFields = 20;
520
+ for (let lp = 0; lp < objectFields - 1; lp++) {
521
+ setValue(baseTestObject, "test.value." + lp, "Test Value " + lp);
522
+ }
523
+
524
+ let optTestObject = optimizeObject(baseTestObject);
525
+ Assert.equal(JSON.stringify(baseTestObject), JSON.stringify(optTestObject), "Make sure the new assigned object is the same");
526
+
527
+ return this._runPerfTestAsync("baseTestObject", () => {
528
+ JSON.stringify(baseTestObject);
529
+ }, 100, iterations, 0.01).then((baseDuration) => {
530
+ return this._runPerfTestAsync("optTestObject", () => {
531
+ JSON.stringify(optTestObject);
532
+ }, 100, iterations, 0.01, baseDuration).then((optDuration) => {
533
+ this._checkRun(baseDuration, optDuration);
534
+ }).catch((reason) => {
535
+ Assert.ok(false, "Promise rejected - " + reason);
536
+ });
537
+ }).catch((reason) => {
538
+ Assert.ok(false, "Promise rejected - " + reason);
539
+ });
540
+ }
541
+ });
542
+
543
+ this.testCase({
544
+ name: "PerfChecks: objKeys with small (<20 fields) dynamic object",
545
+ timeout: 60000,
546
+ test: () => {
547
+ let iterations = 100000;
548
+ let objectFields = 19;
549
+ let baseTestObject = { };
550
+ for (let lp = 0; lp < objectFields; lp++) {
551
+ baseTestObject["value" + lp] = "Test Value " + lp;
552
+ }
553
+
554
+ let optTestObject = optimizeObject(baseTestObject);
555
+
556
+ let checks = 0;
557
+ return this._runPerfTestAsync("baseTestObject", () => {
558
+ checks += objKeys(baseTestObject).length;
559
+ }, 300, iterations, 0.0015).then((baseDuration) => {
560
+ Assert.equal(iterations * objectFields * baseDuration.attempts, checks, "Make sure we hit all of them");
561
+
562
+ checks = 0;
563
+ return this._runPerfTestAsync("optTestObject", () => {
564
+ checks += objKeys(optTestObject).length;
565
+ }, 300, iterations, 0.001, baseDuration).then((optDuration) => {
566
+ Assert.equal(iterations * objectFields * optDuration.attempts, checks, "Make sure we hit all of them");
567
+
568
+ this._checkRun(baseDuration, optDuration);
569
+ }).catch((reason) => {
570
+ Assert.ok(false, "Promise rejected - " + reason);
571
+ });
572
+ }).catch((reason) => {
573
+ Assert.ok(false, "Promise rejected - " + reason);
574
+ });
575
+ }
576
+ });
577
+
578
+ this.testCase({
579
+ name: "PerfChecks: objKeys extended object with small (<20 fields)",
580
+ timeout: 60000,
581
+ test: () => {
582
+ let iterations = 100000;
583
+ let objectFields = 19;
584
+ let baseTestObject = {
585
+ a: 1
586
+ };
587
+ for (let lp = 0; lp < objectFields - 1; lp++) {
588
+ baseTestObject["value" + lp] = "Test Value " + lp;
589
+ }
590
+
591
+ let optTestObject = optimizeObject(baseTestObject);
592
+
593
+ let checks = 0;
594
+ return this._runPerfTestAsync("baseTestObject", () => {
595
+ checks += objKeys(baseTestObject).length;
596
+ }, 150, iterations, 0.0015).then((baseDuration) => {
597
+ Assert.equal(iterations * objectFields * baseDuration.attempts, checks, "Make sure we hit all of them");
598
+
599
+ checks = 0;
600
+ return this._runPerfTestAsync("optTestObject", () => {
601
+ checks += objKeys(optTestObject).length;
602
+ }, 150, iterations, 0.0015, baseDuration).then((optDuration) => {
603
+ Assert.equal(iterations * objectFields * optDuration.attempts, checks, "Make sure we hit all of them");
604
+
605
+ this._checkRun(baseDuration, optDuration);
606
+ }).catch((reason) => {
607
+ Assert.ok(false, "Promise rejected - " + reason);
608
+ });
609
+ }).catch((reason) => {
610
+ Assert.ok(false, "Promise rejected - " + reason);
611
+ });
612
+ }
613
+ });
614
+
615
+ this.testCase({
616
+ name: "PerfChecks: objKeys dynamic object with large (>=20 fields)",
617
+ timeout: 60000,
618
+ test: () => {
619
+ let iterations = 100000;
620
+ let objectFields = 21;
621
+ let baseTestObject = { };
622
+ for (let lp = 0; lp < objectFields; lp++) {
623
+ baseTestObject["value" + lp] = "Test Value " + lp;
624
+ }
625
+
626
+ let checks = 0;
627
+ return this._runPerfTestAsync("baseTestObject", () => {
628
+ checks += objKeys(baseTestObject).length;
629
+ }, 200, iterations, 0.0015).then((baseDuration) => {
630
+ Assert.equal(iterations * objectFields * baseDuration.attempts, checks, "Make sure we hit all of them");
631
+
632
+ let optTestObject = optimizeObject(baseTestObject);
633
+ checks = 0;
634
+ return this._runPerfTestAsync("optTestObject", () => {
635
+ checks += objKeys(optTestObject).length;
636
+ }, 200, iterations, 0.0015, baseDuration).then((optDuration) => {
637
+ Assert.equal(iterations * objectFields * optDuration.attempts, checks, "Make sure we hit all of them");
638
+
639
+ this._checkRun(baseDuration, optDuration);
640
+ }).catch((reason) => {
641
+ Assert.ok(false, "Promise rejected - " + reason);
642
+ });
643
+ }).catch((reason) => {
644
+ Assert.ok(false, "Promise rejected - " + reason);
645
+ });
646
+ }
647
+ });
648
+ }
649
+
650
+ private _getStandardDeviation(values: number[]) {
651
+ const n = values.length
652
+ const mean = values.reduce((a, b) => a + b) / n
653
+ return Math.sqrt(values.map(x => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n)
654
+ }
655
+
656
+ private _checkRun(baseDuration: PerfMeasurements, chkDuration: PerfMeasurements) {
657
+ if (chkDuration.duration <= baseDuration.duration) {
658
+ // If the new min is smaller then it's a pass
659
+ Assert.ok(true, `New minimum ${chkDuration.duration} is <= the base ${baseDuration.duration}`);
660
+ return;
661
+ }
662
+
663
+ if (chkDuration.avgDuration <= baseDuration.avgDuration) {
664
+ // If the new average is smaller then it's a pass
665
+ Assert.ok(true, `New average ${chkDuration.avgDuration} is <= the base average ${baseDuration.avgDuration}`);
666
+ return
667
+ }
668
+
669
+ if (chkDuration.duration <= (baseDuration.avgDuration + (baseDuration.deviation / 2))) {
670
+ // If the new min is smaller then it's a pass
671
+ Assert.ok(true, `Chk minimum ${chkDuration.duration} is <= base average less half base deviation ${baseDuration.avgDuration + (baseDuration.deviation / 2)}`);
672
+ return;
673
+ }
674
+
675
+ if ((chkDuration.duration + chkDuration.deviation) <= baseDuration.avgDuration) {
676
+ // If the new min is smaller then it's a pass
677
+ Assert.ok(true, `Chk min plus deviation ${chkDuration.duration + chkDuration.deviation} is <= base average ${baseDuration.avgDuration}`);
678
+ return;
679
+ }
680
+
681
+ if ((chkDuration.duration + baseDuration.deviation) <= baseDuration.avgDuration) {
682
+ // If the new min is smaller then it's a pass
683
+ Assert.ok(true, `Chk min plus base deviation ${chkDuration.duration + baseDuration.deviation} is <= base average ${baseDuration.avgDuration}`);
684
+ return;
685
+ }
686
+
687
+ if (chkDuration.duration <= baseDuration.avgDuration) {
688
+ // If the new min is smaller than the base average
689
+ Assert.ok(true, `New minimum ${chkDuration.duration} is <= the base average ${baseDuration.avgDuration}`);
690
+ return;
691
+ }
692
+
693
+ if (chkDuration.duration <= baseDuration.maxDuration) {
694
+ // If the new min is smaller than the base max value (needed for build servers and shared CPU runs)
695
+ Assert.ok(true, `New minimum ${chkDuration.duration} is <= the base average ${baseDuration.maxDuration}`);
696
+ return;
697
+ }
698
+
699
+ Assert.ok(false, "The new values are not smaller or within the standard deviation thresholds\n" +
700
+ `Base: mn:${baseDuration.duration}, avg:${baseDuration.avgDuration}, avg:${baseDuration.maxDuration}, dev:${baseDuration.deviation} it:${baseDuration.iteration} avg:${baseDuration.avgIteration}\n` +
701
+ `Chk : mn:${chkDuration.duration}, avg:${chkDuration.avgDuration}, avg:${chkDuration.maxDuration}, dev:${chkDuration.deviation} it:${chkDuration.iteration} avg:${chkDuration.avgIteration}`);
702
+ }
703
+
704
+ private _runPerfIterations(theDuration: PerfMeasurements, testName: string, theTest: () => void, iterations: number, attempts: number[]) {
705
+ let start = performance.now();
706
+ for (let lp = 0; lp < iterations; lp++) {
707
+ theTest();
708
+ }
709
+ let duration = performance.now() - start;
710
+ if (attempts.length === 0) {
711
+ theDuration.duration = duration;
712
+ theDuration.maxDuration = duration;
713
+ theDuration.total = duration;
714
+ } else {
715
+ theDuration.total += duration;
716
+ theDuration.duration = Math.min(theDuration.duration, duration);
717
+ theDuration.maxDuration = Math.max(theDuration.maxDuration, duration);
718
+ }
719
+ attempts.push(duration);
720
+ Assert.ok(true, `${testName}: Attempt: ${(attempts.length)} Took: ${duration}ms Avg: ${duration / iterations}`);
721
+ }
722
+
723
+ private _runPerfAttempts(testName: string, theTest: () => void, iterations: number, maxAttempts: number, totalAttempts: number): PerfMeasurements {
724
+ let values: number[] = []
725
+ let theDuration: PerfMeasurements = {
726
+ duration: 0,
727
+ iteration: 0,
728
+ avgIteration: 0,
729
+ avgDuration: 0,
730
+ maxDuration: 0,
731
+ total: 0,
732
+ attempts: totalAttempts,
733
+ deviation: 0
734
+ };
735
+
736
+ let attempts = 0;
737
+ do {
738
+ attempts++;
739
+ this._runPerfIterations(theDuration, testName, theTest, iterations, values);
740
+ } while (attempts < maxAttempts);
741
+
742
+ theDuration.iteration = theDuration.duration / iterations;
743
+ totalAttempts += attempts;
744
+ theDuration.attempts = totalAttempts;
745
+ theDuration.avgDuration = theDuration.total / attempts;
746
+ theDuration.avgIteration = theDuration.avgDuration / iterations;
747
+ theDuration.deviation = this._getStandardDeviation(values);
748
+
749
+ return theDuration;
750
+ }
751
+
752
+ private _runPerfTest(testName: string, theTest: () => void, maxTime: number, iterations: number, maxIteration: number, baseMeasurements?: PerfMeasurements, maxAttempts = 25): PerfMeasurements {
753
+ let theDuration: PerfMeasurements = {} as PerfMeasurements;
754
+
755
+ let retryCount = 0;
756
+ while (retryCount < 5) {
757
+ retryCount++;
758
+ theDuration = this._runPerfAttempts(testName, theTest, iterations, maxAttempts, theDuration.attempts || 0);
759
+
760
+ let devAllowance = (theDuration.deviation / 2);
761
+ if ((theDuration.duration + devAllowance) <= maxTime && (theDuration.iteration < maxIteration || (theDuration.avgIteration - devAllowance) < maxIteration)) {
762
+ // Good run
763
+ if (!baseMeasurements || theDuration.deviation < baseMeasurements.deviation * 2.5) {
764
+ break;
765
+ }
766
+ }
767
+ }
768
+
769
+ Assert.ok(theDuration.duration <= maxTime,
770
+ `${testName}: Check min total time for <= ${maxTime}ms from ${iterations} iterations. Min: ${theDuration.duration}ms Avg: ${theDuration.avgDuration}ms Max: ${theDuration.maxDuration}ms Total: ${theDuration.total}ms Deviation: ${theDuration.deviation}ms`);
771
+ Assert.ok(theDuration.iteration < maxIteration || (theDuration.avgIteration - (theDuration.deviation / 2)) < maxIteration,
772
+ `${testName}: Check Average iteration. Avg: ${theDuration.avgIteration}ms Min: ${theDuration.iteration}`);
773
+
774
+ return theDuration;
775
+ }
776
+
777
+ private _runPerfTestAsync(testName: string, theTest: () => void, maxTime: number, iterations: number, maxIteration: number, baseMeasurements?: PerfMeasurements, maxAttempts = 25): Promise<PerfMeasurements> {
778
+ let _self = this;
779
+
780
+ return new Promise<PerfMeasurements>((runComplete, runReject) => {
781
+ function _scheduleTest(theTest: () => void) {
782
+ AITestClass.orgSetTimeout(() => {
783
+ try {
784
+ theTest.call(_self);
785
+ } catch (e) {
786
+ Assert.ok(false, "Unexpected exception - " + e);
787
+ runReject(e);
788
+ }
789
+ }, 0);
790
+ }
791
+
792
+ try {
793
+ let theDuration: PerfMeasurements = {} as PerfMeasurements;
794
+ let retryCount = 0;
795
+
796
+ function doAttempts() {
797
+ retryCount++;
798
+ theDuration = _self._runPerfAttempts(testName, theTest, iterations, maxAttempts, theDuration.attempts || 0);
799
+
800
+ let devAllowance = (theDuration.deviation / 2);
801
+ if (retryCount >= 5 || ((theDuration.duration + devAllowance) <= maxTime && (theDuration.iteration < maxIteration || (theDuration.avgIteration - devAllowance) < maxIteration))) {
802
+ // Last Retry or Good run
803
+ if (retryCount >= 5 || !baseMeasurements || theDuration.deviation < baseMeasurements.deviation * 2.5) {
804
+ Assert.ok(theDuration.duration <= maxTime,
805
+ `${testName}: Check min total time for <= ${maxTime}ms from ${iterations} iterations. Min: ${theDuration.duration}ms Avg: ${theDuration.avgDuration}ms Max: ${theDuration.maxDuration}ms Total: ${theDuration.total}ms Deviation: ${theDuration.deviation}ms`);
806
+ Assert.ok(theDuration.iteration < maxIteration || (theDuration.avgIteration - (theDuration.deviation / 2)) < maxIteration,
807
+ `${testName}: Check Average iteration. Avg: ${theDuration.avgIteration}ms Min: ${theDuration.iteration}`);
808
+
809
+ runComplete(theDuration);
810
+ return;
811
+ }
812
+ }
813
+
814
+ Assert.ok(true,
815
+ `${testName}: Summary Min: ${theDuration.duration}ms Avg: ${theDuration.avgDuration}ms Max: ${theDuration.maxDuration}ms Total: ${theDuration.total}ms Deviation: ${theDuration.deviation}ms Iteration Avg: ${theDuration.avgIteration}ms Min: ${theDuration.iteration}`);
816
+
817
+ // reschedule
818
+ _scheduleTest(doAttempts);
819
+ }
820
+
821
+ _scheduleTest(doAttempts);
822
+ } catch (e) {
823
+ Assert.ok(false, "Unexpected exception - " + e);
824
+ runReject(e);
825
+ }
826
+ });
827
+ }
828
+ }