节点 – 使用IP地址进行按位计算

我已经在Node中创build了一个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 !== 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; }; 

我真的build议展开这些循环,并放弃函数调用。 我添加了对@imsky创build的jsPerf的修订: http ://jsperf.com/node-bitwise-calculations-with-ip-addresses/6看起来这比原来快了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); }; 

如果这个按位math有点奇怪,你也可以使用乘法:

 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); }; 

在这里,你去: http : //jsperf.com/node-bitwise-calculations-with-ip-addresses

编辑2:这是原来的解决scheme,约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; }; 

这是更新的展开解决scheme,没有按位运算符(相同的5倍性能):

  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]; }; 

只是玩弄优化这个:

 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 ); }