Skip to content

Commit 00b0bea

Browse files
committed
refactor: move performance tests to a script
1 parent c6ca238 commit 00b0bea

File tree

7 files changed

+50
-127
lines changed

7 files changed

+50
-127
lines changed

package-lock.json

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/machine-id/README.md

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# @mongodb-js/machine-id
22

3-
> Cross-platform module to retrieve unique machine IDs across desktop operating systems without admin privileges or child processes.
3+
> Native implementation for retrieving unique machine ID without admin privileges or child processes for desktop platforms. Faster and more reliable alternative to node-machine-id.
44
55
## Installation
66

@@ -28,21 +28,36 @@ const id = getMachineID({ raw: true });
2828
console.log('Original Machine ID:', id);
2929
```
3030

31-
### As a CLI
3231

33-
After installing globally, run:
34-
35-
```
36-
machine-id
37-
```
32+
## Supported Platforms
3833

39-
This will print the machine ID to the console.
34+
- **macOS**: Uses the `IOPlatformUUID` from the `IOKit` framework (Supported on macOS 12.0 and later).
35+
- **Linux**: Uses the `/var/lib/dbus/machine-id` file to retrieve the machine ID. If this file does not exist, it falls back to `/etc/machine-id`.
36+
- **Windows**: Uses the `MachineGuid` from the `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography` registry.
4037

4138
## Comparison with `node-machine-id`
4239

43-
This module provides similar functionality to [node-machine-id](https://www.npmjs.com/package/node-machine-id), but **using native access to system APIs without the need for child processes**.
40+
This module provides similar functionality to [node-machine-id](https://www.npmjs.com/package/node-machine-id), but **using native access to system APIs without the need for child processes**, making it much faster and reliable.
41+
42+
Here's a table of performance comparisons between the two libraries, based on the average runtime from 1000 iterations of the `getMachineId` and `machineIdSync` functions, from `scripts/benchmark.ts`:
43+
44+
| Test | node-machine-id | @mongodb-js/machine-id | Improvement |
45+
| ----------- | --------------- | ---------------------- | ----------- |
46+
| **Mac** |
47+
| Raw | 10.71ms | 0.0072ms | 1494x |
48+
| Hashed | 12.42ms | 0.0176ms | 707x |
49+
| **Linux** |
50+
| Raw | 3.26ms | 0.0059ms | 557x |
51+
| Hashed | 3.25ms | 0.0088ms | 368x |
52+
| **Windows** |
53+
| Raw | 45.36ms* | 0.0122ms | 3704x |
54+
| Hashed | 28.66ms* | 0.0272ms | 1053x |
4455

45-
If you were previously using `node-machine-id`, you can use the following mapping to get a result that uses the same hashing transformation. This helps create more consistent results as before but it is not guaranteed to be the same for all cases.
56+
\* - Windows tests may be inaccurate due to potential caching.
57+
58+
59+
### Migrating from `node-machine-id`
60+
If you were previously using `node-machine-id`, you can use the following mapping to get a result with the following hashing transformation. This is not guaranteed always to 1:1 match the output of `node-machine-id` for all cases. For example on Linux, it falls back to `/etc/machine-id` if `/var/lib/dbus/machine-id` is not available.
4661

4762
```ts
4863
import { createHash } from 'crypto';
@@ -51,20 +66,10 @@ import { getMachineId } from '@mongodb-js/machine-id';
5166
function machineIdSync(original: boolean): string | undefined {
5267
const rawMachineId = getMachineId({ raw: true }).toLowerCase();
5368

54-
if (original) {
55-
return rawMachineId;
56-
}
57-
58-
return createHash('sha256').update(rawMachineId).digest('hex');
69+
return original ? rawMachineId : createHash('sha256').update(rawMachineId).digest('hex');
5970
}
6071
```
6172

62-
## Supported Platforms
63-
64-
- **macOS**: Uses the `IOPlatformUUID` from the `IOKit` framework (Supported on macOS 12.0 and later).
65-
- **Linux**: Uses the `/etc/machine-id` file to retrieve the machine ID. If this file does not exist, it falls back to `/var/lib/dbus/machine-id`.
66-
- **Windows**: Uses the `MachineGuid` from the `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography` registry.
67-
6873
## License
6974

7075
Apache-2.0

packages/machine-id/bin/machine-id.js

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/machine-id/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@mongodb-js/machine-id",
33
"version": "1.0.0",
4-
"description": "Cross-platform native module to retrieve machine/device identifiers",
4+
"description": "Native implementation for retrieving unique machine ID without admin privileges or child processes for desktop platforms. Faster and more reliable alternative to node-machine-id.",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",
77
"scripts": {
@@ -33,12 +33,12 @@
3333
},
3434
"bugs": "https://jira.mongodb.org/projects/COMPASS/issues",
3535
"bin": {
36-
"machine-id": "lib/bin/machine-id.js"
36+
"machine-id": "dist/bin/machine-id.js"
3737
},
3838
"files": [
3939
"binding.cc",
4040
"binding.gyp",
41-
"lib",
41+
"dist",
4242
"LICENSE"
4343
],
4444
"devDependencies": {
@@ -55,6 +55,7 @@
5555
"mocha": "^8.4.0",
5656
"chai": "^4.5.0",
5757
"node-machine-id": "^1.1.12",
58-
"typescript": "^5.0.4"
58+
"typescript": "^5.0.4",
59+
"ts-node": "^10.9.2"
5960
}
6061
}

packages/machine-id/scripts/benchmark.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import { machineIdSync } from 'node-machine-id';
1212

1313
// Configuration
1414
const ITERATIONS = 100;
15-
const WARMUP_ITERATIONS = 10;
1615

1716
// Utility to format time
1817
function formatTime(ms: number): string {
@@ -40,15 +39,8 @@ function runBenchmark() {
4039
console.log(`Test iterations: ${ITERATIONS}`);
4140
console.log('----------------------------------------');
4241

43-
// Warm-up
44-
console.log('Warming up...');
45-
for (let i = 0; i < WARMUP_ITERATIONS; i++) {
46-
getMachineId({ raw: true });
47-
machineIdSync(true);
48-
}
49-
5042
// Test raw mode (no hashing)
51-
console.log('\nRaw machine ID retrieval:');
43+
console.log('Raw:');
5244

5345
const startOursRaw = process.hrtime.bigint();
5446
for (let i = 0; i < ITERATIONS; i++) {
@@ -75,8 +67,10 @@ function runBenchmark() {
7567
`Comparison: @mongodb-js/machine-id is ${formatComparison(ourTimeRaw, otherTimeRaw)}`,
7668
);
7769

70+
console.log('----------------------------------------');
71+
7872
// Test hashed mode
79-
console.log('\nHashed machine ID:');
73+
console.log('Hashed:');
8074

8175
// @mongodb-js/machine-id
8276
const startOursHashed = process.hrtime.bigint();
@@ -103,8 +97,6 @@ function runBenchmark() {
10397
console.log(
10498
`Comparison: @mongodb-js/machine-id is ${formatComparison(ourTimeHashed, otherTimeHashed)}`,
10599
);
106-
107-
console.log('\n========================================');
108100
}
109101

110102
// Run the benchmark
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env node
2+
import { getMachineId } from '..';
3+
4+
// Check if --raw flag is provided
5+
const rawFlag = process.argv.includes('--raw');
6+
7+
// Get the machine ID, passing the raw option if requested
8+
const id =
9+
getMachineId({ raw: rawFlag }) || 'Machine ID not available on this platform';
10+
11+
// eslint-disable-next-line no-console
12+
console.log(id);

packages/machine-id/src/index.spec.ts

Lines changed: 0 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -55,89 +55,4 @@ describe('machine-id', function () {
5555
expect(hashRegex.test(id));
5656
});
5757
});
58-
59-
describe('performance comparison', function () {
60-
// Increase timeout for performance tests
61-
this.timeout(100_000);
62-
63-
it('performs faster than node-machine-id (raw)', function () {
64-
const iterations = 1000;
65-
66-
// Warm-up run to account for initial load time
67-
getMachineId({ raw: true });
68-
otherMachineId(true);
69-
70-
// Test implementation
71-
const startOurs = process.hrtime.bigint();
72-
for (let i = 0; i < iterations; i++) {
73-
getMachineId({ raw: true });
74-
}
75-
const endOurs = process.hrtime.bigint();
76-
const ourTime = Number(endOurs - startOurs) / 1_000_000; // Convert to ms
77-
78-
// Test node-machine-id
79-
const startOther = process.hrtime.bigint();
80-
for (let i = 0; i < iterations; i++) {
81-
otherMachineId(true);
82-
}
83-
const endOther = process.hrtime.bigint();
84-
const otherTime = Number(endOther - startOther) / 1_000_000; // Convert to ms
85-
86-
console.log(
87-
`Performance comparison (raw mode, ${iterations} iterations):`,
88-
);
89-
console.log(
90-
`- Our implementation: ${ourTime.toFixed(4)}ms (${(ourTime / iterations).toFixed(4)}ms per call)`,
91-
);
92-
console.log(
93-
`- node-machine-id: ${otherTime.toFixed(4)}ms (${(otherTime / iterations).toFixed(4)}ms per call)`,
94-
);
95-
console.log(
96-
`- Difference: ${ourTime < otherTime ? 'Ours is ' + (otherTime / ourTime).toFixed(2) + 'x faster' : 'node-machine-id is ' + (ourTime / otherTime).toFixed(2) + 'x faster'}`,
97-
);
98-
99-
// We expect our native implementation to be faster
100-
// but don't fail the test if it's not, just report the measurements
101-
});
102-
103-
it('performs faster than node-machine-id (hashed)', function () {
104-
const iterations = 1000;
105-
106-
// Warm-up run
107-
getMachineId();
108-
otherMachineId();
109-
110-
// Test our implementation
111-
const startOurs = process.hrtime.bigint();
112-
for (let i = 0; i < iterations; i++) {
113-
getMachineId();
114-
}
115-
const endOurs = process.hrtime.bigint();
116-
const ourTime = Number(endOurs - startOurs) / 1_000_000; // Convert to ms
117-
118-
// Test node-machine-id
119-
const startOther = process.hrtime.bigint();
120-
for (let i = 0; i < iterations; i++) {
121-
otherMachineId();
122-
}
123-
const endOther = process.hrtime.bigint();
124-
const otherTime = Number(endOther - startOther) / 1_000_000; // Convert to ms
125-
126-
console.log(
127-
`Performance comparison (hashed mode, ${iterations} iterations):`,
128-
);
129-
console.log(
130-
`- Our implementation: ${ourTime.toFixed(4)}ms (${(ourTime / iterations).toFixed(4)}ms per call)`,
131-
);
132-
console.log(
133-
`- node-machine-id: ${otherTime.toFixed(4)}ms (${(otherTime / iterations).toFixed(4)}ms per call)`,
134-
);
135-
console.log(
136-
`- Difference: ${ourTime < otherTime ? 'Ours is ' + (otherTime / ourTime).toFixed(2) + 'x faster' : 'node-machine-id is ' + (ourTime / otherTime).toFixed(2) + 'x faster'}`,
137-
);
138-
139-
// We expect our native implementation to be faster
140-
// but don't fail the test if it's not, just report the measurements
141-
});
142-
});
14358
});

0 commit comments

Comments
 (0)