我必须读取并解析太大而无法加载到内存中的.pcap文件。我目前正在离线模式下使用嗅探
sniff(offline=file_in, prn=customAction, store=0)
使用大致如下的customAction函数:
customAction(packet):
global COUNT
COUNT = COUNT + 1
# do some other stuff that takes practically 0 time
目前处理数据包的速度太慢。我已经在'驱动程序中使用子进程'程序在不同内核上同时在多个文件上运行此脚本,但我确实需要提高单核性能。
我尝试使用pypy并且对使用pypy的性能比使用python3(anaconda)的性能低10%感到失望。
使用pypy运行50k数据包的平均时间为52.54秒
使用python3运行50k数据包的平均时间是56.93秒
有什么方法可以加快速度吗?
编辑:下面是cProfile的结果,因为你可以看到代码在被分析时有点慢,但所有的时间都花在了做事上。
66054791 function calls (61851423 primitive calls) in 85.482 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
957/1 0.017 0.000 85.483 85.483 {built-in method builtins.exec}
1 0.001 0.001 85.483 85.483 parser-3.py:1(<module>)
1 0.336 0.336 83.039 83.039 sendrecv.py:542(sniff)
50001 0.075 0.000 81.693 0.002 utils.py:817(recv)
50001 0.379 0.000 81.618 0.002 utils.py:794(read_packet)
795097/50003 3.937 0.000 80.140 0.002 base_classes.py:195(__call__)
397549/50003 6.467 0.000 79.543 0.002 packet.py:70(__init__)
397545/50000 1.475 0.000 76.451 0.002 packet.py:616(dissect)
397397/50000 0.817 0.000 74.002 0.001 packet.py:598(do_dissect_payload)
397545/200039 6.908 0.000 49.511 0.000 packet.py:580(do_dissect)
199083 0.806 0.000 32.319 0.000 dns.py:144(getfield)
104043 1.023 0.000 22.996 0.000 dns.py:127(decodeRR)
397548 0.343 0.000 15.059 0.000 packet.py:99(init_fields)
397549 6.043 0.000 14.716 0.000 packet.py:102(do_init_fields)
6673299/6311213 6.832 0.000 13.259 0.000 packet.py:215(__setattr__)
3099782/3095902 5.785 0.000 8.197 0.000 copy.py:137(deepcopy)
3746538/2335718 4.181 0.000 6.980 0.000 packet.py:199(setfieldval)
149866 1.885 0.000 6.678 0.000 packet.py:629(guess_payload_class)
738212 5.730 0.000 6.311 0.000 fields.py:675(getfield)
1756450 3.393 0.000 5.521 0.000 fields.py:78(getfield)
49775 0.200 0.000 5.401 0.000 dns.py:170(decodeRR)
1632614 2.275 0.000 4.591 0.000 packet.py:191(__getattr__)
985050/985037 1.720 0.000 4.229 0.000 {built-in method builtins.hasattr}
326681/194989 0.965 0.000 2.876 0.000 packet.py:122(add_payload)
...
编辑2:完整代码示例:
from scapy.all import *
from scapy.utils import PcapReader
import time, sys, logging
COUNT = 0
def customAction(packet):
global COUNT
COUNT = COUNT + 1
file_temp = sys.argv[1]
path = '/'.join(file_temp.split('/')[:-2])
file_in = '/'.join(file_temp.split('/')[-2:])
name = file_temp.split('/')[-1:][0].split('.')[0]
os.chdir(path)
q_output_file = 'processed/q_' + name + '.csv'
a_output_file = 'processed/a_' + name + '.csv'
log_file = 'log/' + name + '.log'
logging.basicConfig(filename=log_file, level=logging.DEBUG)
t0=time.time()
sniff(offline=file_in, prn=customAction, lfilter=lambda x:x.haslayer(DNS), store=0)
t1=time.time()
logging.info("File '{}' took {:.2f} seconds to parse {} packets.".format(name, t1-t0, COUNT))
答案 0 :(得分:1)
似乎scapy导致PyPy的JIT预热时间很长,但是如果你运行的时间足够久,JIT仍在工作。以下是我得到的结果(在Linux 64上):
size of .pcap CPython time PyPy time
2MB 4.9s 7.3s
5MB 15.3s 9.1s
15MB 1m15s 21s
答案 1 :(得分:0)
我认为简短的回答是,Scapy只是慢下来。我尝试用sniff()或PcapReader扫描pcap文件,而不对数据包做任何事情。这个过程从我的SSD读取的速度低于3MB / s,CPU使用率为100%。还有其他用于Python的pcap阅读器库。我建议尝试其中一个。