python - 如何提高 scapy 读取大文件的性能

标签 python performance scapy pcap pypy

我必须读取并解析太大而无法加载到内存中的 .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 的结果,您可以看到代码在分析时有点慢,但所有时间都花在 scapy 上。

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))

最佳答案

似乎 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

关于python - 如何提高 scapy 读取大文件的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38601091/

相关文章:

python - Scapy Dot11ReassoReq

python - Scapy BPF 过滤器不工作

python - 无法导入 Scapy ssl_tls 库

javascript - V8中JS中对象属性的缓慢删除

python - 从 pip 转移到诗歌,现在 pytest-cov 不会收集覆盖率数据

python - numba - 打字错误 : cannot determine Numba type of <class 'builtin_function_or_method' >

python - 在 for 循环中返回一次迭代?

C#:对于小型操作,ObjectTrackingEnabled = false 值得吗?

performance - 处理大额交易: any time/memory tradeoffs?

python - 在多个文件中搜索多个正则表达式,然后输出每个匹配项及其各自的文件