-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net: port isIPv6() to JS #22673
net: port isIPv6() to JS #22673
Conversation
Porting isIPv6() to JS makes it 2x-5x faster and reduces some C++ code.
The matching needs to be case-insensitive to match the existing implementation's behavior. It might be a good idea to make the set of tests an array and loop through them to check both lower and upper case? |
Some more test cases in https://github.com/sindresorhus/ip-regex/blob/master/test.js, I suggest using them all. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making it explicit that additional compatibility is missing yet
I've added all the test cases in https://github.com/sindresorhus/ip-regex/blob/master/test.js. It seems no compatibility problems yet. |
You mean with |
Before the most recent push/commit, only [a-f] existed in the ipv6 regex, now there is [a-fA-F]. |
Regex has been updated to be case-insensitive
I just ran a small benchmark against all valid test cases and this is the outcome:
The invalid ones loose in the new implementation but comparing all together, they are on par. I guess most passed in IPs will be valid, so it should be a minor performance improvement. |
@silverwind I've tried both of them and found no performance difference between them. |
Is the "2x-5x faster" claim still accurate after the case insensitivity change? If not please update the commit message. |
The "2x-5x faster" claim is not accurate now because I changed the RegExp for some edge cases, which caused performance regression. I will update the commit message. Here is the benchmark statics for all the valid cases in
And here is the benchmark for invalid cases:
Most of valid cases (103/127) have 0% - 250% performance improvement or regression less than
|
I'm a bit worried about cases like |
Based on some quick testing, it's easily possible to outperform |
@mscdex it would be nice if you could post your port so the @nodejs/v8 team could have a look at it. Regular expressions should be pretty fast and ideally outperform any hand written version (even tough this regexp is definitely quite complex and that might slow it down). |
@BridgeAR I think it's just the complexity of the regexp that makes it slow and I'm not sure there's really much that can be done to simplify that. FWIW here are the results from my quick implementation (times are in milliseconds after Valid IPs ========= ┌─────────────────────────────────────────┬────────┬────────┬────────┐ │ (index) │ C │ regex │ js │ ├─────────────────────────────────────────┼────────┼────────┼────────┤ │ :: │ 104.99 │ 122.88 │ 13.59 │ │ 1:: │ 121.30 │ 157.24 │ 31.68 │ │ ::1 │ 106.27 │ 119.63 │ 28.02 │ │ 1::8 │ 124.48 │ 171.09 │ 35.36 │ │ 1::7:8 │ 140.38 │ 191.82 │ 52.82 │ │ 1:2:3:4:5:6:7:8 │ 209.41 │ 113.15 │ 141.58 │ │ 1:2:3:4:5:6::8 │ 201.60 │ 197.85 │ 118.95 │ │ 1:2:3:4:5:6:7:: │ 216.13 │ 114.23 │ 127.10 │ │ 1:2:3:4:5::7:8 │ 208.81 │ 247.02 │ 119.58 │ │ 1:2:3:4:5::8 │ 188.38 │ 236.46 │ 102.55 │ │ 1:2:3::8 │ 157.50 │ 279.56 │ 64.59 │ │ 1::4:5:6:7:8 │ 190.20 │ 274.56 │ 97.38 │ │ 1::6:7:8 │ 156.15 │ 231.53 │ 64.58 │ │ 1::3:4:5:6:7:8 │ 217.35 │ 281.14 │ 119.62 │ │ 1:2:3:4::6:7:8 │ 209.11 │ 307.03 │ 113.79 │ │ 1:2::4:5:6:7:8 │ 210.40 │ 319.13 │ 113.78 │ │ ::2:3:4:5:6:7:8 │ 207.82 │ 254.80 │ 121.21 │ │ 1:2::8 │ 141.52 │ 234.67 │ 48.23 │ │ 2001:0000:1234:0000:0000:C1C0:ABCD:0876 │ 345.88 │ 133.07 │ 197.32 │ │ 3ffe:0b00:0000:0000:0001:0000:0000:000a │ 297.20 │ 131.38 │ 197.07 │ │ FF02:0000:0000:0000:0000:0000:0000:0001 │ 314.07 │ 131.21 │ 197.33 │ │ 0000:0000:0000:0000:0000:0000:0000:0001 │ 297.37 │ 130.54 │ 197.06 │ │ 0000:0000:0000:0000:0000:0000:0000:0000 │ 297.13 │ 130.57 │ 197.09 │ │ ::ffff:192.168.1.26 │ 220.48 │ 163.77 │ 136.72 │ │ 2::10 │ 127.71 │ 184.49 │ 37.16 │ │ ff02::1 │ 130.10 │ 249.92 │ 40.08 │ │ fe80:: │ 124.96 │ 231.29 │ 30.93 │ │ 2002:: │ 136.17 │ 230.92 │ 30.53 │ │ 2001:db8:: │ 158.96 │ 325.86 │ 55.13 │ │ 2001:0db8:1234:: │ 189.24 │ 364.77 │ 77.69 │ │ ::ffff:0:0 │ 148.24 │ 173.17 │ 60.32 │ │ ::ffff:192.168.1.1 │ 209.00 │ 149.32 │ 114.03 │ │ 1:2:3:4::8 │ 166.60 │ 270.77 │ 85.19 │ │ 1::2:3:4:5:6:7 │ 200.38 │ 282.79 │ 125.01 │ │ 1::2:3:4:5:6 │ 185.61 │ 276.49 │ 102.28 │ │ 1::2:3:4:5 │ 170.20 │ 255.58 │ 85.08 │ │ 1::2:3:4 │ 154.09 │ 232.59 │ 67.91 │ │ 1::2:3 │ 139.20 │ 198.87 │ 50.74 │ │ ::2:3:4:5:6:7 │ 183.97 │ 246.43 │ 110.85 │ │ ::2:3:4:5:6 │ 169.02 │ 226.64 │ 87.64 │ │ ::2:3:4:5 │ 153.44 │ 206.18 │ 70.49 │ │ ::2:3:4 │ 137.46 │ 186.18 │ 53.30 │ │ ::2:3 │ 123.99 │ 143.63 │ 36.13 │ │ ::8 │ 105.85 │ 119.40 │ 18.96 │ │ 1:2:3:4:5:6:: │ 191.96 │ 194.81 │ 115.06 │ │ 1:2:3:4:5:: │ 177.55 │ 237.04 │ 98.01 │ │ 1:2:3:4:: │ 163.28 │ 260.28 │ 75.85 │ │ 1:2:3:: │ 148.89 │ 270.01 │ 58.68 │ │ 1:2:: │ 133.70 │ 226.33 │ 41.52 │ │ 1:2:3:4::7:8 │ 182.49 │ 296.36 │ 102.25 │ │ 1:2:3::7:8 │ 168.14 │ 304.92 │ 85.08 │ │ 1:2::7:8 │ 153.86 │ 259.05 │ 68.10 │ │ 1:2:3:4:5:6:1.2.3.4 │ 236.72 │ 205.76 │ 168.39 │ │ 1:2:3:4:5::1.2.3.4 │ 231.83 │ 249.03 │ 157.78 │ │ 1:2:3:4::1.2.3.4 │ 217.58 │ 276.43 │ 132.58 │ │ 1:2:3::1.2.3.4 │ 201.59 │ 285.80 │ 115.37 │ │ 1:2::1.2.3.4 │ 187.46 │ 242.44 │ 98.12 │ │ 1::1.2.3.4 │ 173.61 │ 181.59 │ 81.00 │ │ 1:2:3:4::5:1.2.3.4 │ 233.29 │ 280.06 │ 149.94 │ │ 1:2:3::5:1.2.3.4 │ 219.29 │ 292.66 │ 132.56 │ │ 1:2::5:1.2.3.4 │ 203.51 │ 249.80 │ 115.41 │ │ 1::5:1.2.3.4 │ 188.48 │ 189.06 │ 98.20 │ │ 1::5:11.22.33.44 │ 213.20 │ 203.87 │ 128.82 │ │ fe80::217:f2ff:254.7.237.98 │ 260.47 │ 325.60 │ 163.21 │ │ fe80::217:f2ff:fe07:ed62 │ 219.73 │ 358.52 │ 122.81 │ │ 2001:DB8:0:0:8:800:200C:417A │ 275.51 │ 124.09 │ 171.31 │ │ FF01:0:0:0:0:0:0:101 │ 233.01 │ 128.56 │ 151.63 │ │ 0:0:0:0:0:0:0:1 │ 206.71 │ 113.18 │ 137.11 │ │ 0:0:0:0:0:0:0:0 │ 206.51 │ 112.54 │ 137.10 │ │ 2001:DB8::8:800:200C:417A │ 261.57 │ 444.37 │ 140.59 │ │ FF01::101 │ 147.72 │ 284.17 │ 47.35 │ │ 0:0:0:0:0:0:13.1.68.3 │ 245.44 │ 209.22 │ 183.39 │ │ 0:0:0:0:0:FFFF:129.144.52.38 │ 300.97 │ 244.43 │ 208.77 │ │ ::13.1.68.3 │ 168.33 │ 133.96 │ 81.73 │ │ ::FFFF:129.144.52.38 │ 241.79 │ 164.71 │ 125.83 │ │ fe80:0000:0000:0000:0204:61ff:fe9d:f156 │ 292.77 │ 129.81 │ 194.41 │ │ fe80:0:0:0:204:61ff:fe9d:f156 │ 247.44 │ 120.96 │ 170.86 │ │ fe80::204:61ff:fe9d:f156 │ 219.87 │ 358.44 │ 122.93 │ │ fe80:0:0:0:204:61ff:254.157.241.86 │ 297.61 │ 274.10 │ 217.86 │ │ fe80::204:61ff:254.157.241.86 │ 270.35 │ 326.17 │ 169.52 │ │ fe80::1 │ 130.11 │ 250.16 │ 40.14 │ │ 2001:0db8:85a3:0000:0000:8a2e:0370:7334 │ 303.83 │ 128.38 │ 188.10 │ │ 2001:db8:85a3:0:0:8a2e:370:7334 │ 265.56 │ 133.41 │ 177.80 │ │ 2001:db8:85a3::8a2e:370:7334 │ 250.85 │ 454.60 │ 146.98 │ │ 2001:0db8:0000:0000:0000:0000:1428:57ab │ 303.57 │ 134.85 │ 194.02 │ │ 2001:0db8:0000:0000:0000::1428:57ab │ 292.05 │ 315.75 │ 168.12 │ │ 2001:0db8:0:0:0:0:1428:57ab │ 250.56 │ 119.46 │ 168.91 │ │ 2001:0db8:0:0::1428:57ab │ 234.68 │ 371.57 │ 132.49 │ │ 2001:0db8::1428:57ab │ 206.32 │ 426.23 │ 98.19 │ │ 2001:db8::1428:57ab │ 202.60 │ 381.51 │ 99.05 │ │ ::ffff:12.34.56.78 │ 205.66 │ 158.49 │ 116.78 │ │ ::ffff:0c22:384e │ 171.93 │ 200.39 │ 77.81 │ │ 2001:0db8:1234:0000:0000:0000:0000:0000 │ 303.56 │ 140.10 │ 193.02 │ │ 2001:0db8:1234:ffff:ffff:ffff:ffff:ffff │ 303.62 │ 127.86 │ 197.31 │ │ 2001:db8:a::123 │ 184.83 │ 315.79 │ 88.89 │ │ ::ffff:192.0.2.128 │ 209.78 │ 189.07 │ 115.82 │ │ ::ffff:c000:280 │ 167.47 │ 207.16 │ 73.64 │ │ a:b:c:d:e:f:f1:f2 │ 203.33 │ 114.21 │ 145.05 │ │ a:b:c::d:e:f:f1 │ 199.14 │ 319.08 │ 123.01 │ │ a:b:c::d:e:f │ 179.63 │ 313.40 │ 102.26 │ │ a:b:c::d:e │ 164.18 │ 286.54 │ 85.15 │ │ a:b:c::d │ 147.70 │ 270.88 │ 67.92 │ │ ::a │ 105.78 │ 118.93 │ 18.96 │ │ ::a:b:c │ 137.52 │ 166.53 │ 53.31 │ │ ::a:b:c:d:e:f:f1 │ 204.09 │ 215.27 │ 130.44 │ │ a:: │ 114.58 │ 159.12 │ 24.35 │ │ a:b:c:: │ 144.43 │ 266.94 │ 58.68 │ │ a:b:c:d:e:f:f1:: │ 205.68 │ 120.59 │ 135.83 │ │ a:bb:ccc:dddd:000e:00f:0f:: │ 245.34 │ 125.94 │ 163.73 │ │ 0:a:0:a:0:0:0:a │ 207.25 │ 111.74 │ 133.19 │ │ 0:a:0:0:a:0:0:a │ 205.60 │ 112.17 │ 138.50 │ │ 2001:db8:1:1:1:1:0:0 │ 225.03 │ 115.30 │ 150.84 │ │ 2001:db8:1:1:1:0:0:0 │ 225.14 │ 127.22 │ 150.87 │ │ 2001:db8:1:1:0:0:0:0 │ 225.01 │ 116.02 │ 150.81 │ │ 2001:db8:1:0:0:0:0:0 │ 225.07 │ 121.30 │ 150.88 │ │ 2001:db8:0:0:0:0:0:0 │ 225.09 │ 115.31 │ 150.82 │ │ 2001:0:0:0:0:0:0:0 │ 225.15 │ 114.55 │ 143.25 │ │ A:BB:CCC:DDDD:000E:00F:0F:: │ 316.86 │ 131.73 │ 163.70 │ │ 0:0:0:0:0:0:0:a │ 206.68 │ 115.84 │ 138.07 │ │ 0:0:0:0:a:0:0:0 │ 206.89 │ 113.80 │ 133.23 │ │ 0:0:0:a:0:0:0:0 │ 206.20 │ 114.81 │ 133.19 │ │ a:0:0:a:0:0:a:a │ 201.88 │ 112.33 │ 138.58 │ │ a:0:0:a:0:0:0:a │ 202.93 │ 112.28 │ 133.28 │ │ a:0:0:0:a:0:0:a │ 200.94 │ 111.77 │ 133.37 │ │ a:0:0:0:a:0:0:0 │ 204.12 │ 114.59 │ 133.45 │ │ a:0:0:0:0:0:0:0 │ 204.69 │ 116.73 │ 137.32 │ │ fe80::7:8%eth0 │ 150.91 │ 315.41 │ 61.33 │ │ fe80::7:8%1 │ 149.27 │ 312.47 │ 61.43 │ └─────────────────────────────────────────┴────────┴────────┴────────┘ Invalid IPs =========== ┌───────────────────────────────────────────────┬────────┬────────┬────────┐ │ (index) │ C │ regex │ js │ ├───────────────────────────────────────────────┼────────┼────────┼────────┤ │ 123 │ 107.27 │ 100.95 │ 31.27 │ │ │ 81.79 │ 56.41 │ 1.54 │ │ 1: │ 103.37 │ 98.31 │ 44.36 │ │ :1 │ 86.00 │ 68.70 │ 6.92 │ │ 11:36:12 │ 145.49 │ 308.47 │ 93.72 │ │ 02001:0000:1234:0000:0000:C1C0:ABCD:0876 │ 129.19 │ 173.17 │ 34.31 │ │ 2001:0000:1234:0000:00001:C1C0:ABCD:0876 │ 234.46 │ 566.64 │ 161.34 │ │ 2001:0000:1234: 0000:0000:C1C0:ABCD:0876 │ 202.93 │ 487.47 │ 107.36 │ │ 2001:1:1:1:1:1:255Z255X255Y255 │ 234.33 │ 490.28 │ 186.33 │ │ 3ffe:0b00:0000:0001:0000:0000:000a │ 270.34 │ 641.02 │ 219.12 │ │ FF02:0000:0000:0000:0000:0000:0000:0000:0001 │ 327.70 │ 663.40 │ 242.17 │ │ 3ffe:b00::1::a │ 177.28 │ 405.48 │ 112.95 │ │ ::1111:2222:3333:4444:5555:6666:: │ 268.61 │ 696.48 │ 216.10 │ │ 1:2:3::4:5::7:8 │ 185.83 │ 373.05 │ 144.11 │ │ 12345::6:7:8 │ 121.54 │ 173.22 │ 34.34 │ │ 1::5:400.2.3.4 │ 172.13 │ 254.93 │ 110.40 │ │ 1::5:260.2.3.4 │ 170.53 │ 244.84 │ 110.32 │ │ 1::5:256.2.3.4 │ 172.37 │ 245.16 │ 111.51 │ │ 1::5:1.256.3.4 │ 175.60 │ 225.32 │ 109.78 │ │ 1::5:1.2.256.4 │ 180.70 │ 247.88 │ 126.19 │ │ 1::5:1.2.3.256 │ 191.20 │ 283.91 │ 140.14 │ │ 1::5:300.2.3.4 │ 170.09 │ 254.72 │ 110.68 │ │ 1::5:1.300.3.4 │ 173.48 │ 224.03 │ 108.95 │ │ 1::5:1.2.300.4 │ 180.61 │ 244.66 │ 126.24 │ │ 1::5:1.2.3.300 │ 190.32 │ 281.23 │ 140.46 │ │ 1::5:900.2.3.4 │ 175.02 │ 253.75 │ 111.08 │ │ 1::5:1.900.3.4 │ 173.30 │ 223.19 │ 108.82 │ │ 1::5:1.2.900.4 │ 181.95 │ 245.83 │ 126.27 │ │ 1::5:1.2.3.900 │ 190.46 │ 281.19 │ 140.31 │ │ 1::5:300.300.300.300 │ 176.92 │ 253.94 │ 110.50 │ │ 1::5:3000.30.30.30 │ 178.17 │ 269.77 │ 109.80 │ │ 1::400.2.3.4 │ 157.34 │ 212.07 │ 86.74 │ │ 1::260.2.3.4 │ 156.04 │ 213.57 │ 86.98 │ │ 1::256.2.3.4 │ 158.18 │ 214.06 │ 87.10 │ │ 1::1.256.3.4 │ 160.41 │ 183.66 │ 85.66 │ │ 1::1.2.256.4 │ 167.70 │ 205.65 │ 102.65 │ │ 1::1.2.3.256 │ 178.39 │ 242.69 │ 114.22 │ │ 1::300.2.3.4 │ 161.56 │ 212.28 │ 87.57 │ │ 1::1.300.3.4 │ 160.95 │ 181.44 │ 85.48 │ │ 1::1.2.300.4 │ 166.15 │ 204.39 │ 102.67 │ │ 1::1.2.3.300 │ 179.66 │ 240.90 │ 114.21 │ │ 1::900.2.3.4 │ 159.57 │ 212.12 │ 86.96 │ │ 1::1.900.3.4 │ 160.21 │ 181.42 │ 85.49 │ │ 1::1.2.900.4 │ 169.03 │ 204.44 │ 102.65 │ │ 1::1.2.3.900 │ 174.93 │ 241.35 │ 114.26 │ │ 1::300.300.300.300 │ 163.26 │ 212.21 │ 87.52 │ │ 1::3000.30.30.30 │ 164.91 │ 228.57 │ 85.73 │ │ ::400.2.3.4 │ 140.56 │ 177.84 │ 65.34 │ │ ::260.2.3.4 │ 139.61 │ 180.97 │ 65.37 │ │ ::256.2.3.4 │ 138.00 │ 181.11 │ 64.84 │ │ ::1.256.3.4 │ 141.30 │ 141.94 │ 64.15 │ │ ::1.2.256.4 │ 150.02 │ 161.87 │ 80.71 │ │ ::1.2.3.256 │ 154.56 │ 199.63 │ 89.90 │ │ ::300.2.3.4 │ 139.73 │ 177.67 │ 64.92 │ │ ::1.300.3.4 │ 140.13 │ 139.81 │ 64.07 │ │ ::1.2.300.4 │ 148.12 │ 159.46 │ 80.82 │ │ ::1.2.3.300 │ 157.94 │ 196.38 │ 90.14 │ │ ::900.2.3.4 │ 138.14 │ 177.79 │ 64.70 │ │ ::1.900.3.4 │ 139.94 │ 140.00 │ 64.09 │ │ ::1.2.900.4 │ 147.25 │ 159.50 │ 80.90 │ │ ::1.2.3.900 │ 153.76 │ 196.45 │ 89.83 │ │ ::300.300.300.300 │ 144.33 │ 178.03 │ 65.24 │ │ ::3000.30.30.30 │ 143.73 │ 194.24 │ 63.86 │ │ 2001:DB8:0:0:8:800:200C:417A:221 │ 311.96 │ 563.52 │ 228.97 │ │ FF01::101::2 │ 168.69 │ 340.05 │ 88.21 │ │ 1111:2222:3333:4444::5555: │ 243.78 │ 668.97 │ 181.70 │ │ 1111:2222:3333::5555: │ 217.78 │ 599.97 │ 141.46 │ │ 1111:2222::5555: │ 190.33 │ 501.53 │ 111.30 │ │ 1111::5555: │ 164.45 │ 342.44 │ 82.17 │ │ ::5555: │ 124.35 │ 199.43 │ 54.38 │ │ ::: │ 109.17 │ 96.14 │ 28.28 │ │ 1111: │ 120.43 │ 174.08 │ 43.78 │ │ : │ 85.49 │ 67.59 │ 3.08 │ │ :1111:2222:3333:4444::5555 │ 98.09 │ 68.60 │ 6.92 │ │ :1111:2222:3333::5555 │ 95.99 │ 68.12 │ 6.92 │ │ :1111:2222::5555 │ 93.57 │ 67.79 │ 6.92 │ │ :1111::5555 │ 91.56 │ 68.20 │ 6.92 │ │ :::5555 │ 112.35 │ 98.14 │ 28.04 │ │ 1.2.3.4:1111:2222:3333:4444::5555 │ 183.07 │ 91.70 │ 27.16 │ │ 1.2.3.4:1111:2222:3333::5555 │ 183.36 │ 91.61 │ 27.16 │ │ 1.2.3.4:1111:2222::5555 │ 183.27 │ 92.03 │ 27.16 │ │ 1.2.3.4:1111::5555 │ 173.17 │ 91.85 │ 27.17 │ │ 1.2.3.4::5555 │ 170.07 │ 92.14 │ 27.16 │ │ 1.2.3.4:: │ 163.74 │ 91.98 │ 27.16 │ │ fe80:0000:0000:0000:0204:61ff:254.157.241.086 │ 336.63 │ 674.15 │ 298.03 │ │ ldkfj │ 98.44 │ 68.05 │ 17.42 │ │ 2001::FFD3::57ab │ 192.44 │ 348.30 │ 86.92 │ │ 2001:db8:85a3::8a2e:37023:7334 │ 237.04 │ 672.99 │ 165.11 │ │ 2001:db8:85a3::8a2e:370k:7334 │ 244.03 │ 656.18 │ 166.42 │ │ 1:2:3:4:5:6:7:8:9 │ 218.16 │ 377.23 │ 191.17 │ │ 1::2::3 │ 142.96 │ 198.58 │ 73.18 │ │ 1:::3:4:5 │ 131.28 │ 146.52 │ 49.65 │ │ 1:2:3::4:5:6:7:8:9 │ 230.79 │ 399.85 │ 181.36 │ │ ::ffff:2.3.4 │ 167.77 │ 258.94 │ 107.14 │ │ ::ffff:257.1.2.3 │ 165.81 │ 281.25 │ 96.90 │ │ ::ffff:12345678901234567890.1.26 │ 161.34 │ 299.28 │ 75.87 │ │ 2001:0000:1234:0000:0000:C1C0:ABCD:0876 0 │ 344.39 │ 666.44 │ 245.23 │ └───────────────────────────────────────────────┴────────┴────────┴────────┘ Yes, there are some cases where the regex beats the simple js implementation and it's possible the js code could be improved more, but it still beats calling out to C in every input tested. Here is the code I used to produce the results (using node v10.9.0): function hexval(c) {
if (c - 48 < 10) return c - 48;
c |= 32;
if (c - 97 < 6) return c - 97 + 10;
return -1;
}
function isdigit(c) {
return c >= 48 && c <= 57;
}
function validate4(src, p) {
var v;
var j;
var ch;
for (v = 0, j = 0; j < 3 && p < src.length && isdigit(ch = src.charCodeAt(p)); ++j, ++p)
v = 10 * v + ch - 48;
if (j === 0 || (j > 1 && src.charCodeAt(p - j) === 48/*'0'*/) || v > 255) return 0;
if (p < src.length && src.charCodeAt(p) !== 46/*'.'*/) return 0;
++p;
for (v = 0, j = 0; j < 3 && p < src.length && isdigit(ch = src.charCodeAt(p)); ++j, ++p)
v = 10 * v + ch - 48;
if (j === 0 || (j > 1 && src.charCodeAt(p - j) === 48/*'0'*/) || v > 255) return 0;
if (p < src.length && src.charCodeAt(p) !== 46/*'.'*/) return 0;
++p;
for (v = 0, j = 0; j < 3 && p < src.length && isdigit(ch = src.charCodeAt(p)); ++j, ++p)
v = 10 * v + ch - 48;
if (j === 0 || (j > 1 && src.charCodeAt(p - j) === 48/*'0'*/) || v > 255) return 0;
if (p < src.length && src.charCodeAt(p) !== 46/*'.'*/) return 0;
++p;
for (v = 0, j = 0; j < 3 && p < src.length && isdigit(ch = src.charCodeAt(p)); ++j, ++p)
v = 10 * v + ch - 48;
if (j === 0 || (j > 1 && src.charCodeAt(p - j) === 48/*'0'*/) || v > 255) return 0;
if (p === src.length) return 1;
return 0;
}
function validate6(src) {
var p = 0;
var v;
var j;
var ch;
var brk = -1;
var d;
if (src.length === 0) return 0;
if (src.charCodeAt(p) === 58/*':'*/ && (++p === src.length || src.charCodeAt(p) !== 58/*':'*/)) return 0;
for (var i = 0; ; ++i) {
if (src.charCodeAt(p) === 58/*':'*/ && brk < 0) {
brk = i;
if (++p === src.length) break;
if (i === 7) return 0;
continue;
}
for (v = 0, j = 0; j < 4 && p < src.length && (d = hexval(src.charCodeAt(p))) >= 0; ++j, ++p)
v = 16 * v + d;
if (j < 4 && p < src.length && src.charCodeAt(p) === 37/*'%'*/) break;
if (j === 0) return 0;
if (p === src.length && (brk >= 0 || i === 7)) break;
if (i === 7) return 0;
ch = src.charCodeAt(p);
if (ch !== 58/*':'*/) {
if (ch !== 46/*'.'*/ || (i < 6 && brk < 0)) return 0;
if (validate4(src, p - j) <= 0)
return 0;
break;
}
++p;
}
return 1;
}
// IPv4 Segment
const v4Seg = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
const v4Str = `(${v4Seg}[.]){3}${v4Seg}`;
const IPv4Reg = new RegExp(`^${v4Str}$`);
// IPv6 Segment
const v6Seg = '(?:[0-9a-fA-F]{1,4})';
const IPv6Reg = new RegExp('^(' +
`(?:${v6Seg}:){7}(?:${v6Seg}|:)|` +
`(?:${v6Seg}:){6}(?:${v4Str}|:${v6Seg}|:)|` +
`(?:${v6Seg}:){5}(?::${v4Str}|(:${v6Seg}){1,2}|:)|` +
`(?:${v6Seg}:){4}(?:(:${v6Seg}){0,1}:${v4Str}|(:${v6Seg}){1,3}|:)|` +
`(?:${v6Seg}:){3}(?:(:${v6Seg}){0,2}:${v4Str}|(:${v6Seg}){1,4}|:)|` +
`(?:${v6Seg}:){2}(?:(:${v6Seg}){0,3}:${v4Str}|(:${v6Seg}){1,5}|:)|` +
`(?:${v6Seg}:){1}(?:(:${v6Seg}){0,4}:${v4Str}|(:${v6Seg}){1,6}|:)|` +
`(?::((?::${v6Seg}){0,5}:${v4Str}|(?::${v6Seg}){1,7}|:))` +
')(%[0-9a-zA-Z]{1,})?$');
const v6 = [
'::',
'1::',
'::1',
'1::8',
'1::7:8',
'1:2:3:4:5:6:7:8',
'1:2:3:4:5:6::8',
'1:2:3:4:5:6:7::',
'1:2:3:4:5::7:8',
'1:2:3:4:5::8',
'1:2:3::8',
'1::4:5:6:7:8',
'1::6:7:8',
'1::3:4:5:6:7:8',
'1:2:3:4::6:7:8',
'1:2::4:5:6:7:8',
'::2:3:4:5:6:7:8',
'1:2::8',
'2001:0000:1234:0000:0000:C1C0:ABCD:0876',
'3ffe:0b00:0000:0000:0001:0000:0000:000a',
'FF02:0000:0000:0000:0000:0000:0000:0001',
'0000:0000:0000:0000:0000:0000:0000:0001',
'0000:0000:0000:0000:0000:0000:0000:0000',
'::ffff:192.168.1.26',
'2::10',
'ff02::1',
'fe80::',
'2002::',
'2001:db8::',
'2001:0db8:1234::',
'::ffff:0:0',
'::ffff:192.168.1.1',
'1:2:3:4::8',
'1::2:3:4:5:6:7',
'1::2:3:4:5:6',
'1::2:3:4:5',
'1::2:3:4',
'1::2:3',
'::2:3:4:5:6:7',
'::2:3:4:5:6',
'::2:3:4:5',
'::2:3:4',
'::2:3',
'::8',
'1:2:3:4:5:6::',
'1:2:3:4:5::',
'1:2:3:4::',
'1:2:3::',
'1:2::',
'1:2:3:4::7:8',
'1:2:3::7:8',
'1:2::7:8',
'1:2:3:4:5:6:1.2.3.4',
'1:2:3:4:5::1.2.3.4',
'1:2:3:4::1.2.3.4',
'1:2:3::1.2.3.4',
'1:2::1.2.3.4',
'1::1.2.3.4',
'1:2:3:4::5:1.2.3.4',
'1:2:3::5:1.2.3.4',
'1:2::5:1.2.3.4',
'1::5:1.2.3.4',
'1::5:11.22.33.44',
'fe80::217:f2ff:254.7.237.98',
'fe80::217:f2ff:fe07:ed62',
'2001:DB8:0:0:8:800:200C:417A',
'FF01:0:0:0:0:0:0:101',
'0:0:0:0:0:0:0:1',
'0:0:0:0:0:0:0:0',
'2001:DB8::8:800:200C:417A',
'FF01::101',
'0:0:0:0:0:0:13.1.68.3',
'0:0:0:0:0:FFFF:129.144.52.38',
'::13.1.68.3',
'::FFFF:129.144.52.38',
'fe80:0000:0000:0000:0204:61ff:fe9d:f156',
'fe80:0:0:0:204:61ff:fe9d:f156',
'fe80::204:61ff:fe9d:f156',
'fe80:0:0:0:204:61ff:254.157.241.86',
'fe80::204:61ff:254.157.241.86',
'fe80::1',
'2001:0db8:85a3:0000:0000:8a2e:0370:7334',
'2001:db8:85a3:0:0:8a2e:370:7334',
'2001:db8:85a3::8a2e:370:7334',
'2001:0db8:0000:0000:0000:0000:1428:57ab',
'2001:0db8:0000:0000:0000::1428:57ab',
'2001:0db8:0:0:0:0:1428:57ab',
'2001:0db8:0:0::1428:57ab',
'2001:0db8::1428:57ab',
'2001:db8::1428:57ab',
'::ffff:12.34.56.78',
'::ffff:0c22:384e',
'2001:0db8:1234:0000:0000:0000:0000:0000',
'2001:0db8:1234:ffff:ffff:ffff:ffff:ffff',
'2001:db8:a::123',
'::ffff:192.0.2.128',
'::ffff:c000:280',
'a:b:c:d:e:f:f1:f2',
'a:b:c::d:e:f:f1',
'a:b:c::d:e:f',
'a:b:c::d:e',
'a:b:c::d',
'::a',
'::a:b:c',
'::a:b:c:d:e:f:f1',
'a::',
'a:b:c::',
'a:b:c:d:e:f:f1::',
'a:bb:ccc:dddd:000e:00f:0f::',
'0:a:0:a:0:0:0:a',
'0:a:0:0:a:0:0:a',
'2001:db8:1:1:1:1:0:0',
'2001:db8:1:1:1:0:0:0',
'2001:db8:1:1:0:0:0:0',
'2001:db8:1:0:0:0:0:0',
'2001:db8:0:0:0:0:0:0',
'2001:0:0:0:0:0:0:0',
'A:BB:CCC:DDDD:000E:00F:0F::',
'0:0:0:0:0:0:0:a',
'0:0:0:0:a:0:0:0',
'0:0:0:a:0:0:0:0',
'a:0:0:a:0:0:a:a',
'a:0:0:a:0:0:0:a',
'a:0:0:0:a:0:0:a',
'a:0:0:0:a:0:0:0',
'a:0:0:0:0:0:0:0',
'fe80::7:8%eth0',
'fe80::7:8%1'
];
const v6not = [
'',
'1:',
':1',
'11:36:12',
'02001:0000:1234:0000:0000:C1C0:ABCD:0876',
'2001:0000:1234:0000:00001:C1C0:ABCD:0876',
'2001:0000:1234: 0000:0000:C1C0:ABCD:0876',
'2001:1:1:1:1:1:255Z255X255Y255',
'3ffe:0b00:0000:0001:0000:0000:000a',
'FF02:0000:0000:0000:0000:0000:0000:0000:0001',
'3ffe:b00::1::a',
'::1111:2222:3333:4444:5555:6666::',
'1:2:3::4:5::7:8',
'12345::6:7:8',
'1::5:400.2.3.4',
'1::5:260.2.3.4',
'1::5:256.2.3.4',
'1::5:1.256.3.4',
'1::5:1.2.256.4',
'1::5:1.2.3.256',
'1::5:300.2.3.4',
'1::5:1.300.3.4',
'1::5:1.2.300.4',
'1::5:1.2.3.300',
'1::5:900.2.3.4',
'1::5:1.900.3.4',
'1::5:1.2.900.4',
'1::5:1.2.3.900',
'1::5:300.300.300.300',
'1::5:3000.30.30.30',
'1::400.2.3.4',
'1::260.2.3.4',
'1::256.2.3.4',
'1::1.256.3.4',
'1::1.2.256.4',
'1::1.2.3.256',
'1::300.2.3.4',
'1::1.300.3.4',
'1::1.2.300.4',
'1::1.2.3.300',
'1::900.2.3.4',
'1::1.900.3.4',
'1::1.2.900.4',
'1::1.2.3.900',
'1::300.300.300.300',
'1::3000.30.30.30',
'::400.2.3.4',
'::260.2.3.4',
'::256.2.3.4',
'::1.256.3.4',
'::1.2.256.4',
'::1.2.3.256',
'::300.2.3.4',
'::1.300.3.4',
'::1.2.300.4',
'::1.2.3.300',
'::900.2.3.4',
'::1.900.3.4',
'::1.2.900.4',
'::1.2.3.900',
'::300.300.300.300',
'::3000.30.30.30',
'2001:DB8:0:0:8:800:200C:417A:221',
'FF01::101::2',
'1111:2222:3333:4444::5555:',
'1111:2222:3333::5555:',
'1111:2222::5555:',
'1111::5555:',
'::5555:',
':::',
'1111:',
':',
':1111:2222:3333:4444::5555',
':1111:2222:3333::5555',
':1111:2222::5555',
':1111::5555',
':::5555',
'1.2.3.4:1111:2222:3333:4444::5555',
'1.2.3.4:1111:2222:3333::5555',
'1.2.3.4:1111:2222::5555',
'1.2.3.4:1111::5555',
'1.2.3.4::5555',
'1.2.3.4::',
'fe80:0000:0000:0000:0204:61ff:254.157.241.086',
'123',
'ldkfj',
'2001::FFD3::57ab',
'2001:db8:85a3::8a2e:37023:7334',
'2001:db8:85a3::8a2e:370k:7334',
'1:2:3:4:5:6:7:8:9',
'1::2::3',
'1:::3:4:5',
'1:2:3::4:5:6:7:8:9',
'::ffff:2.3.4',
'::ffff:257.1.2.3',
'::ffff:12345678901234567890.1.26',
'2001:0000:1234:0000:0000:C1C0:ABCD:0876 0',
'02001:0000:1234:0000:0000:C1C0:ABCD:0876'
];
const { isIPv6 } = require('net');
const n = 1e6;
var results;
function timeIP(ip) {
var diff_C = process.hrtime();
for (var i = 0; i < n; ++i)
isIPv6(ip);
diff_C = process.hrtime(diff_C);
var diff_regex = process.hrtime();
for (var i = 0; i < n; ++i)
IPv6Reg.test(ip);
diff_regex = process.hrtime(diff_regex);
var diff_js = process.hrtime();
for (var i = 0; i < n; ++i)
validate6(ip);
diff_js = process.hrtime(diff_js);
results[ip] = {
C: (diff_C[0] * 1000 + diff_C[1] / 1e6).toFixed(2),
regex: (diff_regex[0] * 1000 + diff_regex[1] / 1e6).toFixed(2),
js: (diff_js[0] * 1000 + diff_js[1] / 1e6).toFixed(2),
};
}
console.log('Valid IPs');
console.log('=========');
results = Object.create(null);
v6.forEach(timeIP);
console.table(results);
console.log('Invalid IPs');
console.log('===========');
results = Object.create(null);
v6not.forEach(timeIP);
console.table(results); |
CI before landing: https://ci.nodejs.org/job/node-test-pull-request/17113/ |
Landed in 8e73594 |
Porting isIPv6() to JS makes it 10%-250% faster in most cases and reduces some C++ code. This change also adds tests for some edge cases. PR-URL: #22673 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Roman Reiss <[email protected]>
Porting isIPv6() to JS makes it 10%-250% faster in most cases and reduces some C++ code. This change also adds tests for some edge cases. PR-URL: #22673 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Roman Reiss <[email protected]>
Porting
isIPv6()
to JS makes it 10%-250% faster in most cases and reduces some C++ code. This change also adds tests for some edge cases.Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes