Landmarks es una biblioteca de perfil simple para Ocaml. Proporciona primitivas para delimitar porciones de código y medir el rendimiento del código instrumentado en tiempo de ejecución. Las medidas disponibles se obtienen agregando ciclos de CPU (utilizando el contador de sellos de tiempo de la CPU), tiempo aplicativo (usando Sys.time
) y bytes asignados (con Gc.allocated_bytes
). La instrumentación del código puede realizarse a mano, automáticamente o semiautomáticamente utilizando una extensión PPX.
Durante la ejecución de su programa, el recorrido del código instrumentado por el flujo de control se registra como un "callgraph" que lleva las medidas recopiladas. Los resultados se pueden navegar directamente en la consola o exportarse a JSON.
Esta herramienta está destinada a usarse como una forma de encontrar dónde pasa el tiempo en sus programas (y no de referencia de piezas de código independientes como Core_Bench) al tiempo que proporciona resultados que solo corresponden a la parte instrumentada de su código OCAML (contrario a las herramientas que Trabaje directamente con el ejecutable binario como gprof o perf).
Para obtener más información, puede navegar por la API.
La biblioteca se divide en dos paquetes: landmarks
para la biblioteca de tiempo de ejecución y landmarks-ppx
para el preprocesador que implementa instrumentación automática.
opam install landmarks
o
opam install landmarks-ppx
Instalará la biblioteca de tiempo de ejecución o tanto la biblioteca de tiempo de ejecución y el preprocesador.
git clone https://github.com/LexiFi/landmarks.git
cd landmarks
dune build @install
Simplemente use los landmarks
de la biblioteca y el preprocesador landmarks-ppx
para comparar sus ejecutables y bibliotecas. Por ejemplo, el siguiente archivo dune
construye la test
ejecutable utilizando la biblioteca landmarks
y su PPX. La bandera opcional --auto
enciende la instrumentación automática (ver más abajo).
(executable
(name test)
(libraries landmarks)
(preprocess (pps landmarks-ppx --auto))
)
Es posible usar Dune para activar automáticamente la instrumentación de un proyecto. Eche un vistazo a Lexifi/Landmarks-Starter para un ejemplo básico y vea el manual de dunas para obtener más información.
ocamlfind ocamlopt -c -package landmarks prog.ml
ocamlfind ocamlopt -o prog -package landmarks -linkpkg prog.cmx
Puede reemplazar "OCAMLOPT" por "OCAMLC" para compilar el programa en Bytecode.
ocamlfind ocamlopt -c -package landmarks -package landmarks-ppx -ppxopt landmarks-ppx,--auto prog.ml
ocamlfind ocamlopt -o prog -package landmarks -linkpkg prog.cmx
Tenga en cuenta que "-ppxopt Landmarks-PPX,-Auto" es opcional y enciende la instrumentación automática.
Hay tres primitivas principales:
val register : string -> landmark
val enter : landmark -> unit
val exit : landmark -> unit
La función register
declara nuevos puntos de referencia y debe usarse en Toplevel. Las funciones enter
y exit
se utilizan para delimitar la parte del código adjunto a un punto de referencia. Al final del perfil, recuperamos para cada punto de referencia, la información de tiempo agregada gastada ejecutando la pieza de código correspondiente. Durante la ejecución, también se registra un rastro de cada punto de referencia visitado para construir un "callgraph".
Por ejemplo:
open Landmark
let loop = register " loop "
let sleep = register " sleep "
let main = register " main "
let zzz () =
enter sleep;
Unix. sleep 1 ;
exit sleep
let () =
begin
start_profiling () ;
enter main;
enter loop;
for _ = 1 to 9 do
zzz ()
done ;
exit loop;
zzz () ;
exit main;
end
(Este archivo se puede compilar con ocamlfind ocamlc -o prog -package landmarks -package unix -linkpkg prog.ml
)
El callgraph inducido es:
- 100.00% : main
| - 90.00% : loop
| | - 100.00% : sleep
| - 10.00% : sleep
que puede ser parafraseado como:
clock()
La biblioteca proporciona una unión al contador de ciclos de alto rendimiento para las arquitecturas X86 32 y 64 bits (tenga en cuenta que puede usar los landmarks-noc.cm(x)a
archivo para proporcionar su propia implementación). Se usa para medir el tiempo dedicado al código instrumentado.
Para evitar escribir el código de Boilerplate, puede usar la extensión PPX distribuida con este paquete. Permite al programador expresiones de instrumentos utilizando anotaciones y instrumentos automáticamente de instrumentos de las funciones de nivel superior.
El valor expr [@landmark "name"]
se expande a
Landmark. enter __generated_landmark_1;
let r =
try expr with e -> Landmark. exit __generated_landmark_1; raise e
in
Landmark. exit __generated_landmark_1;
r
y la declaración
let __generated_landmark_1 = Landmark. register " name "
se adjunta en el nivel superior.
Cabe señalar que esta transformación no preserva las llamadas recursivas de la cola (y también previene alguna generalización del polimorfismo). Para evitar estos problemas, se recomienda usar la otra extensión proporcionada alrededor de let ... in
y let rec ... in
:
let [ @ landmark] f = body
que se expande en:
let __generated_landmark_2 = Landmark. register " f "
let f = body
let f x1 ... xn =
Landmark. enter __generated_landmark_2;
let r =
try f x1 ... xn with e -> Landmark. exit __generated_landmark_2; raise e
in
Landmark. exit __generated_landmark_2;
r
Cuando se obtiene la n
de f
contando las sucesos superficiales de fun ... ->
y function ... ->
en body
. Tenga en cuenta que al usar esta anotación con enlaces Let-REC, solo se registrarán las llamadas de punto de entrada. Por ejemplo, en la siguiente pieza de código
let () =
let [ @ landmark] rec even n = (n = 0 ) || odd (n - 1 )
and [ @ landmark] odd n = (n = 1 ) || n > 0 && even (n - 1 )
in Printf. printf " 'six is even' is %b n " (even 6 )
El punto de referencia asociado con "incluso" se atravesará exactamente una vez (¡y no tres veces!), Mientras que el flujo de control no pasará a través del punto de referencia asociado con "impar".
Las anotaciones de la estructura [@@@landmark "auto"]
y [@@@landmark "auto-off"]
activan o desactivan la instrumentación automática de las funciones de nivel superior en un módulo. En modo automático, todas las declaraciones de funciones se anotan implícitamente. La instrumentación automática se puede habilitar/deshabilitar para todos los archivos a través de la opción auto
en OCAML_LANDMARKS
, como se detalla a continuación.
La variable de entorno OCAML_LANDMARKS
se lee en dos etapas diferentes: cuando se ejecuta el reescritor PPX y cuando el módulo de rejillas se carga mediante un programa instrumentado. Esta variable se analiza como una lista separada por comas de elementos de la option=argument
u option
, donde option
es:
Durante la etapa de reescritores PPX (en el tiempo de compilación):
auto
(sin argumentos): enciende la instrumentación automática de forma predeterminada (se comporta como si cada módulo comience con la anotación [@@@landmark "auto"]
).
threads
(sin argumentos): le dice a la extensión PPX que use el módulo Landmark_threads
en lugar del Landmark
de Módulo.
Al cargar un programa instrumentado (en tiempo de ejecución):
format
con posibles argumentos: textual
(predeterminado) o json
. Controla el formato de salida del perfil, que es una representación amigable con la consola o la codificación JSON del callgraph.
threshold
con un número entre 0.0 y 100.0 como argumento (predeterminado: 1.0). Si el umbral no es cero, la salida textual ocultará nodos en el callgraph por debajo de este umbral (en el porcentaje de tiempo de sus padres). Esta opción no tiene sentido para otros formatos.
output
con posible argumento: stderr
(predeterminado), stdout
, temporary
, <file>
(donde <file>
es la ruta de un archivo). Le dice dónde generar los resultados del perfil. Con temporary
lo imprimirá en un archivo temporal (el nombre de este archivo se imprimirá en el error estándar). También puede usar temporary:<directory>
para especificar el directorio donde se generan los archivos.
debug
sin discusión. Activa un modo detallado que genera trazas en Stderr cada vez que se llaman a los puntos de referencia primitivos.
time
sin argumento. También recolecte Sys.time
tiempo de tiempo durante el perfil.
off
sin discusión. Deshabilitar el perfil.
on
argumento. Habilitar el perfil (predeterminado; se puede omitir).
allocation
sin argumento. También recopile datos Gc.allocated_byte
.
Puede compilar el visor web en su computadora o explorarlo en línea. Debe cargar los archivos JSON usando FilePicker y luego puede hacer clic para explorar el Callgraph.
El módulo Landmark
no es seguro de hilo. Si tiene varios hilos, debe asegurarse de que, como máximo, un hilo esté ejecutando código instrumentado. Para eso, puede usar el módulo Landmark_threads
(incluido en los puntos de referencia-threads.cm (x) un archivo) que evita que las funciones no seguras de hilo se ejecuten en todos los hilos, pero el que comenzó el perfil.
La anotación de las expresiones puede templar con el polimorfismo (este no es el caso de la anotación de enlace). Por ejemplo, la siguiente pieza de código no se compilará:
let test = ( fun x -> x)[ @ landmark " test " ]
in test " string " , test 1
Este paquete de 'puntos de referencia' tiene licencia por Lexifi bajo los términos de la licencia MIT.
Contacto: [email protected]