Les monuments sont une bibliothèque de profilage simple pour OCAML. Il fournit des primitives pour délimiter les parties du code et mesurer les performances du code instrumenté au moment de l'exécution. Les mesures disponibles sont obtenues en agrégeant les cycles CPU (en utilisant le compteur horaire du CPU), le temps applicatif (en utilisant Sys.time
) et les octets alloués (avec Gc.allocated_bytes
). L'instrumentation du code peut être effectuée à la main, automatiquement ou semi-automatique à l'aide d'une extension PPX.
Lors de l'exécution de votre programme, la traversée du code instrumenté par le flux de contrôle est enregistrée comme un "callgraph" qui transporte les mesures collectées. Les résultats peuvent être parcourus soit directement sur la console, soit exportés vers JSON.
Cet outil est destiné à être utilisé comme un moyen de trouver où le temps est passé dans vos programmes (et non des pièces de code indépendantes de référence comme Core_Bench) tout en fournissant des résultats qui correspondent uniquement à la partie instrumentée de votre code OCAML (contrairement aux outils qui Fonctionnez directement avec l'exécutable binaire comme GPROF ou perf).
Pour plus d'informations, vous pouvez parcourir l'API.
La bibliothèque est divisée en deux packages: landmarks
pour la bibliothèque d'exécution et landmarks-ppx
pour le préprocesseur implémentant l'instrumentation automatique.
opam install landmarks
ou
opam install landmarks-ppx
Installera la bibliothèque d'exécution ou la bibliothèque d'exécution et le préprocesseur.
git clone https://github.com/LexiFi/landmarks.git
cd landmarks
dune build @install
Utilisez simplement les landmarks
de la bibliothèque et les landmarks-ppx
pour comparer vos exécutables et bibliothèques. Par exemple, le fichier dune
suivant construit le test
exécutable à l'aide de la bibliothèque landmarks
et de son PPX. Le drapeau en option --auto
allume l'instrumentation automatique (voir ci-dessous).
(executable
(name test)
(libraries landmarks)
(preprocess (pps landmarks-ppx --auto))
)
Il est possible d'utiliser Dune pour déclencher automatiquement l'instrumentation d'un projet. Jetez un œil à LeXIFI / STARKS-Starter pour un exemple de base et consultez le manuel Dune pour plus d'informations.
ocamlfind ocamlopt -c -package landmarks prog.ml
ocamlfind ocamlopt -o prog -package landmarks -linkpkg prog.cmx
Vous pouvez remplacer "OCAMLOPT" par "OCAMLC" pour compiler le programme dans ByteCode.
ocamlfind ocamlopt -c -package landmarks -package landmarks-ppx -ppxopt landmarks-ppx,--auto prog.ml
ocamlfind ocamlopt -o prog -package landmarks -linkpkg prog.cmx
Notez que "-PPXOPT STOWNmarks-PPX, - Auto" est facultatif et allume l'instrumentation automatique.
Il y a trois principales primitives:
val register : string -> landmark
val enter : landmark -> unit
val exit : landmark -> unit
La fonction register
déclare de nouveaux points de repère et doit être utilisé au niveau Toplevel. Les fonctions enter
et exit
sont utilisées pour délimiter la partie du code attaché à un point de repère. À la fin du profilage, nous récupérons pour chaque point de repère les informations de temps agrégées passées à exécuter le morceau de code correspondant. Au cours de l'exécution, une trace de chaque point de repère visité est également enregistrée afin de construire un "callgraph".
Par exemple:
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
(Ce fichier peut être compilé avec ocamlfind ocamlc -o prog -package landmarks -package unix -linkpkg prog.ml
)
Le callgraph induit est:
- 100.00% : main
| - 90.00% : loop
| | - 100.00% : sleep
| - 10.00% : sleep
qui peut être paraphrasé comme:
clock()
La bibliothèque fournit une liaison au compteur de cycles haute performance pour les architectures x86 32 et 64 bits (notez que vous pouvez utiliser les landmarks-noc.cm(x)a
archive pour fournir votre propre implémentation). Il est utilisé pour mesurer le temps passé dans le code instrumenté.
Pour éviter d'écrire du code de passe-partout, vous pouvez utiliser l'extension PPX distribuée avec ce package. Il permet au programmeur d'expressions d'instruments en utilisant l'annotation et à instrumenter automatiquement les fonctions de niveau supérieur.
La valeur expr [@landmark "name"]
est étendue en
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
Et la déclaration
let __generated_landmark_1 = Landmark. register " name "
est annexé au niveau supérieur.
Il convient de souligner que cette transformation ne préserve pas les appels de la queue (et empêche également une certaine généralisation du polymorphisme). Pour contourner ces problèmes, il est recommandé d'utiliser l'autre extension fournie autour de let ... in
et let rec ... in
let [ @ landmark] f = body
qui est élargi dans:
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
Lorsque l'arité n
de f
est obtenue en comptant les occurrences peu profondes de fun ... ->
et function ... ->
dans body
. Veuillez noter que lors de l'utilisation de cette annotation avec des liaisons Let-REC, seuls les appels à point d'entrée seront enregistrés. Par exemple, dans le morceau de code suivant
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 )
Le point de repère associé à "même" sera traversé exactement une fois (et pas trois fois!) Alors que le flux de contrôle ne passera pas par le point de repère associé à "Odd".
Les annotations de structure [@@@landmark "auto"]
et [@@@landmark "auto-off"]
activent ou désactivent l'instrumentation automatique des fonctions de niveau supérieur dans un module. En mode automatique, toutes les déclarations de fonctions sont implicitement annotées. L'instrumentation automatique peut être activée / désactivée pour tous les fichiers via l'option auto
dans OCAML_LANDMARKS
, comme détaillé ci-dessous.
La variable d'environnement OCAML_LANDMARKS
est lue à deux étapes différentes: lorsque le réécriture PPX est exécuté, et lorsque le module de repères est chargé par un programme instrumenté. Cette variable est analysée en tant que liste des éléments séparés par des virgules de l' option=argument
ou option
, où option
est:
Pendant l'étape du réécriture PPX (au moment de la compilation):
auto
(pas d'arguments): allume l'instrumentation automatique par défaut (se comporte comme si chaque module commence par l'annotation [@@@landmark "auto"]
).
threads
(pas d'arguments): indique à l'extension ppx d'utiliser le module Landmark_threads
au lieu du Landmark
du module.
Lors du chargement d'un programme instrumenté (au moment de l'exécution):
format
avec des arguments possibles: textual
(par défaut) ou json
. Il contrôle le format de sortie du profilage qui est soit une représentation conviviale ou un codage JSON du CallGraph.
threshold
avec un nombre entre 0,0 et 100,0 comme argument (par défaut: 1.0). Si le seuil n'est pas zéro, la sortie textuelle masquera les nœuds dans le callgraph en dessous de ce seuil (en pourcentage de temps de leur parent). Cette option n'a pas de sens pour d'autres formats.
output
avec un argument possible: stderr
(par défaut), stdout
, temporary
, <file>
(où <file>
est le chemin d'accès d'un fichier). Il indique où produire les résultats du profilage. Avec temporary
, il l'imprimera dans un fichier temporaire (le nom de ce fichier sera imprimé sur l'erreur standard). Vous pouvez également utiliser temporary:<directory>
pour spécifier le répertoire où les fichiers sont générés.
debug
sans argument. Active un mode verbeux qui publie des traces sur STDERR chaque fois que les primitives de repères sont appelées.
time
sans argument. Collectez également les horodatages Sys.time
pendant le profilage.
off
argument. Désactiver le profilage.
on
argument. Activer le profilage (par défaut; peut être omis).
allocation
sans argument. Collectez également les données Gc.allocated_byte
.
Vous pouvez soit compiler la visionneuse Web sur votre ordinateur ou le parcourir en ligne. Vous devez charger les fichiers JSON à l'aide du FilePicker, puis vous pouvez cliquer pour parcourir le callGraph.
Le module Landmark
n'est pas un filetage. Si vous avez plusieurs threads, vous devez vous assurer que, au maximum, un thread exécute du code instrumenté. Pour cela, vous pouvez utiliser le module Landmark_threads
(inclus dans le point de repère-threads.cm (x) une archive) qui empêche les fonctions non filigologiques d'exécuter dans tous les threads mais celui qui a commencé le profilage.
L'annotation sur les expressions peut tempérer avec le polymorphisme (ce n'est pas le cas pour l'annotation de liaison à la location). Par exemple, le morceau de code suivant ne compilera pas:
let test = ( fun x -> x)[ @ landmark " test " ]
in test " string " , test 1
Ce forfait «repères» est autorisé par Lexifi en vertu des termes de la licence du MIT.
Contact: [email protected]