假设有一个192.168.54.0/24网络,如何快速分配一个可用ip,查找,添加,删除
192.168.54.0/24 可以使用 192.168.54.1-162.168.54.255 范围的ip,那么,就可以使用256个bit来表示某个ip是否已经被使用,在C#中,可以使用4个ulong来表示,于是
示例
C#
class FindIPTest{ public ulong[] array = new ulong[4] { ulong.MaxValue, ulong.MaxValue, ulong.MaxValue, 0 }; /// <summary> /// 查找网段内可用ip(/24) /// </summary> /// <param name="array">缓存数组</param> /// <param name="value">找到的值</param> /// <returns></returns> /// <exception cref="Exception">array length must be 4</exception> public bool Find(ulong[] array, out byte value) { value = 0; if (array.Length != 4) throw new Exception("array length must be 4"); //排除 .1 .255 .256 array[0] |= 0b1; array[3] |= (ulong)0b11 << 62; if (array[0] < ulong.MaxValue) value = Find(array[0], 0); else if (array[1] < ulong.MaxValue) value = Find(array[1], 1); else if (array[2] < ulong.MaxValue) value = Find(array[2], 2); else if (array[3] < ulong.MaxValue) value = Find(array[3], 3); return value > 0; } private byte Find(ulong group, byte index) { byte value = (byte)(index * 64); //每次对半开,也可以循环,循环稍微会慢3-4ns,常量值快一点 ulong _group = (group & uint.MaxValue); if (_group >= uint.MaxValue) { _group = group >> 32; value += 32; } group = _group; _group = (group & ushort.MaxValue); if (_group >= ushort.MaxValue) { _group = group >> 16; value += 16; } group = _group; _group = (group & byte.MaxValue); if (_group >= byte.MaxValue) { _group = group >> 8; value += 8; } group = _group; _group = (group & 0b1111); if (_group >= 0b1111) { _group = group >> 4; value += 4; } group = _group; _group = (group & 0b11); if (_group >= 0b11) { _group = group >> 2; value += 2; } group = _group; _group = (group & 0b1); if (_group >= 0b1) { value += 1; } value += 1; return value; } /// <summary> /// 是否存在一个ip /// </summary> /// <param name="group"></param> /// <param name="value"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public bool Exists(ulong[] array, byte value) { if (array.Length != 4) throw new Exception("array length must be 4"); int arrayIndex = value / 64; int length = value - arrayIndex * 64; return (array[arrayIndex] >> (length - 1) & 1) == 1; } /// <summary> /// 将一个ip(/24)设为已使用 /// </summary> /// <param name="array">缓存数组</param> /// <param name="value">值</param> public void Add(ulong[] array, byte value) { if (array.Length != 4) throw new Exception("array length must be 4"); int arrayIndex = value / 64; int length = value - arrayIndex * 64; array[arrayIndex] |= (ulong)1 << (length - 1); } /// <summary> /// 删除一个ip(/24),设为未使用 /// </summary> /// <param name="array"></param> /// <param name="value"></param> /// <exception cref="Exception"></exception> public void Delete(ulong[] array, byte value) { if (array.Length != 4) throw new Exception("array length must be 4"); int arrayIndex = value / 64; int length = value - arrayIndex * 64; array[arrayIndex] &= ~((ulong)1 << (length - 1)); }}测试
C#
[MemoryDiagnoser]public partial class Test{ [GlobalSetup] public void Startup(){} FindPoerTest t = new FindPoerTest(); [Benchmark] public void FindIP() { t.Find(t.array, out byte point); } [Benchmark] public void AddIP() { t.Add(t.array, 253); } [Benchmark] public void DeleteIP() { t.Delete(t.array, 253); } }基准
C#
BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19045.3208/22H2/2022Update)AMD Ryzen 3 2200G with Radeon Vega Graphics, 1 CPU, 4 logical and 4 physical cores.NET SDK=7.0.100 [Host] : .NET 7.0.0 (7.0.22.51805), X64 RyuJIT AVX2 [AttachedDebugger] DefaultJob : .NET 7.0.0 (7.0.22.51805), X64 RyuJIT AVX2| Method | Mean | Error | StdDev | Median | Allocated ||--------- |---------:|----------:|----------:|---------:|----------:|| FindIP | 8.246 ns | 0.1799 ns | 0.1595 ns | 8.303 ns | - || AddIP | 4.604 ns | 0.2598 ns | 0.7067 ns | 4.923 ns | - || DeleteIP | 4.837 ns | 0.1308 ns | 0.1701 ns | 4.873 ns | - |

支付宝微信扫一扫,打赏作者吧~
