Estoy trabajando con un programa de análisis bastante simple en PLY, y una de mis reglas adquiere la siguiente forma:PLY: ¿analiza rápidamente listas largas de elementos?
def p_things(p):
'''
things : thing things
things : thing
'''
p[0] = [p[1]]
if len(p) == 3:
p[0] += p[2]
archivos de entrada son generalmente simples listas de thing
s, por lo que el análisis en sí no es compleja . Sin embargo, algunos de mis archivos de entrada son muy grandes (más de 100.000 líneas con bastante regularidad y más de 1.000.000 en casos extremos). En la creación de perfiles (a través de cProfile and pstats), la mayor parte del tiempo de ejecución se utiliza para llamadas repetidas al p_things
, presumiblemente, una llamada para cada elemento en una lista things
.
¿Hay alguna manera de reducir este tiempo, o una forma más eficiente de estructurar esta regla? La mayoría de las respuestas que he visto hasta ahora (y la información de los compiladores canónicos que he encontrado) han enumerado este método como la forma generalmente aceptada de construir una lista de elementos analizables, sin importar la longitud.
Esto no es un problema de análisis en sí mismo - en su método original 'p [0] + = p [2]' se ejecuta linealmente a la longitud de la lista cada vez que agrega una nueva 'cosa', por lo que se analiza una lista toma tiempo cuadrático, mientras que en su nuevo método, al agregar un nuevo elemento 'p [0] .append (p [2])' se ejecuta el tiempo constante amortizado, por lo que, en general, el análisis de la lista requiere tiempo lineal. – math4tots
Secundario: divida su regla en dos, digamos una con el sufijo '_iter' y la otra con' _end'. Como los documentos de PLY ya lo recomiendan, la declaración de selección simplemente duplica el trabajo ya realizado por el mismo analizador para distinguir entre los dos casos en la regla de producción. Esto ahorrará algo de cálculo, pero no está relacionado con la observación de una mejora en la eficiencia. –
Si tiene un archivo de datos con un encabezado complejo que requiere PLY y una cola enorme de datos muy simples, entonces considere dividir la entrada en dos partes. Pase el primero (pequeño) a PLY, y maneje el segundo en una iteración simple por línea, que divide cada línea de forma léxica (por ejemplo, si es una tupla de 3 coordenadas). –