我在python中有一个小程序,它收集探测请求并将ssids和mac发送到服务器。但几分钟后它会减慢我的电脑速度。我试图添加dict,以便我只在必要时才进行POST。 但问题仍然存在:几分钟后,我的电脑速度变慢了。我也尝试过覆盆子pi,结果是一样的。
请告诉我这里有什么问题。
这是代码
#!/usr/bin/env python
from scapy.all import *
import json
import requests
macSsid = {}
def handler(pkt):
url = 'http://10.10.10.10:3000/ssids'
headers = {'content-type': 'application/json'}
if pkt.haslayer(Dot11):
if pkt.type == 0 and pkt.subtype == 4:
if pkt.info :
print "Client MAC = %s probe request =%s" % (pkt.addr2, pkt.info)
if pkt.addr2 not in macSsid:
macSsid[pkt.addr2] = []
macSsid[pkt.addr2].append(pkt.info)
r = requests.post(url, data = json.dumps({"mac": pkt.addr2, "ssid": pkt.info }), headers = headers)
else:
if pkt.info not in macSsid[pkt.addr2]:
macSsid[pkt.addr2].append(pkt.info)
r = requests.post(url, data = json.dumps({"mac": pkt.addr2, "ssid": pkt.info }), headers = headers)
while 1:
try:
exc_info = sys.exc_info()
sniff(iface="mon0", prn = handler)
except Exception, err:
traceback.print_exception(*exc_info)
请告诉我这里有什么问题。
答案 0 :(得分:1)
我认为这是由这条线引起的:
if pkt.info not in macSsid[pkt.addr2]:
随着macSsid [pkt.addr2]引用的列表变大,在python列表上进行迭代搜索的成本变得非常高。这是一个列表,而不是字典,所以没有索引,python必须按顺序检查每个元素,直到找到匹配的元素,或者检查了列表中的每个元素。
我建议将其更改为字典以便更快地操作,
macSsid[pkt.addr2] = {}
macSsid[pkt.addr2][pkt.info] = 1 # the 1 is just a placeholder,
# so if you want to store e.g. a repeat count, this would allow it
在else子句中添加pkt.info时的相应更改。
更改为索引类型将允许基于索引的查找,而不是迭代列表。我相信Python中有索引列表类型,但我不太多使用它们,因为除了索引查找之外,指标或类似数据的额外存储一直是一个好处。
你的用例可能也夸大了这个效果,因为我怀疑你很有可能找不到pkt.info的匹配,所以每次搜索列表时,都要检查每一个在得出它不存在之前的要素。
考虑将前1000个元素添加到列表中的成本:每个新元素都需要在添加之前搜索前一个元素,仅需要对这些新元素进行50万次比较,不包括任何不重复的元素加。如果网络数据包使用顺序标识符而不是完全随机标识符,那么已经存在的元素可能需要检查超过统计平均值,这是大多数网络协议的情况。
另请注意,当列表不再完全适合CPU缓存时,这似乎会突然减慢。此时,您的性能通常会突然下降10倍到100倍,具体取决于您机器的规格。
这似乎影响计算机其余部分的原因是因为在等待每次内存提取操作完成时CPU被阻塞,并且常量内存提取操作会降低内存控制器的速度。运行你的python程序的核心将被完全阻止,你的内存总线将几乎饱和,导致其他应用程序看起来也很慢。
答案 1 :(得分:0)
您的程序使用了太多内存。这是因为您没有清除macSsid字典。如果您在使用它们后删除这些条目(使用del
),您的程序将使用更少的内存,从而停止减慢计算机速度。