【发布时间】:2017-10-30 22:33:57
【问题描述】:
我有一组大约 200,000 个 IP 地址和 10,000 个形式的子网 (1.1.1.1/24)。对于每个 IP 地址,我需要检查它是否属于这些子网之一,但由于它是一个如此大的数据集并且我的计算能力较低,因此我想要一个有效的实现。
在搜索时,我找到了一种方法(https://stackoverflow.com/a/820124/7995937):
from netaddr import IPNetwork, IPAddress
if IPAddress("192.168.0.1") in IPNetwork("192.168.0.0/24"):
print "Yay!"
但由于我必须循环超过 200,000 个 IP 地址,并且每个地址循环超过 10,000 个子网,我不确定这是否有效。 我的第一个疑问是,检查“IPNetwork() 中的 IPAddress()”只是线性扫描还是以某种方式优化?
我想出的另一个解决方案是列出 IP 子网中包含的所有 IP(大约 13,000,000 个 IP,没有重复),然后对其进行排序。如果我这样做,那么在我对 200,000 个 IP 地址的循环中,我只需要在更大的 IP 地址集上对每个 IP 进行二进制搜索。
for ipMasked in ipsubnets: # Here ipsubnets is the list of all subnets
setUnmaskedIPs = [str(ip) for ip in IPNetwork(ipMasked)]
ip_list = ip_list + setUnmaskedIPs
ip_list = list(set(ip_list)) # To eliminate duplicates
ip_list.sort()
然后我可以通过以下方式执行二进制搜索:
for ip in myIPList: # myIPList is the list of 200,000 IPs
if bin_search(ip,ip_list):
print('The ip is present')
这种方法比另一种更有效吗?或者还有其他更有效的方法来执行此任务吗?
【问题讨论】:
-
如前所述,最快的是使用集合。其他相关话题:stackoverflow.com/questions/5993621/…
-
将 IPv4 字符串转换为 32 位 int 很简单,所以如果我必须创建一个这样的库,我可能会在内部使用 int 和二进制运算符,这将非常有效。像往常一样,您应该首先测量是否真的存在性能问题。
标签: python performance ip cidr