@contrail/util 1.1.14-alpha-1 → 1.1.15-alpha-2

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/lib/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export * from './date-util/date-util';
4
4
  export * from './map-util/map-util';
5
5
  export * from './object-util/object-util';
6
6
  export * from './order-util/order-util';
7
+ export * from './performance-util/performance-util';
7
8
  export * from './promise-util/promise-util';
8
9
  export * from './retry-util/retry-util';
9
10
  export * from './string-util/string-util';
package/lib/index.js CHANGED
@@ -20,6 +20,7 @@ __exportStar(require("./date-util/date-util"), exports);
20
20
  __exportStar(require("./map-util/map-util"), exports);
21
21
  __exportStar(require("./object-util/object-util"), exports);
22
22
  __exportStar(require("./order-util/order-util"), exports);
23
+ __exportStar(require("./performance-util/performance-util"), exports);
23
24
  __exportStar(require("./promise-util/promise-util"), exports);
24
25
  __exportStar(require("./retry-util/retry-util"), exports);
25
26
  __exportStar(require("./string-util/string-util"), exports);
@@ -1,23 +1 @@
1
- type PerformanceComparisonEvent = {
2
- durationMsJson: number;
3
- durationMsRFDC: number;
4
- input: any;
5
- };
6
- type PerformanceSummary = {
7
- eventForWhichJsonWasMostFaster: PerformanceComparisonEvent | null;
8
- eventForWhichRFDCWasMostFaster: PerformanceComparisonEvent | null;
9
- totalDurationMsJson: number;
10
- totalDurationMsRFDC: number;
11
- invocationsInWhichJsonWasFaster: PerformanceComparisonEvent[];
12
- invocationsInWhichRFDCWasFaster: PerformanceComparisonEvent[];
13
- };
14
- declare global {
15
- interface Window {
16
- performanceSummary: PerformanceSummary;
17
- performanceEvents: PerformanceComparisonEvent[];
18
- }
19
- }
20
- export declare function cloneDeep<T>(obj: T, options?: {
21
- shouldPreserveCircularReferences?: boolean;
22
- }): T;
23
- export {};
1
+ export declare function cloneDeep<T>(obj: T): T | null;
@@ -1,53 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.cloneDeep = cloneDeep;
4
- const cloneDefault = require('rfdc')();
5
- const cloneWithCircles = require('rfdc')({ circles: true });
6
- function cloneDeep(obj, options) {
7
- var _a;
8
- console.log('running cloneDeep');
9
- const shouldPreserveCircles = (_a = options === null || options === void 0 ? void 0 : options.shouldPreserveCircularReferences) !== null && _a !== void 0 ? _a : false;
10
- const clone = shouldPreserveCircles ? cloneWithCircles : cloneDefault;
11
- const startJson = performance.now();
12
- JSON.parse(JSON.stringify(obj));
13
- const durationMsJson = performance.now() - startJson;
14
- const startRFDC = performance.now();
15
- const rfdcClone = clone(obj);
16
- const durationMsRFDC = performance.now() - startRFDC;
17
- if (!window.performanceEvents) {
18
- window.performanceEvents = [];
19
- }
20
- const performanceEvent = {
21
- durationMsJson,
22
- durationMsRFDC,
23
- input: obj,
24
- };
25
- window.performanceEvents.push(performanceEvent);
26
- window.performanceSummary = window.performanceSummary || {
27
- eventForWhichJsonWasMostFaster: null,
28
- eventForWhichRFDCWasMostFaster: null,
29
- totalDurationMsJson: 0,
30
- totalDurationMsRFDC: 0,
31
- invocationsInWhichJsonWasFaster: [],
32
- invocationsInWhichRFDCWasFaster: [],
33
- };
34
- window.performanceSummary.totalDurationMsJson += durationMsJson;
35
- window.performanceSummary.totalDurationMsRFDC += durationMsRFDC;
36
- const isJsonFaster = durationMsJson < durationMsRFDC;
37
- if (isJsonFaster) {
38
- window.performanceSummary.invocationsInWhichJsonWasFaster.push(performanceEvent);
39
- if (!window.performanceSummary.eventForWhichJsonWasMostFaster ||
40
- durationMsJson < window.performanceSummary.eventForWhichJsonWasMostFaster.durationMsJson) {
41
- window.performanceSummary.eventForWhichJsonWasMostFaster = performanceEvent;
4
+ function cloneDeep(obj) {
5
+ if (obj === null || obj === undefined)
6
+ return null;
7
+ return JSON.parse(JSON.stringify(obj), (_key, value) => {
8
+ if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/.test(value)) {
9
+ const date = new Date(value);
10
+ if (!isNaN(date.getTime()))
11
+ return date;
42
12
  }
43
- }
44
- else {
45
- window.performanceSummary.invocationsInWhichRFDCWasFaster.push(performanceEvent);
46
- if (!window.performanceSummary.eventForWhichRFDCWasMostFaster ||
47
- durationMsRFDC < window.performanceSummary.eventForWhichRFDCWasMostFaster.durationMsRFDC) {
48
- window.performanceSummary.eventForWhichRFDCWasMostFaster = performanceEvent;
49
- }
50
- }
51
- console.log('cloneDeep performance summary:', window.performanceSummary);
52
- return rfdcClone;
13
+ return value;
14
+ });
53
15
  }
@@ -5,7 +5,37 @@ const cloneDeep_1 = require("./cloneDeep");
5
5
  function jsonClone(obj) {
6
6
  return JSON.parse(JSON.stringify(obj));
7
7
  }
8
- console.log('Performance test for very large objects:');
8
+ console.log('Performance test for small objects:');
9
+ let smallObject = {
10
+ sub1: {
11
+ val: 1,
12
+ },
13
+ sub3: {
14
+ val: 2,
15
+ valX: '3',
16
+ },
17
+ };
18
+ console.time('cloneDeepSmallRFDC');
19
+ Array.from({ length: 10000 }).forEach(() => {
20
+ (0, cloneDeep_1.cloneDeep)(smallObject);
21
+ });
22
+ console.timeEnd('cloneDeepSmallRFDC');
23
+ console.time('cloneDeepSmallLodash');
24
+ Array.from({ length: 10000 }).forEach(() => {
25
+ (0, lodash_1.cloneDeep)(smallObject);
26
+ });
27
+ console.timeEnd('cloneDeepSmallLodash');
28
+ console.time('cloneDeepSmallJson');
29
+ Array.from({ length: 10000 }).forEach(() => {
30
+ jsonClone(smallObject);
31
+ });
32
+ console.timeEnd('cloneDeepSmallJson');
33
+ console.time('structuredCloneSmall');
34
+ Array.from({ length: 10000 }).forEach(() => {
35
+ structuredClone(smallObject);
36
+ });
37
+ console.timeEnd('structuredCloneSmall');
38
+ console.log('\n\nPerformance test for very large objects:');
9
39
  let veryLargeObject = {};
10
40
  for (let i = 0; i < 100000; i++) {
11
41
  veryLargeObject[`key${i}`] = {
@@ -19,9 +49,9 @@ for (let i = 0; i < 100000; i++) {
19
49
  },
20
50
  };
21
51
  }
22
- console.time('cloneDeep');
52
+ console.time('cloneDeepRFDC');
23
53
  (0, cloneDeep_1.cloneDeep)(veryLargeObject);
24
- console.timeEnd('cloneDeep');
54
+ console.timeEnd('cloneDeepRFDC');
25
55
  console.time('cloneDeepLodash');
26
56
  (0, lodash_1.cloneDeep)(veryLargeObject);
27
57
  console.timeEnd('cloneDeepLodash');
@@ -45,9 +75,9 @@ for (let i = 0; i < 100000; i++) {
45
75
  },
46
76
  });
47
77
  }
48
- console.time('cloneDeepArray');
78
+ console.time('cloneDeepArrayRFDC');
49
79
  (0, cloneDeep_1.cloneDeep)(veryLargeArray);
50
- console.timeEnd('cloneDeepArray');
80
+ console.timeEnd('cloneDeepArrayRFDC');
51
81
  console.time('cloneDeepArrayLodash');
52
82
  (0, lodash_1.cloneDeep)(veryLargeArray);
53
83
  console.timeEnd('cloneDeepArrayLodash');
@@ -62,9 +92,9 @@ const fs = require("fs");
62
92
  const path = require("path");
63
93
  const assortmentFilePath = path.join(__dirname, 'assortment.json');
64
94
  const assortmentData = JSON.parse(fs.readFileSync(assortmentFilePath, 'utf8'));
65
- console.time('cloneDeepAssortment25k');
95
+ console.time('cloneDeepAssortment25kRFDC');
66
96
  (0, cloneDeep_1.cloneDeep)(assortmentData);
67
- console.timeEnd('cloneDeepAssortment25k');
97
+ console.timeEnd('cloneDeepAssortment25kRFDC');
68
98
  console.time('cloneDeepAssortment25kLodash');
69
99
  (0, lodash_1.cloneDeep)(assortmentData);
70
100
  console.timeEnd('cloneDeepAssortment25kLodash');
@@ -0,0 +1,17 @@
1
+ type TimingSpans = TimingNode[];
2
+ type TimingStack = TimingNode[];
3
+ type TimingNode = {
4
+ label: string;
5
+ durationMs: number;
6
+ children: TimingNode[];
7
+ };
8
+ type TimingProfile = {
9
+ timingSpans: TimingSpans;
10
+ timingStack: TimingStack;
11
+ };
12
+ export declare function getDefaultTimingProfile(): TimingProfile;
13
+ export declare function clearDefaultTimingProfile(): void;
14
+ export declare function withTimingAsync<T>(label: string, fn: () => Promise<T>): Promise<T>;
15
+ export declare function withTimingSync<T>(label: string, fn: () => T): T;
16
+ export declare function displayTimingTree(nodes: TimingSpans, depth?: number): string;
17
+ export {};
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getDefaultTimingProfile = getDefaultTimingProfile;
13
+ exports.clearDefaultTimingProfile = clearDefaultTimingProfile;
14
+ exports.withTimingAsync = withTimingAsync;
15
+ exports.withTimingSync = withTimingSync;
16
+ exports.displayTimingTree = displayTimingTree;
17
+ const DEFAULT_TIMING_PROFILE = {
18
+ timingSpans: [],
19
+ timingStack: [],
20
+ };
21
+ function getDefaultTimingProfile() {
22
+ return DEFAULT_TIMING_PROFILE;
23
+ }
24
+ function getTimingStack() {
25
+ return DEFAULT_TIMING_PROFILE.timingStack;
26
+ }
27
+ function getTimingSpans() {
28
+ return DEFAULT_TIMING_PROFILE.timingSpans;
29
+ }
30
+ function clearDefaultTimingProfile() {
31
+ DEFAULT_TIMING_PROFILE.timingSpans = [];
32
+ DEFAULT_TIMING_PROFILE.timingStack = [];
33
+ }
34
+ function withTimingAsync(label, fn) {
35
+ return __awaiter(this, void 0, void 0, function* () {
36
+ const start = performance.now();
37
+ const timingNode = { label, durationMs: 0, children: [] };
38
+ const parent = getTimingStack().length > 0 ? getTimingStack()[getTimingStack().length - 1] : null;
39
+ if (parent) {
40
+ parent.children.push(timingNode);
41
+ }
42
+ else {
43
+ getTimingSpans().push(timingNode);
44
+ }
45
+ getTimingStack().push(timingNode);
46
+ return fn().finally(() => {
47
+ const end = performance.now();
48
+ timingNode.durationMs = end - start;
49
+ getTimingStack().pop();
50
+ });
51
+ });
52
+ }
53
+ function withTimingSync(label, fn) {
54
+ const start = performance.now();
55
+ const timingNode = { label, durationMs: 0, children: [] };
56
+ const parent = getTimingStack().length > 0 ? getTimingStack()[getTimingStack().length - 1] : null;
57
+ if (parent) {
58
+ parent.children.push(timingNode);
59
+ }
60
+ else {
61
+ getTimingSpans().push(timingNode);
62
+ }
63
+ getTimingStack().push(timingNode);
64
+ try {
65
+ return fn();
66
+ }
67
+ finally {
68
+ const end = performance.now();
69
+ timingNode.durationMs = end - start;
70
+ getTimingStack().pop();
71
+ }
72
+ }
73
+ function displayTimingTree(nodes, depth = 0) {
74
+ const lines = [];
75
+ const indent = ' '.repeat(depth);
76
+ const totalWidth = 80;
77
+ const timeWidth = 10;
78
+ nodes.forEach((node) => {
79
+ const timeStr = `${node.durationMs.toFixed(2)}ms`;
80
+ const labelWithIndent = `${indent}${node.label}`;
81
+ const availableWidth = totalWidth - timeWidth - labelWithIndent.length;
82
+ const dots = '.'.repeat(Math.max(2, availableWidth));
83
+ lines.push(`${labelWithIndent}${dots}${timeStr.padStart(timeWidth)}`);
84
+ if (node.children && node.children.length > 0) {
85
+ lines.push(displayTimingTree(node.children, depth + 1));
86
+ }
87
+ });
88
+ const result = lines.join('\n');
89
+ if (depth === 0) {
90
+ console.log('\n--- Performance Timing Tree ---');
91
+ console.log(result);
92
+ console.log('--- End Timing ---\n');
93
+ }
94
+ return result;
95
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@contrail/util",
3
- "version": "1.1.14-alpha-1",
4
- "description": "General javascript utilities",
3
+ "version": "1.1.15-alpha-2",
4
+ "description": "General JavaScript utilities",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "scripts": {
@@ -41,7 +41,6 @@
41
41
  "dependencies": {
42
42
  "@contrail/types": "^3.0.95",
43
43
  "fflate": "^0.8.2",
44
- "lodash": "^4.17.21",
45
- "rfdc": "^1.4.1"
44
+ "lodash": "^4.17.21"
46
45
  }
47
46
  }