Amazon Best VPN GoSearch

icono de página de OnWorks

perlperf - Online en la nube

Ejecute perlperf en el proveedor de alojamiento gratuito de OnWorks sobre Ubuntu Online, Fedora Online, emulador en línea de Windows o emulador en línea de MAC OS

Este es el comando perlperf que se puede ejecutar en el proveedor de alojamiento gratuito de OnWorks utilizando una de nuestras múltiples estaciones de trabajo en línea gratuitas, como Ubuntu Online, Fedora Online, emulador en línea de Windows o emulador en línea de MAC OS.

PROGRAMA:

NOMBRE


perlperf - Técnicas de optimización y rendimiento de Perl

DESCRIPCIÓN


Esta es una introducción al uso de técnicas de optimización y rendimiento que se pueden
se utiliza con especial referencia a los programas de Perl. Si bien muchos desarrolladores de Perl han llegado
de otros idiomas, y pueden utilizar sus conocimientos previos cuando sea apropiado, hay muchos
otras personas que podrían beneficiarse de algunos consejos específicos de Perl. Si quieres el
versión condensada, quizás el mejor consejo proviene del renombrado samurái japonés,
Miyamoto Musashi, quien dijo:

"No participar en actividades inútiles"

en el 1645.

Descripción


Quizás el error más común que cometen los programadores es intentar optimizar su código
antes de que un programa realmente haga algo útil, esta es una mala idea. No tiene sentido
tener un programa extremadamente rápido que no funciona. El primer trabajo es conseguir que un programa
correctamente hacer algo eficiente, (sin mencionar que se garantiza que el conjunto de pruebas esté completamente
funcional), y solo entonces considerar optimizarlo. Habiendo decidido optimizar lo existente
código de trabajo, hay varios pasos simples pero esenciales a considerar que son intrínsecos
a cualquier proceso de optimización.

ONE PASO OBLICUO
En primer lugar, debe establecer un tiempo de referencia para el código existente, qué tiempo necesita
ser confiable y repetible. Probablemente desee utilizar el "Benchmark" o
Módulos "Devel :: NYTProf", o algo similar, para este paso, o quizás el sistema Unix
Utilidad de "tiempo", lo que sea apropiado. Consulte la base de este documento para obtener una lista más extensa.
de módulos de evaluación comparativa y elaboración de perfiles, y se recomienda una lectura adicional.

ONE PASO ADELANTE
A continuación, habiendo examinado el programa para calientes puntos, (lugares donde el código parece ejecutarse
lentamente), cambie el código con la intención de que se ejecute más rápido. Usando la versión
El software de control, como "subversion", asegurará que ningún cambio sea irreversible. Es muy
fácil de manipular aquí y allá; no cambie demasiado a la vez o podría
no descubrir qué fragmento de código realmente fue la parte lenta.

OTRA FORMA PASO OBLICUO
No basta con decir: "eso hará que corra más rápido", hay que comprobarlo. Vuelva a ejecutar el
código bajo control de los módulos de evaluación comparativa o de creación de perfiles, desde el primer paso anterior,
y comprobar que el nuevo código ejecutó el mismo tarea in less time. Guarda tu trabajo y
repetir...

GENERAL LINEAS DIRECTRICES


Lo crítico al considerar el desempeño es recordar que no existe tal cosa como un
"Golden Bullet", por eso no hay reglas, solo pautas.

Está claro que el código en línea será más rápido que las llamadas a subrutinas o métodos,
porque hay menos gastos generales, pero este enfoque tiene la desventaja de ser menos
mantenible y tiene el costo de un mayor uso de memoria: no existe tal cosa como un
almuerzo gratis. Si está buscando un elemento en una lista, puede ser más eficiente
almacenar los datos en una estructura hash, y luego simplemente mirar para ver si la clave es
definido, en lugar de recorrer toda la matriz utilizando grep () por ejemplo. substr ()
puede ser (mucho) más rápido que grep () pero no tan flexible, por lo que tiene otra compensación para
acceso. Su código puede contener una línea que tarda 0.01 de segundo en ejecutarse, si usted
llámelo 1,000 veces, muy probablemente en un programa que analiza incluso archivos de tamaño mediano para
Por ejemplo, ya tiene un retraso de 10 segundos, en una sola ubicación de código, y si
llame a esa línea 100,000 veces, todo su programa se ralentizará a un rastreo insoportable.

Usar una subrutina como parte de su clasificación es una forma poderosa de obtener exactamente lo que desea,
pero normalmente será más lento que el incorporado alfabético "cmp" y numérico "<=>" ordenar
operadores. Es posible realizar varias pasadas sobre sus datos, creando índices para
hacer que la próxima clasificación sea más eficiente, y usar lo que se conoce como el "OM" (Orcish
Maniobra) para almacenar en caché las claves de clasificación por adelantado. La búsqueda de caché, aunque es una buena idea, puede
en sí mismo ser una fuente de desaceleración al imponer una doble pasada sobre los datos, una vez para configurar
la caché, y una vez para ordenar los datos. Usando "pack ()" para extraer la clave de clasificación requerida
en una cadena consistente puede ser una forma eficiente de construir una sola cadena para comparar,
en lugar de utilizar varias claves de clasificación, lo que hace posible utilizar el estándar, escrito
en "c" y rápido, la función "sort ()" de perl en la salida, y es la base de la "GRT"
(Transformada de Guttman Rossler). Algunas combinaciones de cadenas pueden ralentizar el "GRT", simplemente
siendo demasiado complejo para su propio bien.

Para las aplicaciones que utilizan backends de bases de datos, el espacio de nombres estándar "DBIx" ha intentado ayudar
con mantener las cosas nippy, sobre todo porque trata de No consultar la base de datos hasta que
último momento posible, pero siempre lea los documentos que vienen con las bibliotecas de su elección.
Entre los muchos problemas a los que se enfrentan los desarrolladores que tratan con bases de datos, se encuentran:
utilizar siempre marcadores de posición "SQL" y considerar la obtención previa de conjuntos de datos cuando esto podría
resultar ventajoso. Dividir un archivo grande asignando múltiples procesos al análisis
un solo archivo, por ejemplo, "POE", "subprocesos" o "fork" también puede ser una forma útil de optimizar
su uso de los recursos de "CPU" disponibles, aunque esta técnica está cargada de
problemas de concurrencia y exige una gran atención a los detalles.

Cada caso tiene una aplicación específica y una o más excepciones, y no hay
reemplazo para ejecutar algunas pruebas y averiguar qué método funciona mejor para su
entorno particular, esta es la razón por la que escribir un código óptimo no es una ciencia exacta, y por qué
Nos encanta usar Perl - TMTOWTDI.

PUNTOS DE REFERENCIA


A continuación, se muestran algunos ejemplos para demostrar el uso de las herramientas de evaluación comparativa de Perl.

Asignando y Desreferenciar Variables
Estoy seguro de que la mayoría de nosotros hemos visto un código que se parece (o peor) a esto:

if ($ obj -> {_ ref} -> {_ myscore}> = $ obj -> {_ ref} -> {_ yourscore}) {
...

Este tipo de código puede ser una auténtica monstruosidad de leer, además de ser muy sensible a los errores tipográficos,
y es mucho más claro desreferenciar la variable explícitamente. Estamos evitando el
problema de trabajar con técnicas de programación orientadas a objetos para encapsular variables
acceso a través de métodos, solo accesible a través de un objeto. Aquí solo estamos discutiendo el
implementación técnica de elección, y si esto tiene un efecto sobre el rendimiento. Podemos
ver si esta operación de eliminación de referencias tiene alguna sobrecarga poniendo código comparativo en
un archivo y ejecutando una prueba "Benchmark".

# desreferencia

#!/ usr / bin / perl

uso estricto
use advertencias;

utilizar Benchmark;

my $ ref = {
'ref' => {
_myscore => '100 + 1',
_yourscore => '102 - 1',
},
};

timethese (1000000, {
'directo' => sub {
my $ x = $ ref -> {ref} -> {_ myscore}. $ ref -> {ref} -> {_ yourscore};
},
'desreferencia' => sub {
my $ ref = $ ref -> {ref};
my $ myscore = $ ref -> {_ myscore};
my $ yourscore = $ ref -> {_ yourscore};
my $ x = $ myscore. $ yourcore;
},
});

Es esencial ejecutar cualquier medición de tiempo una cantidad suficiente de veces para que los números
establecerse en un promedio numérico, de lo contrario, cada ejecución fluctuará naturalmente debido a
variaciones en el entorno, para reducir el efecto de la contención por los recursos de "CPU" y
ancho de banda de la red, por ejemplo. Ejecutando el código anterior durante un millón de iteraciones, podemos
eche un vistazo a la salida del informe del módulo "Benchmark", para ver qué enfoque es el
más efectivo.

$> desreferencia de perl

Benchmark: sincronización de 1000000 iteraciones de desreferencia, directo ...
desreferencia: 2 segundos de reloj de pared (1.59 usr + 0.00 sys = 1.59 CPU) @ 628930.82 / s (n = 1000000)
directo: 1 segundo de reloj de pared (1.20 usr + 0.00 sys = 1.20 CPU) @ 833333.33 / s (n = 1000000)

La diferencia es evidente y el enfoque de desreferenciar es más lento. Mientras se las arreglaba
para ejecutar un promedio de 628,930 veces por segundo durante nuestra prueba, el enfoque directo
Se las arregló para ejecutar 204,403 veces adicionales, desafortunadamente. Desafortunadamente, porque hay
Hay muchos ejemplos de código escrito usando el acceso variable directo de múltiples capas, y
suele ser horrible. Sin embargo, es minuscully más rápido. La pregunta sigue siendo si
la ganancia mínima en realidad vale la pena la fatiga visual o la pérdida de capacidad de mantenimiento.

Buscar y reemplazar or tr
Si tenemos una cadena que necesita ser modificada, mientras que una expresión regular casi siempre será mucho
más flexible, "tr", una herramienta frecuentemente infrautilizada, aún puede ser útil. Un escenario podría ser
reemplace todas las vocales con otro carácter. La solución de expresiones regulares podría verse así:

$ str = ~ s / [aeiou] / x / g

La alternativa "tr" podría verse así:

$cadena =~ tr/aeiou//

Podemos poner eso en un archivo de prueba que podemos ejecutar para verificar qué enfoque es el más rápido,
usando una variable $ STR global para asignar a la variable "my $ str" para evitar perl
tratando de optimizar el trabajo notando que se asigna solo una vez.

# regex-transliterar

#!/ usr / bin / perl

uso estricto
use advertencias;

utilizar Benchmark;

my $ STR = "$$ - esto y aquello";

timethese (1000000, {
'sr' => sub {mi $ str = $ STR; $ str = ~ s / [aeiou] / x / g; return $ str; },
'tr' => sub { mi $str = $STR; $cadena =~ tr/aeiou//; devolver $cadena; },
});

Ejecutar el código nos da nuestros resultados:

$> perl regex-transliterate

Benchmark: cronometraje 1000000 iteraciones de sr, tr ...
sr: 2 segundos de reloj de pared (1.19 usr + 0.00 sys = 1.19 CPU) @ 840336.13 / s (n = 1000000)
tr: 0 segundos de reloj de pared (0.49 usr + 0.00 sys = 0.49 CPU) @ 2040816.33 / s (n = 1000000)

La versión "tr" es un claro ganador. Una solución es flexible, la otra es rápida y
es apropiadamente la elección del programador cuál usar.

Consulte los documentos de "Benchmark" para obtener más técnicas útiles.

PERFILANDO HERRAMIENTAS


Un fragmento de código un poco más grande proporcionará algo sobre lo que un generador de perfiles puede producir
estadísticas de informes más extensas. Este ejemplo utiliza el programa simplista "wordmatch"
que analiza un archivo de entrada dado y arroja un breve informe sobre el contenido.

# coincidencia de palabras

#!/ usr / bin / perl

uso estricto
use advertencias;

= head1 NAME

filewords: análisis de palabras del archivo de entrada

= head1 SINOPSIS

palabras de archivo -f nombre de archivo de entrada [-d]

= head1 DESCRIPCIÓN

Este programa analiza el nombre de archivo dado, especificado con C <-f>, y muestra un
simple análisis de las palabras que allí se encuentran. Utilice el interruptor C <-d> para habilitar
depurar mensajes.

= cortar

utilice FileHandle;
use Getopt :: Long;

my $ debug = 0;
mi $ archivo = '';

my $ resultado = GetOptions (
'debug' => \ $ debug,
'archivo = s' => \ $ archivo,
);
die ("argumentos inválidos") a menos que $ resultado;

a menos que (-f $ archivo) {
die ("Uso: $ 0 -f nombre de archivo [-d]");
}
my $ FH = FileHandle-> new ("<$ archivo") o muere ("no se puede abrir el archivo ($ archivo): $!");

my $ i_LINES = 0;
my $ i_WORDS = 0;
mi% cuenta = ();

my @lines = <$ FH>;
foreach my $ line (@lines) {
$ i_LINES ++;
$ línea = ~ s / \ n //;
mis @palabras = dividir (/ + /, $ línea);
my $ i_words = escalar (@palabras);
$ i_WORDS = $ i_WORDS + $ i_words;
debug ("línea: $ i_LINES proporcionando $ i_words palabras: @palabras");
my $ i_word = 0;
Foreach my $ word (@words) {
$ i_word ++;
$ count {$ i_LINES} {spec} + = coincidencias ($ i_word, $ word, '[^ a-zA-Z0-9]');
$ count {$ i_LINES} {solo} + = coincidencias ($ i_word, $ word, '^ [^ a-zA-Z0-9] + $');
$ count {$ i_LINES} {cons} + = coincidencias ($ i_word, $ word, '^ [(? i: bcdfghjklmnpqrstvwxyz)] + $');
$ count {$ i_LINES} {votos} + = coincidencias ($ i_word, $ word, '^ [(? i: aeiou)] + $');
$ count {$ i_LINES} {mayúsculas} + = coincidencias ($ i_word, $ word, '^ [(AZ)] + $');
}
}

imprimir informe (% de recuento);

sub coincidencias {
my $ i_wd = turno;
my $ palabra = turno;
my $ regex = shift;
my $ tiene = 0;

if ($ palabra = ~ / ($ expresión regular) /) {
$ tiene ++ si $ 1;
}

debug ("palabra: $ i_wd". ($ tiene? 'coincide con': 'no coincide'). "chars: / $ regex /");

return $ tiene;
}

subinforme {
mi% informe = @_;
my% rep;

foreach my $ line (keys% report) {
foreach my $ key (keys% {$ report {$ line}}) {
$ rep {$ key} + = $ report {$ line} {$ key};
}
}

my $ report = qq |
Informe de $ 0 para $ file:
líneas en archivo: $ i_LINES
palabras en archivo: $ i_WORDS
palabras con caracteres especiales (que no son palabras): $ i_spec
palabras con solo caracteres especiales (que no son palabras): $ i_only
palabras con solo consonantes: $ i_cons
palabras con solo letras mayúsculas: $ i_caps
palabras con solo vocales: $ i_vows
|;

return $ report;
}

depuración secundaria {
mi $ mensaje = turno;

if ($ debug) {
imprimir STDERR "DBG: $ mensaje \ n";
}
}

salida 0;

Desarrollo :: DProf
Este venerable módulo ha sido el estándar de facto para la creación de perfiles de código Perl durante más de
una década, pero ha sido reemplazado por una serie de otros módulos que nos han devuelto a
el siglo 21. Aunque se recomienda evaluar su herramienta entre las diversas
mencionado aquí y de la lista CPAN en la base de este documento, (y actualmente
Devel :: NYTProf parece ser el arma preferida (ver más abajo), echaremos un vistazo rápido a
la salida de Devel :: DProf primero, para establecer una línea de base para las herramientas de creación de perfiles de Perl. Ejecutar el
programa anterior bajo el control de "Devel :: DProf" usando el interruptor "-d" en el comando-
la línea.

$> perl -d: DProf palabra concordancia -f perl5db.pl

<... varias líneas recortadas ...>

informe wordmatch para perl5db.pl:
líneas en archivo: 9428
palabras en archivo: 50243
palabras con caracteres especiales (que no son palabras): 20480
palabras con solo caracteres especiales (que no son palabras): 7790
palabras con solo consonantes: 4801
palabras con solo letras mayúsculas: 1316
palabras con solo vocales: 1701

"Devel :: DProf" produce un archivo especial, llamado tmon.fuera de forma predeterminada, y este archivo se lee
por el programa "dprofpp", que ya está instalado como parte de "Devel :: DProf"
distribución. Si llama a "dprofpp" sin opciones, leerá el tmon.fuera archivo en
el directorio actual y producir un informe estadístico legible por humanos de la ejecución de su
programa. Tenga en cuenta que esto puede llevar un poco de tiempo.

$> dprofpp

Tiempo total transcurrido = 2.951677 segundos
Usuario + tiempo del sistema = 2.871677 segundos
Horarios exclusivos
% Tiempo ExclSec CumulS #Calls sec / call Csec / c Nombre
102. 2.945 3.003 251215 0.0000 0.0000 principal :: coincidencias
2.40 0.069 0.069 260643 0.0000 0.0000 principal :: depuración
1.74 0.050 0.050 1 0.0500 0.0500 principal :: informe
1.04 0.030 0.049 4 0.0075 0.0123 principal :: COMIENZO
0.35 0.010 0.010 3 0.0033 0.0033 Exportador :: as_heavy
0.35 0.010 0.010 7 0.0014 0.0014 IO :: Archivo :: BEGIN
0.00 - -0.000 1 - - Getopt :: Long :: FindOption
0.00 - -0.000 1 - - Símbolo :: COMIENZO
0.00 - -0.000 1 - - Fcntl :: COMIENZO
0.00 - -0.000 1 - - Fcntl :: bootstrap
0.00 - -0.000 1 - - advertencias :: BEGIN
0.00 - -0.000 1 - - IO :: bootstrap
0.00 - -0.000 1 - - Getopt :: Long :: ConfigDefaults
0.00 - -0.000 1 - - Getopt :: Long :: Configure
0.00 - -0.000 1 - - Símbolo :: gensym

"dprofpp" producirá informes bastante detallados sobre la actividad de "wordmatch"
programa. El reloj de pared, el usuario y el sistema, los tiempos están en la parte superior del análisis, y después
estas son las columnas principales que definen las que definen el informe. Consulte los documentos "dprofpp" para
detalles de las muchas opciones que admite.

Vea también "Apache :: DProf" que enlaza "Devel :: DProf" en "mod_perl".

Devel :: Profiler
Echemos un vistazo al mismo programa usando un generador de perfiles diferente: "Devel :: Profiler", un
reemplazo directo en Perl para "Devel :: DProf". El uso es ligeramente diferente en
que en lugar de utilizar la bandera especial "-d:", se introduce "Devel :: Profiler" directamente como
módulo utilizando "-M".

$> perl -MDevel :: Profiler wordmatch -f perl5db.pl

<... varias líneas recortadas ...>

informe wordmatch para perl5db.pl:
líneas en archivo: 9428
palabras en archivo: 50243
palabras con caracteres especiales (que no son palabras): 20480
palabras con solo caracteres especiales (que no son palabras): 7790
palabras con solo consonantes: 4801
palabras con solo letras mayúsculas: 1316
palabras con solo vocales: 1701

"Devel :: Profiler" genera un archivo tmon.out que es compatible con "dprofpp"
programa, ahorrando así la construcción de un programa lector de estadísticas dedicado. "dprofpp"
por tanto, el uso es idéntico al del ejemplo anterior.

$> dprofpp

Tiempo total transcurrido = 20.984 segundos
Usuario + tiempo del sistema = 19.981 segundos
Horarios exclusivos
% Tiempo ExclSec CumulS #Calls sec / call Csec / c Nombre
49.0 9.792 14.509 251215 0.0000 0.0001 main :: partidos
24.4 4.887 4.887 260643 0.0000 0.0000 principal :: depuración
0.25 0.049 0.049 1 0.0490 0.0490 principal :: informe
0.00 0.000 0.000 1 0.0000 0.0000 Getopt :: Long :: GetOptions
0.00 0.000 0.000 2 0.0000 0.0000 Getopt :: Long :: ParseOptionSpec
0.00 0.000 0.000 1 0.0000 0.0000 Getopt :: Long :: FindOption
0.00 0.000 0.000 1 0.0000 0.0000 IO :: Archivo :: nuevo
0.00 0.000 0.000 1 0.0000 0.0000 IO :: Mango :: nuevo
0.00 0.000 0.000 1 0.0000 0.0000 Símbolo :: gensym
0.00 0.000 0.000 1 0.0000 0.0000 IO :: Archivo :: abrir

Curiosamente, obtenemos resultados ligeramente diferentes, lo que se debe principalmente a que el algoritmo
que genera el informe es diferente, aunque el formato del archivo de salida supuestamente fue
idéntico. Los tiempos transcurridos, del usuario y del sistema muestran claramente el tiempo que tardó
"Devel :: Profiler" para ejecutar su propia ejecución, pero las listas de columnas parecen más precisas
de alguna manera que los que teníamos antes de "Devel :: DProf". La cifra del 102% tiene
desaparecido, por ejemplo. Aquí es donde tenemos que utilizar las herramientas a nuestra disposición, y
reconocer sus pros y contras, antes de usarlos. Curiosamente, el número de llamadas para
cada subrutina es idéntica en los dos informes, son los porcentajes los que difieren. Como
el autor de "Devel :: Proviler" escribe:

... ejecutando HTML :: Template's test suite bajo Devel :: DProf muestra output ()
sin tomar NINGÚN tiempo, pero Devel :: Profiler muestra que alrededor del 10% del tiempo está en la salida ().
No sé en quién confiar, pero mi instinto me dice que algo anda mal
Desarrollo :: DProf. HTML :: Template :: output () es una gran rutina que se requiere
cada prueba. De cualquier manera, hay que arreglar algo.

Tu caso es distinto.

Vea también "Devel :: Apache :: Profiler" que enlaza "Devel :: Profiler" en "mod_perl".

Devel :: SmallProf
El generador de perfiles "Devel :: SmallProf" examina el tiempo de ejecución de su programa Perl y produce un
lista línea por línea para mostrar cuántas veces se llamó a cada línea y cuánto tiempo cada línea
tomó para ejecutar. Se llama proporcionando la conocida bandera "-d" a Perl en tiempo de ejecución.

$> perl -d: Coincidencia de palabras SmallProf -f perl5db.pl

<... varias líneas recortadas ...>

informe wordmatch para perl5db.pl:
líneas en archivo: 9428
palabras en archivo: 50243
palabras con caracteres especiales (que no son palabras): 20480
palabras con solo caracteres especiales (que no son palabras): 7790
palabras con solo consonantes: 4801
palabras con solo letras mayúsculas: 1316
palabras con solo vocales: 1701

"Devel :: SmallProf" escribe su salida en un archivo llamado pequeñoprof.fuera, por defecto. El
El formato del archivo se ve así:

:

Cuando el programa ha terminado, la salida puede examinarse y clasificarse utilizando cualquier estándar
utilidades de filtrado de texto. Algo como lo siguiente puede ser suficiente:

$> gato smallprof.out | grep \ d *: | sort -k3 | tac | cabeza -n20

251215 1.65674 7.68000 75: if ($ palabra = ~ / ($ regex) /) {
251215 0.03264 4.40000 79: debug ("palabra: $ i_wd". ($ Tiene? 'Coincide':
251215 0.02693 4.10000 81: return $ has;
260643 0.02841 4.07000 128: if ($ debug) {
260643 0.02601 4.04000 126: my $ message = shift;
251215 0.02641 3.91000 73: mi $ tiene = 0;
251215 0.03311 3.71000 70: my $ i_wd = shift;
251215 0.02699 3.69000 72: my $ regex = shift;
251215 0.02766 3.68000 71: my $ word = shift;
50243 0.59726 1.00000 59: $ recuento {$ i_LINES} {contras} =
50243 0.48175 0.92000 61: $ count {$ i_LINES} {spec} =
50243 0.00644 0.89000 56: mis $ i_cons = coincidencias ($ i_word, $ palabra,
50243 0.48837 0.88000 63: $ recuento {$ i_LINES} {mayúsculas} =
50243 0.00516 0.88000 58: my $ i_caps = coincidencias ($ i_word, $ word, '^ [(A-
50243 0.00631 0.81000 54: my $ i_spec = coincidencias ($ i_word, $ word, '[^ a-
50243 0.00496 0.80000 57: mis $ i_vows = coincidencias ($ i_word, $ palabra,
50243 0.00688 0.80000 53: $ i_word ++;
50243 0.48469 0.79000 62: $ count {$ i_LINES} {only} =
50243 0.48928 0.77000 60: $ count {$ i_LINES} {votos} =

50243 0.00683 0.75000 55: my $ i_only = coincidencias ($ i_word, $ word, '^ [^ a-
Inmediatamente puede ver un enfoque ligeramente diferente a los módulos de perfilado de subrutinas,
y comenzamos a ver exactamente qué línea de código está tomando más tiempo. Esa línea de expresiones regulares
parece un poco sospechoso, por ejemplo. Recuerde que se supone que estas herramientas
Usados ​​juntos, no existe una única mejor manera de perfilar su código, debe usar el mejor
herramientas para el trabajo.

Consulte también "Apache :: SmallProf" que enlaza "Devel :: SmallProf" en "mod_perl".

Desarrollo :: FastProf
"Devel :: FastProf" es otro perfilador de líneas de Perl. Esto fue escrito con miras a obtener
un perfilador de líneas más rápido, de lo que es posible con, por ejemplo, "Devel :: SmallProf", porque es
escrito en "C". Para usar "Devel :: FastProf", proporcione el argumento "-d" a Perl:

$> perl -d: Coincidencia de palabras FastProf -f perl5db.pl

<... varias líneas recortadas ...>

informe wordmatch para perl5db.pl:
líneas en archivo: 9428
palabras en archivo: 50243
palabras con caracteres especiales (que no son palabras): 20480
palabras con solo caracteres especiales (que no son palabras): 7790
palabras con solo consonantes: 4801
palabras con solo letras mayúsculas: 1316
palabras con solo vocales: 1701

"Devel :: FastProf" escribe estadísticas en el archivo fastprof.fuera en el directorio actual.
El archivo de salida, que se puede especificar, se puede interpretar utilizando el "fprofpp"
programa de línea de comandos.

$> fprofpp | cabeza -n20

El formato de salida # fprofpp es:
# nombre de archivo: recuento de tiempo de línea: fuente
wordmatch: 75 3.93338 251215: if ($ word = ~ / ($ regex) /) {
wordmatch: 79 1.77774 251215: debug ("word: $ i_wd". ($ has? 'matches': 'does not match'). "chars: / $ regex /");
wordmatch: 81 1.47604 251215: return $ has;
wordmatch: 126 1.43441 260643: my $ message = shift;
wordmatch: 128 1.42156 260643: if ($ debug) {
wordmatch: 70 1.36824 251215: my $ i_wd = turno;
wordmatch: 71 1.36739 251215: my $ word = shift;
wordmatch: 72 1.35939 251215: my $ regex = shift;

Inmediatamente podemos ver que el número de veces que se ha llamado a cada línea es idéntico a
la salida "Devel :: SmallProf", y la secuencia es solo ligeramente diferente según
el orden de la cantidad de tiempo que cada línea tardó en ejecutarse, "if ($ debug) {" y "my
$ message = shift; ", por ejemplo. Las diferencias en los tiempos reales registrados pueden estar en
el algoritmo utilizado internamente, o podría deberse a limitaciones de recursos del sistema o
contención.

Consulte también DBIx :: Profile, que perfilará las consultas de la base de datos que se ejecutan bajo "DBIx :: *"
espacio de nombres

Devel :: NYTProf
"Devel :: NYTProf" es el Next generación de AHSS del generador de perfiles de código Perl, solucionando muchas deficiencias en
otras herramientas e implementando muchas características interesantes. En primer lugar, se puede utilizar como
línea perfilador, un bloquear o subrutina perfilador, todo a la vez. También puede utilizar sub-
resolución de microsegundos (100ns) en sistemas que proporcionan "clock_gettime ()". Puede ser
iniciado y detenido incluso por el programa que se está perfilando. Es una entrada de una línea al perfil.
Aplicaciones "mod_perl". Está escrito en "c" y probablemente sea el generador de perfiles más rápido.
disponible para Perl. La lista de lo cool continúa. Suficiente de eso, veamos cómo
Funciona, simplemente use el conocido interruptor "-d" para conectarlo y ejecutar el código.

$> perl -d: NYTProf palabra concordancia -f perl5db.pl

informe wordmatch para perl5db.pl:
líneas en archivo: 9427
palabras en archivo: 50243
palabras con caracteres especiales (que no son palabras): 20480
palabras con solo caracteres especiales (que no son palabras): 7790
palabras con solo consonantes: 4801
palabras con solo letras mayúsculas: 1316
palabras con solo vocales: 1701

"NYTProf" generará una base de datos de informes en el archivo nytprof.fuera por defecto. Humano
Se pueden generar informes legibles desde aquí utilizando el "nytprofhtml" (HTML
salida) y programas "nytprofcsv" (salida CSV). Hemos utilizado el sistema Unix "html2text"
utilidad para convertir el nytprof / index.html archivo por conveniencia aquí.

$> html2text nytprof / index.html

Índice de perfil de rendimiento
Para wordmatch
Ejecutar el viernes 26 de septiembre 13:46:39 2008
Reportado el viernes 26 de septiembre 13:47:23 2008

Las 15 mejores subrutinas: ordenadas por tiempo exclusivo
| Llamadas | P | F | Incluido | Exclusivo | Subrutina |
| | | | Tiempo | tiempo | |
| 251215 | 5 | 1 | 13.09263 | 10.47692 | principal :: | partidos |
| 260642 | 2 | 1 | 2.71199 | 2.71199 | principal :: | depuración |
| 1 | 1 | 1 | 0.21404 | 0.21404 | principal :: | informe |
| 2 | 2 | 2 | 0.00511 | 0.00511 | XSLoader :: | cargar (xsub) |
| 14 | 14 | 7 | 0.00304 | 0.00298 | Exportador :: | importación |
| 3 | 1 | 1 | 0.00265 | 0.00254 | Exportador :: | as_heavy |
| 10 | 10 | 4 | 0.00140 | 0.00140 | vars :: | importación |
| 13 | 13 | 1 | 0.00129 | 0.00109 | constante :: | importación |
| 1 | 1 | 1 | 0.00360 | 0.00096 | FileHandle :: | importar |
| 3 | 3 | 3 | 0.00086 | 0.00074 | advertencias :: registrarse :: | importar |
| 9 | 3 | 1 | 0.00036 | 0.00036 | estricto :: | bits |
| 13 | 13 | 13 | 0.00032 | 0.00029 | estricto :: | importación |
| 2 | 2 | 2 | 0.00020 | 0.00020 | advertencias :: | importación |
| 2 | 1 | 1 | 0.00020 | 0.00020 | Getopt :: Long :: | ParseOptionSpec |
| 7 | 7 | 6 | 0.00043 | 0.00020 | estricto :: | unimportar |

Para obtener más información, consulte la lista completa de 189 subrutinas.

La primera parte del informe ya muestra la información crítica sobre la que
las subrutinas son las que utilizan la mayor parte del tiempo. El siguiente da algunas estadísticas sobre la fuente.
archivos perfilados.

Archivos de código fuente: ordenados por tiempo exclusivo y luego por nombre
| Stmts | Exclusivo | Promedio. | Informes | Archivo fuente |
| | Tiempo | | | |
| 2699761 | 15.66654 | 6e-06 | línea. cuadra . sub | wordmatch |
| 35 | 0.02187 | 0.00062 | línea. cuadra . sub | IO / Handle.pm |
| 274 | 0.01525 | 0.00006 | línea. cuadra . sub | Getopt / Long.pm |
| 20 | 0.00585 | 0.00029 | línea. cuadra . sub | Fcntl.pm |
| 128 | 0.00340 | 0.00003 | línea. cuadra . sub | Exportador / Heavy.pm |
| 42 | 0.00332 | 0.00008 | línea. cuadra . sub | IO / File.pm |
| 261 | 0.00308 | 0.00001 | línea. cuadra . sub | Exporter.pm |
| 323 | 0.00248 | 8e-06 | línea. cuadra . sub | constant.pm |
| 12 | 0.00246 | 0.00021 | línea. cuadra . sub | Archivo / Spec / Unix.pm |
| 191 | 0.00240 | 0.00001 | línea. cuadra . sub | vars.pm |
| 77 | 0.00201 | 0.00003 | línea. cuadra . sub | FileHandle.pm |
| 12 | 0.00198 | 0.00016 | línea. cuadra . sub | Carp.pm |
| 14 | 0.00175 | 0.00013 | línea. cuadra . sub | Symbol.pm |
| 15 | 0.00130 | 0.00009 | línea. cuadra . sub | IO.pm |
| 22 | 0.00120 | 0.00005 | línea. cuadra . sub | IO / Seekable.pm |
| 198 | 0.00085 | 4e-06 | línea. cuadra . sub | warnings / register.pm |
| 114 | 0.00080 | 7e-06 | línea. cuadra . sub | estricto.pm |
| 47 | 0.00068 | 0.00001 | línea. cuadra . sub | warnings.pm |
| 27 | 0.00054 | 0.00002 | línea. cuadra . sub | overload.pm |
| 9 | 0.00047 | 0.00005 | línea. cuadra . sub | SelectSaver.pm |
| 13 | 0.00045 | 0.00003 | línea. cuadra . sub | Archivo / Spec.pm |
| 2701595 | 15.73869 | | Total |
| 128647 | 0.74946 | | Promedio |
| | 0.00201 | 0.00003 | Mediana |
| | 0.00121 | 0.00003 | Desviación |

Informe elaborado por el perfilador Perl NYTProf 2.03, desarrollado por Tim Bunce y
Adán Kaplan.

En este punto, si está utilizando el html informe, puede hacer clic en los distintos enlaces para
perforar en cada subrutina y cada línea de código. Porque estamos usando el texto
informes aquí, y hay un directorio completo lleno de informes creados para cada archivo de origen,
solo mostraremos una parte del correspondiente línea de coincidencia de palabras.html archivo, suficiente para
dé una idea del tipo de resultado que puede esperar de esta genial herramienta.

$> html2text nytprof / wordmatch-line.html

Perfil de rendimiento - -vista de bloque -.- vista de línea -.- vista secundaria-
Para wordmatch
Ejecutar el viernes 26 de septiembre 13:46:39 2008
Reportado el viernes 26 de septiembre 13:47:22 2008

Wordmatch de archivo

Subrutinas: ordenadas por tiempo exclusivo
| Llamadas | P | F | Incluido | Exclusivo | Subrutina |
| | | | Tiempo | tiempo | |
|251215|5|1|13.09263 |10.47692 |main::|matches|
| 260642 | 2 | 1 | 2.71199 | 2.71199 | principal :: | depuración |
| 1 | 1 | 1 | 0.21404 | 0.21404 | principal :: | informe |
| 0 | 0 | 0 | 0 | 0 | principal :: | BEGIN |

| Línea | Stmts. | Exclusivo | Prom. | Código |
| | | Tiempo | | |
| 1 | | | | #!/ usr / bin / perl |
| 2 | | | | |
| | | | | uso estricto; |
| 3 | 3 | 0.00086 | 0.00029 | # gastó 0.00003s haciendo 1 llamadas a estricto :: |
| | | | | importación |
| | | | | use advertencias; |
| 4 | 3 | 0.01563 | 0.00521 | # gastó 0.00012s haciendo 1 llamadas a advertencias :: |
| | | | | importación |
| 5 | | | | |
| 6 | | | | = head1 NAME |
| 7 | | | | |
| 8 | | | | filewords - análisis de palabras del archivo de entrada |
<... recortar ...>
| 62 | 1 | 0.00445 | 0.00445 | Imprimir informe (% de recuento); |
| | | | | # gastó 0.21404s haciendo 1 llamadas a main :: report |
| 63 | | | | |
| | | | | # gastado 23.56955s (10.47692 + 2.61571) dentro de |
| | | | | main :: coincidencias que se llamaron 251215 veces, |
| | | | | promedio 0.00005s / llamada: # 50243 veces |
| | | | | (2.12134 + 0.51939s) en la línea 57 de wordmatch, avg |
| | | | | 0.00005s / llamada # 50243 veces (2.17735 + 0.54550s) |
| 64 | | | | en la línea 56 de wordmatch, promedio 0.00005s / call # |
| | | | | 50243 veces (2.10992 + 0.51797 s) en la línea 58 de |
| | | | | wordmatch, promedio 0.00005s / llamada # 50243 veces |
| | | | | (2.12696 + 0.51598s) en la línea 55 de wordmatch, avg |
| | | | | 0.00005s / llamada # 50243 veces (1.94134 + 0.51687s) |
| | | | | en la línea 54 de wordmatch, promedio 0.00005s / call |
| | | | | sub coincidencias {|
<... recortar ...>
| 102 | | | | |
| | | | | # pasó 2.71199s dentro de main :: debug que era |
| | | | | llamado 260642 veces, promedio 0.00001s / llamada: # |
| | | | | 251215 veces (2.61571 + 0s) por main :: coincide con |
| 103 | | | | línea 74 de wordmatch, promedio 0.00001s / llamada # 9427 |
| | | | | veces (0.09628 + 0s) en la línea 50 de wordmatch, avg |
| | | | | 0.00001s / llamada |
| | | | | sub debug {|
| 104 | 260642 | 0.58496 | 2e-06 | mi $ mensaje = turno; |
| 105 | | | | |
| 106 | 260642 | 1.09917 | 4e-06 | if ($ debug) {|
| 107 | | | | imprimir STDERR "DBG: $ mensaje \ n"; |
| 108 | | | |} |
| 109 | | | |} |
| 110 | | | | |
| 111 | 1 | 0.01501 | 0.01501 | salida 0; |
| 112 | | | | |

Hay montones de información muy útil allí: este parece ser el camino a seguir.

Vea también "Devel :: NYTProf :: Apache" que enlaza "Devel :: NYTProf" en "mod_perl".

CLASIFICACIÓN


Los módulos de Perl no son las únicas herramientas que un analista de rendimiento tiene a su disposición, el sistema
herramientas como "tiempo" no deben pasarse por alto, como muestra el siguiente ejemplo, donde tomamos un
mirada rápida a la clasificación. Se han escrito muchos libros, tesis y artículos sobre eficientes
algoritmos de clasificación, y este no es el lugar para repetir ese trabajo, hay varios buenos
ordenar módulos que merecen ser revisados ​​también: "Sort :: Maker", "Sort :: Key" se abren para
mente. Sin embargo, todavía es posible hacer algunas observaciones sobre ciertos elementos específicos de Perl.
interpretaciones sobre cuestiones relacionadas con la clasificación de conjuntos de datos y dar un ejemplo o dos con
con respecto a cómo la clasificación de grandes volúmenes de datos puede afectar el rendimiento. En primer lugar, a menudo
punto que se pasa por alto al ordenar grandes cantidades de datos, se puede intentar reducir los datos
configurado para ser tratado y en muchos casos "grep ()" puede ser bastante útil como un filtro simple:

@data = sort grep {/ $ filter /} @incoming

Un comando como este puede reducir enormemente el volumen de material para clasificar realmente
en primer lugar, y no debe ser ignorado a la ligera simplemente sobre la base de su
sencillez. El principio "KISS" se pasa por alto con demasiada frecuencia; el siguiente ejemplo utiliza el
utilidad de "tiempo" del sistema simple para demostrar. Echemos un vistazo a un ejemplo real de
clasificando el contenido de un archivo grande, un archivo de registro de Apache sería suficiente. Este tiene más de un
un cuarto de millón de líneas, tiene un tamaño de 50 millones y un fragmento se ve así:

# archivo de registro

188.209-65-87.adsl-dyn.isp.belgacom.be - - [08 / Feb / 2007: 12: 57: 16 +0000] "GET /favicon.ico HTTP / 1.1" 404 209 "-" "Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) "
188.209-65-87.adsl-dyn.isp.belgacom.be - - [08 / Feb / 2007: 12: 57: 16 +0000] "GET /favicon.ico HTTP / 1.1" 404 209 "-" "Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) "
151.56.71.198 - - [08 / Feb / 2007: 12: 57: 41 +0000] "GET /suse-on-vaio.html HTTP / 1.1" 200 2858 "http://www.linux-on-laptops.com/sony.html"" Mozilla / 5.0 (Windows; U; Windows NT 5.2; en-US; rv: 1.8.1.1) Gecko / 20061204 Firefox / 2.0.0.1 "
151.56.71.198 - - [08 / Feb / 2007: 12: 57: 42 +0000] "GET / data / css HTTP / 1.1" 404 "http://www.rfi.net/suse-on-vaio.html"" Mozilla / 5.0 (Windows; U; Windows NT 5.2; en-US; rv: 1.8.1.1) Gecko / 20061204 Firefox / 2.0.0.1 "
151.56.71.198 - - [08 / Feb / 2007: 12: 57: 43 +0000] "GET /favicon.ico HTTP / 1.1" 404 "-" "Mozilla / 209 (Windows; U; Windows NT 5.0; en- EE. UU.; RV: 5.2) Gecko / 1.8.1.1 Firefox / 20061204 "
217.113.68.60 - - [08 / Feb / 2007: 13: 02: 15 +0000] "GET / HTTP / 1.1" 304 - "-" "Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
217.113.68.60 - - [08 / Feb / 2007: 13: 02: 16 +0000] "GET / data / css HTTP / 1.1" 404 "http://www.rfi.net/"" Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) "
debora.to.isac.cnr.it - ​​- [08 / Feb / 2007: 13: 03: 58 +0000] "OBTENER /suse-on-vaio.html HTTP / 1.1" 200 2858 "http://www.linux-on-laptops.com/sony.html"" Mozilla / 5.0 (compatible; Konqueror / 3.4; Linux) KHTML / 3.4.0 (como Gecko) "
debora.to.isac.cnr.it - ​​- [08 / Feb / 2007: 13: 03: 58 +0000] "GET / data / css HTTP / 1.1" 404 "http://www.rfi.net/suse-on-vaio.html"" Mozilla / 5.0 (compatible; Konqueror / 3.4; Linux) KHTML / 3.4.0 (como Gecko) "
debora.to.isac.cnr.it - ​​- [08 / Feb / 2007: 13: 03: 58 +0000] "GET /favicon.ico HTTP / 1.1" 404 "-" "Mozilla / 209 (compatible; Konqueror / 5.0; Linux) KHTML / 3.4 (como Gecko) "
195.24.196.99 - - [08 / Feb / 2007: 13: 26: 48 +0000] "GET / HTTP / 1.0" 200 3309 "-" "Mozilla / 5.0 (Windows; U; Windows NT 5.1; fr; rv: 1.8.0.9 .20061206) Gecko / 1.5.0.9 Firefox / XNUMX "
195.24.196.99 - - [08 / Feb / 2007: 13: 26: 58 +0000] "GET / data / css HTTP / 1.0" 404 "http://www.rfi.net/"" Mozilla / 5.0 (Windows; U; Windows NT 5.1; fr; rv: 1.8.0.9) Gecko / 20061206 Firefox / 1.5.0.9 "
195.24.196.99 - - [08 / Feb / 2007: 13: 26: 59 +0000] "GET /favicon.ico HTTP / 1.0" 404 209 "-" "Mozilla / 5.0 (Windows; U; Windows NT 5.1; fr; RV: 1.8.0.9) Gecko / 20061206 Firefox / 1.5.0.9 "
crawl1.cosmixcorp.com - - [08 / Feb / 2007: 13: 27: 57 +0000] "GET /robots.txt HTTP / 1.0" 200 "-" "voyager / 179"
crawl1.cosmixcorp.com - - [08 / Feb / 2007: 13: 28: 25 +0000] "GET /links.html HTTP / 1.0" 200 3413 "-" "voyager / 1.0"
fhm226.internetdsl.tpnet.pl - - [08 / Feb / 2007: 13: 37: 32 +0000] "GET /suse-on-vaio.html HTTP / 1.1" 200 2858 "http://www.linux-on-laptops.com/sony.html"" Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) "
fhm226.internetdsl.tpnet.pl - - [08 / Feb / 2007: 13: 37: 34 +0000] "GET / data / css HTTP / 1.1" 404 "http://www.rfi.net/suse-on-vaio.html"" Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) "
80.247.140.134 - - [08 / Feb / 2007: 13: 57: 35 +0000] "GET / HTTP / 1.1" 200 3309 "-" "Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322 .XNUMX) "
80.247.140.134 - - [08 / Feb / 2007: 13: 57: 37 +0000] "GET / data / css HTTP / 1.1" 404 "http://www.rfi.net"" Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322) "
pop.compuscan.co.za - - [08 / Feb / 2007: 14: 10: 43 +0000] "GET / HTTP / 1.1" 200 3309 "-" "www.clamav.net"
livebot-207-46-98-57.search.live.com - - [08 / Feb / 2007: 14: 12: 04 +0000] "GET /robots.txt HTTP / 1.0" 200 "-" "msnbot / 179 (+http://search.msn.com/msnbot.htm)"
livebot-207-46-98-57.search.live.com - - [08 / Feb / 2007: 14: 12: 04 +0000] "GET /html/oracle.html HTTP / 1.0" 404 214 "-" " msnbot / 1.0 (+http://search.msn.com/msnbot.htm)"
dslb-088-064-005-154.pools.arcor-ip.net - - [08 / Feb / 2007: 14: 12: 15 +0000] "GET / HTTP / 1.1" 200 3309 "-" "www.clamav .red"
196.201.92.41 - - [08 / Feb / 2007: 14: 15: 01 +0000] "GET / HTTP / 1.1" 200 3309 "-" "MOT-L7 / 08.B7.DCR MIB / 2.2.1 Perfil / MIDP -2.0 Configuración / CLDC-1.1 "

La tarea específica aquí es ordenar las 286,525 líneas de este archivo por código de respuesta, consulta,
Navegador, URL de referencia y, por último, Fecha. Una solución podría ser utilizar el siguiente código,
que itera sobre los archivos dados en la línea de comandos.

# sort-apache-registro

#!/ usr / bin / perl -n

uso estricto
use advertencias;

mis datos;

LÍNEA:
while (<>) {
mi $ línea = $ _;
if (
$ línea = ~ m / ^ (
([\ w \. \ -] +) # cliente
\ s * - \ s * - \ s * \ [
([^]] +) # fecha
\] \ s * "\ w + \ s *
(\ S +) # consulta
[^ "] +" \ s *
(\ d +) # estado
\ s + \ S + \ s + "[^"] * "\ s +"
([^ "] *) # navegador
"
.*
) $ / x
) {
my @chunks = split (/ + /, $ línea);
mi $ ip = $ 1;
mi $ fecha = $ 2;
mi $ consulta = $ 3;
my $ status = $ 4;
mi $ navegador = $ 5;

push (@data, [$ ip, $ fecha, $ consulta, $ estado, $ navegador, $ línea]);
}
}

mi @ordenado = ordenar {
$ a -> [3] cmp $ b -> [3]
||
$ a -> [2] cmp $ b -> [2]
||
$ a -> [0] cmp $ b -> [0]
||
$ a -> [1] cmp $ b -> [1]
||
$ a -> [4] cmp $ b -> [4]
} @datos;

foreach my $ data (@sorted) {
imprimir $ datos -> [5];
}

salida 0;

Al ejecutar este programa, redirija "STDOUT" para que sea posible comprobar que la salida es
corrija de las siguientes ejecuciones de prueba y use la utilidad de "tiempo" del sistema para verificar el
tiempo de ejecución.

$> time ./sort-apache-log logfile> out-sort

0m17.371s reales
usuario 0m15.757s
sistema 0m0.592s

El programa tardó poco más de 17 segundos en ejecutarse. Tenga en cuenta los diferentes valores "tiempo"
salidas, es importante usar siempre la misma y no confundir lo que cada una
significa.

Tiempo real transcurrido
El tiempo total o de reloj de pared entre el momento en que se llamó "tiempo" y el momento
termina. El tiempo transcurrido incluye los tiempos del usuario y del sistema, y ​​el tiempo empleado
esperando a otros usuarios y procesos en el sistema. Inevitablemente, este es el
aproximada de las medidas dadas.

Tiempo de CPU del usuario
El tiempo del usuario es la cantidad de tiempo que el proceso completo pasó en nombre del usuario en
este sistema ejecutando este programa.

Tiempo de CPU del sistema
El tiempo del sistema es la cantidad de tiempo que el kernel dedicó a ejecutar rutinas, o
llamadas al sistema, en nombre de este usuario de proceso.

Ejecutando este mismo proceso como una "Transformada de Schwarzian" es posible eliminar el
matrices de entrada y salida para almacenar todos los datos y trabajar en la entrada directamente
llega también. De lo contrario, el código se ve bastante similar:

# ordenar-apache-log-schwarzian

#!/ usr / bin / perl -n

uso estricto
use advertencias;

Imprimir

mapa $ _-> [0] =>

clasificar {
$ a -> [4] cmp $ b -> [4]
||
$ a -> [3] cmp $ b -> [3]
||
$ a -> [1] cmp $ b -> [1]
||
$ a -> [2] cmp $ b -> [2]
||
$ a -> [5] cmp $ b -> [5]
}
mapa [$ _, m / ^ (
([\ w \. \ -] +) # cliente
\ s * - \ s * - \ s * \ [
([^]] +) # fecha
\] \ s * "\ w + \ s *
(\ S +) # consulta
[^ "] +" \ s *
(\ d +) # estado
\ s + \ S + \ s + "[^"] * "\ s +"
([^ "] *) # navegador
"
.*
) $ / xo]

=> <>;

salida 0;

Ejecute el nuevo código contra el mismo archivo de registro, como el anterior, para verificar la nueva hora.

$> time ./sort-apache-log-schwarzian logfile> out-schwarz

0m9.664s reales
usuario 0m8.873s
sistema 0m0.704s

El tiempo se ha reducido a la mitad, lo que supone una mejora de velocidad respetable según cualquier estándar.
Naturalmente, es importante comprobar que la salida sea coherente con la primera ejecución del programa,
aquí es donde entra en juego la utilidad "cksum" del sistema Unix.

$> cksum out-sort out-schwarz
3044173777 52029194 ordenar
3044173777 52029194 fuera-schwarz

POR CIERTO. Tenga cuidado también con la presión de los gerentes que lo ven acelerar un programa en un 50% del
tiempo de ejecución una vez, solo para recibir una solicitud un mes después para hacer lo mismo nuevamente (historia real) -
solo tendrá que señalar que es solo un ser humano, incluso si es un programador de Perl, y
verás lo que puedes hacer ...

REGISTRO


Una parte esencial de cualquier buen proceso de desarrollo es el manejo apropiado de errores con
mensajes apropiadamente informativos, sin embargo existe una escuela de pensamiento que
sugiere que los archivos de registro deben hablador, como si la cadena de producción ininterrumpida de alguna manera
asegura la supervivencia del programa. Si la velocidad es un problema de alguna manera, este enfoque es
equivocada.

Una vista común es el código que se parece a esto:

logger-> debug ("Un mensaje de registro a través del ID de proceso: $$ INC:". Dumper (\% INC))

El problema es que este código siempre se analizará y ejecutará, incluso cuando la depuración
el nivel establecido en el archivo de configuración de registro es cero. Una vez el depurar() subrutina ha sido
ingresado, y la variable interna $ debug confirmada como cero, por ejemplo, el mensaje
que ha sido enviado será descartado y el programa continuará. En el ejemplo
Sin embargo, dado que el hash "\% INC" ya se habrá descargado, y la cadena del mensaje
construido, todo el trabajo podría ser omitido por una variable de depuración en la declaración
nivel, así:

logger-> debug ("Un mensaje de registro vía ID de proceso: $$ INC:". Dumper (\% INC)) if $ DEBUG;

Este efecto se puede demostrar configurando un script de prueba con ambos formularios, incluido un
Subrutina "debug ()" para emular la funcionalidad típica de "logger ()".

# si se depura

#!/ usr / bin / perl

uso estricto
use advertencias;

utilizar Benchmark;
use Data :: Dumper;
my $ DEBUG = 0;

depuración secundaria {
my $ msg = turno;

if ($ DEBUG) {
imprimir "DEPURACIÓN: $ msg \ n";
}
};

timethese (100000, {
'debug' => sub {
debug ("Un mensaje de registro de $ 0 a través de ID de proceso: $$". Dumper (\% INC))
},
'ifdebug' => sub {
debug ("Un mensaje de registro de $ 0 a través de ID de proceso: $$". Dumper (\% INC)) if $ DEBUG
},
});

Veamos qué hace "Benchmark" con esto:

$> perl ifdebug
Benchmark: cronometraje 100000 iteraciones de constante, sub ...
ifdebug: 0 segundos de reloj de pared (0.01 usr + 0.00 sys = 0.01 CPU) @ 10000000.00 / s (n = 100000)
(advertencia: muy pocas iteraciones para un recuento confiable)
depuración: 14 segundos de reloj de pared (13.18 usr + 0.04 sys = 13.22 CPU) @ 7564.30 / s (n = 100000)

En un caso, el código, que hace exactamente lo mismo en cuanto a generar cualquier
la depuración de información se refiere, en otras palabras, nada, toma 14 segundos, y en el
en otro caso, el código tarda una centésima de segundo. Parece bastante definitivo. Utilizar una
$ DEBUG variable ANTES de llamar a la subrutina, en lugar de depender de la
funcionalidad en su interior.

Inicio de sesión if DEBUG (constante)
Es posible llevar la idea anterior un poco más lejos, usando un tiempo de compilación "DEBUG"
constante.

# ifdebug-constante

#!/ usr / bin / perl

uso estricto
use advertencias;

utilizar Benchmark;
use Data :: Dumper;
usar constante
DEPURACIÓN => 0
;

depuración secundaria {
si (DEPURAR) {
my $ msg = turno;
imprimir "DEPURACIÓN: $ msg \ n";
}
};

timethese (100000, {
'debug' => sub {
debug ("Un mensaje de registro de $ 0 a través de ID de proceso: $$". Dumper (\% INC))
},
'constante' => sub {
debug ("Un mensaje de registro de $ 0 a través de ID de proceso: $$". Dumper (\% INC)) if DEBUG
},
});

La ejecución de este programa produce el siguiente resultado:

$> perl ifdebug-constante
Benchmark: cronometraje 100000 iteraciones de constante, sub ...
constante: 0 segundos de reloj de pared (-0.00 usr + 0.00 sys = -0.00 CPU) @ -7205759403792793600000.00 / s (n = 100000)
(advertencia: muy pocas iteraciones para un recuento confiable)
sub: 14 segundos de reloj de pared (13.09 usr + 0.00 sys = 13.09 CPU) @ 7639.42 / s (n = 100000)

La constante "DEBUG" borra el piso incluso con la variable $ debug, marcando en menos
cero segundos y genera un mensaje de "advertencia: muy pocas iteraciones para un recuento confiable"
por añadidura. Para ver lo que realmente está sucediendo y por qué tuvimos muy pocas iteraciones cuando
pensamos que pedimos 100000, podemos usar el muy útil "B :: Deparse" para inspeccionar el nuevo
código:

$> perl -MO = Deparse ifdebug-constante

utilizar Benchmark;
use Data :: Dumper;
use constante ('DEBUG', 0);
depuración secundaria {
use advertencias;
use 'refs' estrictos;
0;
}
use advertencias;
use 'refs' estrictos;
timethese (100000, {'sub', sub {
debug "Un mensaje de registro de $ 0 a través de ID de proceso: $$". Dumper (\% INC);
}
, 'constante', sub {
0;
}
});
sintaxis de ifdebug-constant OK

La salida muestra el constante() La subrutina que estamos probando se reemplaza con el valor de
la constante "DEBUG": cero. La línea a probar se ha optimizado completamente y
no puede ser mucho más eficiente que eso.

POSDATA


Este documento proporciona varias formas de identificar los puntos calientes y verificar
si alguna modificación ha mejorado el tiempo de ejecución del código.

Como pensamiento final, recuerde que no es (en el momento de escribir este artículo) posible producir una
programa útil que se ejecutará en tiempo cero o negativo y este principio básico puede ser
Escrito como: eficiente programas están slow por su propia definición. Por supuesto es posible
escribir un programa casi instantáneo, pero no va a hacer mucho, aquí hay una muy
eficiente:

$> perl -e 0

Optimizar eso más es un trabajo para "p5p".

Use perlperf en línea usando los servicios de onworks.net


Servidores y estaciones de trabajo gratuitos

Descargar aplicaciones de Windows y Linux

Comandos de Linux

Ad




×
Anuncio
❤ ️Compre, reserve o adquiera aquí: sin costo, ayuda a mantener los servicios gratuitos.