os: improve networkInterfaces performance
This algorithm uses less data transformations and is therefore significantly faster than the one before. PR-URL: https://github.com/nodejs/node/pull/22359 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This commit is contained in:
parent
104492bd83
commit
9bcb744ee5
@ -1,41 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
function getCIDRSuffix(mask, protocol = 'ipv4') {
|
||||
const isV6 = protocol === 'ipv6';
|
||||
const bitsString = mask
|
||||
.split(isV6 ? ':' : '.')
|
||||
.filter((v) => !!v)
|
||||
.map((v) => pad(parseInt(v, isV6 ? 16 : 10).toString(2), isV6))
|
||||
.join('');
|
||||
|
||||
if (isValidMask(bitsString)) {
|
||||
return countOnes(bitsString);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function pad(binaryString, isV6) {
|
||||
const groupLength = isV6 ? 16 : 8;
|
||||
const binLen = binaryString.length;
|
||||
|
||||
return binLen < groupLength ?
|
||||
`${'0'.repeat(groupLength - binLen)}${binaryString}` : binaryString;
|
||||
}
|
||||
|
||||
function isValidMask(bitsString) {
|
||||
const firstIndexOfZero = bitsString.indexOf(0);
|
||||
const lastIndexOfOne = bitsString.lastIndexOf(1);
|
||||
|
||||
return firstIndexOfZero < 0 || firstIndexOfZero > lastIndexOfOne;
|
||||
}
|
||||
|
||||
function countOnes(bitsString) {
|
||||
return bitsString
|
||||
.split('')
|
||||
.reduce((acc, bit) => acc += parseInt(bit, 10), 0);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getCIDRSuffix
|
||||
};
|
67
lib/os.js
67
lib/os.js
@ -24,7 +24,6 @@
|
||||
const { pushValToArrayMax, safeGetenv } = process.binding('util');
|
||||
const constants = process.binding('constants').os;
|
||||
const { deprecate } = require('internal/util');
|
||||
const { getCIDRSuffix } = require('internal/os');
|
||||
const isWindows = process.platform === 'win32';
|
||||
|
||||
const { ERR_SYSTEM_ERROR } = require('internal/errors');
|
||||
@ -144,19 +143,67 @@ function endianness() {
|
||||
}
|
||||
endianness[Symbol.toPrimitive] = () => kEndianness;
|
||||
|
||||
// Returns the number of ones in the binary representation of the decimal
|
||||
// number.
|
||||
function countBinaryOnes(n) {
|
||||
let count = 0;
|
||||
// Remove one "1" bit from n until n is the power of 2. This iterates k times
|
||||
// while k is the number of "1" in the binary representation.
|
||||
// For more check https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
|
||||
while (n !== 0) {
|
||||
n = n & (n - 1);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function getCIDR({ address, netmask, family }) {
|
||||
let ones = 0;
|
||||
let split = '.';
|
||||
let range = 10;
|
||||
let groupLength = 8;
|
||||
let hasZeros = false;
|
||||
|
||||
if (family === 'IPv6') {
|
||||
split = ':';
|
||||
range = 16;
|
||||
groupLength = 16;
|
||||
}
|
||||
|
||||
const parts = netmask.split(split);
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
if (parts[i] !== '') {
|
||||
const binary = parseInt(parts[i], range);
|
||||
const tmp = countBinaryOnes(binary);
|
||||
ones += tmp;
|
||||
if (hasZeros) {
|
||||
if (tmp !== 0) {
|
||||
return null;
|
||||
}
|
||||
} else if (tmp !== groupLength) {
|
||||
if ((binary & 1) !== 0) {
|
||||
return null;
|
||||
}
|
||||
hasZeros = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return `${address}/${ones}`;
|
||||
}
|
||||
|
||||
function networkInterfaces() {
|
||||
const interfaceAddresses = getInterfaceAddresses();
|
||||
|
||||
return Object.entries(interfaceAddresses).reduce((acc, [key, val]) => {
|
||||
acc[key] = val.map((v) => {
|
||||
const protocol = v.family.toLowerCase();
|
||||
const suffix = getCIDRSuffix(v.netmask, protocol);
|
||||
const cidr = suffix ? `${v.address}/${suffix}` : null;
|
||||
const keys = Object.keys(interfaceAddresses);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
const arr = interfaceAddresses[keys[i]];
|
||||
for (var j = 0; j < arr.length; j++) {
|
||||
arr[j].cidr = getCIDR(arr[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return Object.assign({}, v, { cidr });
|
||||
});
|
||||
return acc;
|
||||
}, {});
|
||||
return interfaceAddresses;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
1
node.gyp
1
node.gyp
@ -132,7 +132,6 @@
|
||||
'lib/internal/modules/esm/translators.js',
|
||||
'lib/internal/safe_globals.js',
|
||||
'lib/internal/net.js',
|
||||
'lib/internal/os.js',
|
||||
'lib/internal/priority_queue.js',
|
||||
'lib/internal/process/esm_loader.js',
|
||||
'lib/internal/process/main_thread_only.js',
|
||||
|
@ -1,32 +0,0 @@
|
||||
// Flags: --expose-internals
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const getCIDRSuffix = require('internal/os').getCIDRSuffix;
|
||||
|
||||
const specs = [
|
||||
// valid
|
||||
['128.0.0.0', 'ipv4', 1],
|
||||
['255.0.0.0', 'ipv4', 8],
|
||||
['255.255.255.128', 'ipv4', 25],
|
||||
['255.255.255.255', 'ipv4', 32],
|
||||
['ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', 'ipv6', 128],
|
||||
['ffff:ffff:ffff:ffff::', 'ipv6', 64],
|
||||
['ffff:ffff:ffff:ff80::', 'ipv6', 57],
|
||||
// invalid
|
||||
['255.0.0.1', 'ipv4', null],
|
||||
['255.255.9.0', 'ipv4', null],
|
||||
['255.255.1.0', 'ipv4', null],
|
||||
['ffff:ffff:43::', 'ipv6', null],
|
||||
['ffff:ffff:ffff:1::', 'ipv6', null]
|
||||
];
|
||||
|
||||
specs.forEach(([mask, protocol, expectedSuffix]) => {
|
||||
const actualSuffix = getCIDRSuffix(mask, protocol);
|
||||
|
||||
assert.strictEqual(
|
||||
actualSuffix, expectedSuffix,
|
||||
`Mask: ${mask}, expected: ${expectedSuffix}, actual: ${actualSuffix}`
|
||||
);
|
||||
});
|
@ -130,8 +130,8 @@ switch (platform) {
|
||||
const expected = [{
|
||||
address: '127.0.0.1',
|
||||
netmask: '255.0.0.0',
|
||||
mac: '00:00:00:00:00:00',
|
||||
family: 'IPv4',
|
||||
mac: '00:00:00:00:00:00',
|
||||
internal: true,
|
||||
cidr: '127.0.0.1/8'
|
||||
}];
|
||||
@ -146,8 +146,8 @@ switch (platform) {
|
||||
const expected = [{
|
||||
address: '127.0.0.1',
|
||||
netmask: '255.0.0.0',
|
||||
mac: '00:00:00:00:00:00',
|
||||
family: 'IPv4',
|
||||
mac: '00:00:00:00:00:00',
|
||||
internal: true,
|
||||
cidr: '127.0.0.1/8'
|
||||
}];
|
||||
|
Loading…
x
Reference in New Issue
Block a user