node-opcua-leak-detector 2.168.0 → 2.172.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-opcua-leak-detector",
3
- "version": "2.168.0",
3
+ "version": "2.172.0",
4
4
  "description": "pure nodejs OPCUA SDK - module leak-detector",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -24,14 +24,14 @@
24
24
  "internet of things"
25
25
  ],
26
26
  "homepage": "http://node-opcua.github.io/",
27
- "gitHead": "653b6d6df801ca17298308089dee32e5b12102b6",
27
+ "gitHead": "dfe9993a93b5c3897825e898b5f07b25952c7f45",
28
28
  "files": [
29
29
  "src"
30
30
  ],
31
31
  "dependencies": {
32
32
  "chalk": "4.1.2",
33
33
  "node-opcua-assert": "2.164.0",
34
- "node-opcua-object-registry": "2.168.0",
34
+ "node-opcua-object-registry": "2.172.0",
35
35
  "wtfnode": "^0.10.1"
36
36
  }
37
37
  }
@@ -1,31 +1,33 @@
1
1
  // memoryLeakDetector.js
2
2
  let wtf;
3
3
 
4
-
5
4
  if (process.env.MEM_LEAK_DETECTION_WTF_ENABLED) {
6
- console.log("[LeakDetector] ⚠️ WTFNODE enabled");
7
- wtf = require('wtfnode');
8
- wtf.init();
5
+ console.log("[LeakDetector] ⚠️ WTFNODE enabled");
6
+ wtf = require("wtfnode");
7
+ wtf.init();
9
8
  } else {
10
- console.log("[LeakDetector] ℹ️ WTFNODE disabled. Use MEM_LEAK_DETECTION_WTF_ENABLED=true to enable it.");
9
+ console.log("[LeakDetector] ℹ️ WTFNODE disabled. Use MEM_LEAK_DETECTION_WTF_ENABLED=true to enable it.");
11
10
  }
12
11
 
13
-
14
- let noGCexposed = undefined;
12
+ let noGCexposed;
15
13
 
16
14
  /**
17
15
  * Forces garbage collection if available.
18
16
  */
19
17
  function forceGC() {
20
- if (global.gc) {
21
- global.gc();
22
- noGCexposed = false;
23
- } else {
24
- if (noGCexposed == undefined) {
25
- console.warn('[LeakDetector] ⚠️ Garbage collection not exposed. Run Node.js with --expose-gc flag for more accurate results.');
18
+ if (global.gc) {
19
+ // Major GC: thorough enough that callers don't need to invoke a separate
20
+ // global.gc(true) themselves before calling takeMemorySnapshot.
21
+ global.gc(true);
22
+ noGCexposed = false;
23
+ } else {
24
+ if (noGCexposed === undefined) {
25
+ console.warn(
26
+ "[LeakDetector] ⚠️ Garbage collection not exposed. Run Node.js with --expose-gc flag for more accurate results."
27
+ );
28
+ }
29
+ noGCexposed = true;
26
30
  }
27
- noGCexposed = true;
28
- }
29
31
  }
30
32
 
31
33
  /**
@@ -33,11 +35,18 @@ function forceGC() {
33
35
  * @returns {number} Heap used in bytes.
34
36
  */
35
37
  function takeMemorySnapshot() {
36
- if (noGCexposed) {
37
- return;
38
- }
39
- forceGC();
40
- return process.memoryUsage().heapUsed;
38
+ if (noGCexposed) {
39
+ return;
40
+ }
41
+ const { performance } = require("node:perf_hooks");
42
+ const start = performance.now();
43
+ forceGC();
44
+ const end = performance.now();
45
+ const duration = (end - start).toFixed(2);
46
+ if (duration > 1) {
47
+ console.log(`[LeakDetector] ♻️ Garbage collection took ${duration}ms`);
48
+ }
49
+ return process.memoryUsage().heapUsed;
41
50
  }
42
51
 
43
52
  /**
@@ -48,29 +57,27 @@ function takeMemorySnapshot() {
48
57
  * @returns {Object} - Result with before/after memory and leak status.
49
58
  */
50
59
  function checkForMemoryLeak(before, after, threshold = 2) {
60
+ if (noGCexposed) {
61
+ return;
62
+ }
63
+ const heapUsedBefore = before / 1024 / 1024; // MB
64
+ const heapUsedAfter = after / 1024 / 1024; // MB
65
+ const delta = heapUsedAfter - heapUsedBefore;
66
+ const isLeak = delta > threshold;
51
67
 
52
- if (noGCexposed) {
53
- return;
54
- }
55
- const heapUsedBefore = before / 1024 / 1024; // MB
56
- const heapUsedAfter = after / 1024 / 1024; // MB
57
- const delta = heapUsedAfter - heapUsedBefore;
58
- const isLeak = delta > threshold;
59
-
60
- if (isLeak) {
61
- console.warn(
62
- `[LeakDetector] ⚠️ Potential memory leak detected in test: ${delta.toFixed(2)} MB increase (threshold: ${threshold} MB , total : ${heapUsedAfter.toFixed(2)} MB)`
63
- );
64
- } else {
65
- console.log(
66
- `[LeakDetector] ✅ No significant memory leak detected: ${delta.toFixed(2)} MB increase total : ${heapUsedAfter.toFixed(2)} MB`
67
- );
68
- }
69
-
68
+ if (isLeak) {
69
+ console.warn(
70
+ `[LeakDetector] ⚠️ Potential memory leak detected in test: ${delta.toFixed(2)} MB increase (threshold: ${threshold} MB , total : ${heapUsedAfter.toFixed(2)} MB)`
71
+ );
72
+ } else {
73
+ console.log(
74
+ `[LeakDetector] No significant memory leak detected: ${delta.toFixed(2)} MB increase total : ${heapUsedAfter.toFixed(2)} MB`
75
+ );
76
+ }
70
77
 
71
- wtf?.dump({ fullStacks: true }); // Show open handles, listeners, etc.
78
+ wtf?.dump({ fullStacks: true }); // Show open handles, listeners, etc.
72
79
 
73
- return { before: heapUsedBefore, after: heapUsedAfter, delta, isLeak };
80
+ return { before: heapUsedBefore, after: heapUsedAfter, delta, isLeak };
74
81
  }
75
82
 
76
- module.exports = { takeMemorySnapshot, checkForMemoryLeak };
83
+ module.exports = { takeMemorySnapshot, checkForMemoryLeak };
@@ -477,10 +477,8 @@ exports.installResourceLeakDetector = function(isGlobal, func) {
477
477
 
478
478
  });
479
479
  beforeEach(() => {
480
- // make sure we start with a garbage collected situation
481
- if (global.gc) {
482
- global.gc(true);
483
- }
480
+ // takeMemorySnapshot now does its own major GC; no need for an
481
+ // explicit gc(true) here. Saves one ~100ms major-GC stall per test.
484
482
  beforeSnapshot = takeMemorySnapshot();
485
483
  });
486
484
  if (func) {
@@ -506,10 +504,7 @@ exports.installResourceLeakDetector = function(isGlobal, func) {
506
504
 
507
505
  } else {
508
506
  beforeEach(function(/*this: Mocha.Test*/) {
509
-
510
- if (global.gc) {
511
- global.gc(true);
512
- }
507
+ // takeMemorySnapshot now does its own major GC; no separate gc(true) here.
513
508
  resourceLeakDetector.ctx = this.test.ctx;
514
509
  resourceLeakDetector.start();
515
510
  beforeSnapshot = takeMemorySnapshot();