2016-07-26 3 views
1

Мне нужно прочитать и проанализировать файлы .pcap, которые слишком велики для загрузки в память. Я в настоящее время использую сопение в автономном режимеКак улучшить работу scapy при чтении больших файлов

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 менее 10% лучше, чем использование python3 (anaconda).

Среднее время выполнения 50k пакетов с использованием PyPy составляет 52,54 секунды

Среднее время выполнения 50k пакетов с использованием python3 в 56.93 секунд

Есть ли способ, чтобы ускорить процесс?

EDIT: Ниже приведен результат 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) 
... 

EDIT 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

Согласно https://gist.github.com/dpifke/2244911 defaultdict не должен быть причиной того, что pypy медленнее, чем python3. По мере устранения кажется, что очевидным виновником является scapy + pypy. – deltap

+0

Можете ли вы привести конкретный пример PyPy? Если это действительно медленнее (даже для больших файлов), это может быть из-за некоторой недостающей оптимизации внутри самого PyPy, которую мы могли бы исправить. –

+0

После некоторой настройки кода я могу теперь получить 10% -ное улучшение скорости выполнения, используя pypy. – deltap

ответ

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 
+0

Сколько пакетов в этих файлах? Мои файлы с 50 000 пакетов составляют примерно 8 Мбайт, а время работы значительно больше, чем у вас. – deltap

+0

Я видел в номерах журналов ближе к десятку «пакетов». Опять же, это означает, что вы не говорите нам все, что нам нужно знать. Просьба привести полный пример; это может быть некоторый публичный файл .pcap, доступный в Интернете. –

0

Я думаю, что короткий ответ, что Scapy просто медленно, как ад. Я попробовал просто сканировать файл pcap с помощью sniff() или PcapReader и ничего не делать с пакетами. Этот процесс читал менее 3 Мбайт/с от моего SSD, а использование ЦП составляло 100%. В Python есть другие библиотеки чтения pcap. Я бы предложил экспериментировать с одним из них.

+0

Было бы полезно, если бы вы упомянули или предложили конкретные библиотеки. – charlesreid1