Чтение SNMP из OID с тремя библиотеками дает разное время выполнения

Я уже пользовалась easysnmp читать SNMP OID, но я выбрал pysnmp библиотека сейчас, потому что easysnmp не поддерживал asyncio архитектура в Python3.

Рассматриваемая проблема заключается в том, что pysnmp Слишком медленнее, чем другие библиотеки:

pysnmp:

from pysnmp.hlapi import *
import time

t = time.time()
iterator = getCmd(SnmpEngine(),
                  CommunityData('public'),
                  UdpTransportTarget(('192.168.1.120', 161)),
                  ContextData(),
                  ObjectType(ObjectIdentity("1.3.6.1.2.1.33.1.2.7.0")))

errorIndication, errorStatus, errorIndex, varBinds = next(iterator)

if errorIndication:  # SNMP engine errors
    print(errorIndication)
else:
    if errorStatus:  # SNMP agent errors
        print('%s at %s' % (
            errorStatus.prettyPrint(),
            varBinds[int(errorIndex)-1] if errorIndex else '?'))
    else:
        for varBind in varBinds:  # SNMP response contents
            print(' = '.join([x.prettyPrint() for x in varBind]))


print(time.time() - t, 's') 

Из:

SNMPv2-SMI::mib-2.33.1.2.7.0 = 21
0.15317177772521973 s

easysnmp

from easysnmp import snmp_get
import time

if __name__ == '__main__':
    t = time.time()
    response = snmp_get(
        '1.3.6.1.2.1.33.1.2.7.0', hostname='192.168.1.120',
        community='public', version=1
    )
    print(response.value)
    print(time.time() - t, 's')

Из:

21
0.0063724517822265625 s

gosnmp

func elapsed(what string) func() {
    start := time.Now()
    fmt.Println("start")
    return func() {
        fmt.Printf("%s took %v\n", what, time.Since(start))
    }
}

func snmpRead() {
    g.Default.Target = "192.168.1.120"
    err := g.Default.Connect()
    if err != nil {
        log.Fatalf("Connect() err: %v", err)
    }
    defer g.Default.Conn.Close()

    oids := []string{"1.3.6.1.2.1.33.1.2.7.0"}
    result, err2 := g.Default.Get(oids) // Get() accepts up to g.MAX_OIDS
    if err2 != nil {
        log.Fatalf("Get() err: %v", err2)
    }

    for i, variable := range result.Variables {
        fmt.Printf("%d: oid: %s ", i, variable.Name)

        switch variable.Type {
        case g.OctetString:
            fmt.Printf("string: %s\n", string(variable.Value.([]byte)))
        default:
            fmt.Printf("number: %d\n", g.ToBigInt(variable.Value))
        }
    }
}

func main() {
    defer elapsed("snmp")()
    snmpRead()
}

Из:

start
0: oid: .1.3.6.1.2.1.33.1.2.7.0 number: 21
snmp took 3.668148ms

В 30 раз быстрее чем pysnmp


Мне нужно асинхронное выполнение которого go-routine населенный asyncio в Python3.

Итак, означает ли это, что я должен мигрировать из pysnmp в gosnmp?

1 ответ

Помните, что первый вызов pysnmp может занять гораздо больше времени по сравнению с последующими вызовами. Из-за отложенного импорта, индексации, возможной компиляции MIB и т. Д.

Поэтому, если ваш вариант использования состоит в том, чтобы выдавать много запросов SNMP от одного и того же процесса, я бы посоветовал принять это во внимание при измерении времени.

Другое дело, что последний (неизданный) pysnmp ввел асинхронные привязки для низкоуровневых подпрограмм SNMP, т.е. исключая механизм SNMP и все тяжелые механизмы, которые он задействует.

pysnmp.hlapi.v1arch.asyncio API должен быть очень похож на pysnmp.hlapi.v3arch.asyncio однако с точки зрения подписи он должен быть быстрее за счет отсутствия поддержки SNMPv3. Поддержка MIB все еще на месте, если вам это нужно.

Когда вы импортируете только pysnmp.hlapi.asyncio, вы эффективно получите pysnmp.hlapi.v3arch.asyncioтак что ладить v1arch вам нужно импортировать это явно.

Например, приведенный ниже скрипт (работающий под GitHub master pysnmp) может быть быстрее:

import asyncio
from pysnmp.hlapi.v1arch.asyncio import *


@asyncio.coroutine
def run():
    snmpDispatcher = SnmpDispatcher()

    iterator = getCmd(
        snmpDispatcher,
        CommunityData('public'),
        UdpTransportTarget(('192.168.1.120', 161)),
        ('1.3.6.1.2.1.33.1.2.7.0', None)
    )

    errorIndication, errorStatus, errorIndex, varBinds = yield from iterator

    if errorIndication:
        print(errorIndication)

    elif errorStatus:
        print('%s at %s' % (
            errorStatus.prettyPrint(),
            errorIndex and varBinds[int(errorIndex) - 1][0] or '?'
        )
              )
    else:
        for varBind in varBinds:
            print(' = '.join([x.prettyPrint() for x in varBind]))

    snmpDispatcher.transportDispatcher.closeDispatcher()


asyncio.get_event_loop().run_until_complete(run())
Другие вопросы по тегам