Javascript 具有IP地址的节点位计算
我在Node中制作了一个DNS工具,我想知道如何使用按位优化Javascript 具有IP地址的节点位计算,javascript,node.js,bit-manipulation,Javascript,Node.js,Bit Manipulation,我在Node中制作了一个DNS工具,我想知道如何使用按位优化toLong()的性能?我已经包含了一些伪代码供参考 var _parser = function (ip) { return ip.split('.').map(function (i) { return i | 0; }); }, _isIPv4 = function (ip) { var i, isValid = true, octets = _parser(ip); if (octets.length
toLong()
的性能?我已经包含了一些伪代码供参考
var _parser = function (ip) {
return ip.split('.').map(function (i) {
return i | 0;
});
},
_isIPv4 = function (ip) {
var i, isValid = true, octets = _parser(ip);
if (octets.length !== 4) {
isValid = false;
}
octets.forEach(function (octet) {
if (octet < 0 || octet > 255) {
isValid = false;
}
});
return isValid;
};
toLong: function (ip) {
var i, converted, octets = _parser(ip);
if (!_isIPv4(ip)) {
throw 'Invalid IPv4 address!';
}
converted = 0;
for (i = 0; i < octets.length; i++) {
converted += octets[i] * Math.pow(256, (3 - i));
}
return converted;
};
var\u解析器=函数(ip){
返回ip.split('.').map(函数(i){
返回i | 0;
});
},
_isIPv4=功能(ip){
变量i,isValid=true,八位字节=_解析器(ip);
如果(八位字节长度!==4){
isValid=false;
}
八位字节。forEach(函数(八位字节){
如果(八位组<0 | |八位组>255){
isValid=false;
}
});
返回有效;
};
托龙:功能(ip){
变量i,已转换,八位字节=_解析器(ip);
如果(!\u isIPv4(ip)){
抛出“无效IPv4地址!”;
}
换算为0;
对于(i=0;i
给你:
编辑2:这是原始解决方案,性能约为2倍:
var p256 = [Math.pow(256, 3), Math.pow(256, 2), 256, 1];
var cache = {};
var newToLongCache = function(ip) {
var octets = _parser(ip);
var converted = 0;
for (var i = 0; i < octets.length; i++) {
var val = octets[i];
if (cache[val] == null) {
cache[val] = {};
}
if (cache[val][i] == null) {
cache[val][i] = val * p256[i];
}
converted += cache[val][i];
}
return converted;
};
var unrolledMultiplicationLongNoBitwise = function(ip) {
var octets = ip.split('.');
if (octets.length !== 4) throw "Invalid IPv4 address!";
octets[0] = octets[0] | 0;
octets[1] = octets[1] | 0;
octets[2] = octets[2] | 0;
octets[3] = octets[3] | 0;
if ((octets[0] < 0 || octets[0] > 255) ||
(octets[1] < 0 || octets[1] > 255) ||
(octets[2] < 0 || octets[2] > 255) ||
(octets[3] < 0 || octets[3] > 255)) {
throw 'Invalid IPv4 address!';
}
return (octets[0] * 16777216) + (octets[1] * 65536) +
(octets[2] * 256) + octets[3];
};
var p256=[Math.pow(256,3),Math.pow(256,2),256,1];
var cache={};
var newToLongCache=函数(ip){
变量八位字节=_解析器(ip);
var=0;
对于(变量i=0;i
这是更新的展开解决方案,没有按位运算符(相同的5x性能):
var unrolled multiplicationLongNobitWise=函数(ip){
var八位字节=ip.split('.');
如果(octets.length!==4)抛出“无效IPv4地址!”;
八位位组[0]=八位位组[0]| 0;
八位位组[1]=八位位组[1]| 0;
八位位组[2]=八位位组[2]| 0;
八位位组[3]=八位位组[3]| 0;
if((八位字节[0]<0 | |八位字节[0]>255)||
(八位字节[1]<0 | |八位字节[1]>255)||
(八位字节[2]<0 | |八位字节[2]>255)||
(八位字节[3]<0 | |八位字节[3]>255)){
抛出“无效IPv4地址!”;
}
返回(八位字节[0]*16777216)+(八位字节[1]*65536)+
(八位组[2]*256)+八位组[3];
};
我真的建议展开这些循环并放弃函数调用。我在@imsky:创建的jsPerf中添加了一个修订版,看起来比原来快了5倍
var unrolledLong = function(ip) {
var octets = ip.split('.');
if (octets.length !== 4) throw "Invalid IPv4 address!";
octets[0] = octets[0] | 0;
octets[1] = octets[1] | 0;
octets[2] = octets[2] | 0;
octets[3] = octets[3] | 0;
if ((octets[0] < 0 || octets[0] > 255) ||
(octets[1] < 0 || octets[1] > 255) ||
(octets[2] < 0 || octets[2] > 255) ||
(octets[3] < 0 || octets[3] > 255)) {
throw 'Invalid IPv4 address!';
}
// The >>> 0 calls will force the number back to an unsigned value.
return octets[3] +
((octets[2] << 8) >>> 0) +
((octets[1] << 16) >>> 0) +
((octets[0] << 24) >>> 0);
};
var unrolled long=函数(ip){
var八位字节=ip.split('.');
如果(octets.length!==4)抛出“无效IPv4地址!”;
八位位组[0]=八位位组[0]| 0;
八位位组[1]=八位位组[1]| 0;
八位位组[2]=八位位组[2]| 0;
八位位组[3]=八位位组[3]| 0;
if((八位字节[0]<0 | |八位字节[0]>255)||
(八位字节[1]<0 | |八位字节[1]>255)||
(八位字节[2]<0 | |八位字节[2]>255)||
(八位字节[3]<0 | |八位字节[3]>255)){
抛出“无效IPv4地址!”;
}
//>>>0调用将强制将数字恢复为无符号值。
返回八位字节[3]+
((八位组[2]>>0)+
((八位组[1]>>0)+
((八位组[0]>>0);
};
如果按位计算有点奇怪,也可以使用乘法:
var unrolledLong = function(ip) {
var octets = ip.split('.');
if (octets.length !== 4) throw "Invalid IPv4 address!";
octets[0] = octets[0] | 0;
octets[1] = octets[1] | 0;
octets[2] = octets[2] | 0;
octets[3] = octets[3] | 0;
if ((octets[0] < 0 || octets[0] > 255) ||
(octets[1] < 0 || octets[1] > 255) ||
(octets[2] < 0 || octets[2] > 255) ||
(octets[3] < 0 || octets[3] > 255)) {
throw 'Invalid IPv4 address!';
}
// The >>> 0 calls will force the number back to an unsigned value.
return octets[3] +
(octets[2] * 0x100) +
(octets[1] * 0x10000) +
(octets[0] * 0x1000000);
};
var unrolled long=函数(ip){
var八位字节=ip.split('.');
如果(octets.length!==4)抛出“无效IPv4地址!”;
八位位组[0]=八位位组[0]| 0;
八位位组[1]=八位位组[1]| 0;
八位位组[2]=八位位组[2]| 0;
八位位组[3]=八位位组[3]| 0;
if((八位字节[0]<0 | |八位字节[0]>255)||
(八位字节[1]<0 | |八位字节[1]>255)||
(八位字节[2]<0 | |八位字节[2]>255)||
(八位字节[3]<0 | |八位字节[3]>255)){
抛出“无效IPv4地址!”;
}
//>>>0调用将强制将数字恢复为无符号值。
返回八位字节[3]+
(八位字节[2]*0x100)+
(八位字节[1]*0x10000)+
(八位字节[0]*0x1000000);
};
只是在玩弄优化:
function( ip ){
var octets = ip.split( '.' );
if( ( octets.length !== 4 ) ||
( ( octets[0] |= 0 ) & ~0xFF ) ||
( ( octets[1] |= 0 ) & ~0xFF ) ||
( ( octets[2] |= 0 ) & ~0xFF ) ||
( ( octets[3] |= 0 ) & ~0xFF ) ){
throw new Error( 'Invalid IPv4 address!' );
}
return ( octets[3] ) |
( octets[2] << 8 ) |
( octets[1] << 16 ) |
( octets[0] * 0x1000000 );
}
功能(ip){
var八位字节=ip.split('.');
if((八位字节长度!==4)||
((八位组[0]|=0)和~0xFF)||
((八位组[1]|=0)和~0xFF)||
((八位组[2]|=0)和~0xFF)||
((八位组[3]|=0)和~0xFF)){
抛出新错误(“无效IPv4地址!”);
}
返回(八位字节[3])|
(八位位组[2]+1用于基准测试。我会看看你做了什么,然后想出一些办法。谢谢!我有很多关于位的阅读。我很感谢你的反馈!我认为数学是错的。当给出unrolled long('172.2.6.139'))
它返回-1409153397
。这是我在尝试按位使用时遇到的问题。我想我可能必须先转换为二进制。@GrayFox检查我的修订答案,我想它会像你预期的那样工作。@GrayFox也修复了我的问题。我花了一些时间来理解为什么展开会更快。我想,因为作为一名学生,我在软件开发中,你学到的第一件事是不要重复自己,编写预期会失败的测试,然后重新迭代。我从这些基准测试中学到了很多东西,并找到了这个伟大的来源: