Interface to the Criterium native agent for allocation tracking and call tracing.
This namespace provides functions for:
Key Features:
Agent Loading: Due to JVMTI limitations, the agent MUST be loaded at JVM startup using -agentpath for full functionality. Start your JVM with: clojure -J-agentpath:/path/to/libcriterium.dylib -M:dev
Or use (jvm-opts) to get the correct path, then restart your JVM with that option.
Example usage:
;; Allocation tracking
(let [[allocations result] (with-allocation-tracing
(your-code-here))]
(let [thread-allocs (filter (allocation-on-thread?) allocations)]
(allocations-summary thread-allocs)))
;; Call tracing
(let [[call-tree result] (with-call-tracing
(your-code-here))]
;; call-tree is a nested map with :class, :method, :call-count, :children
call-tree)
For more details, see the README in projects/agent/.
Interface to the Criterium native agent for allocation tracking and call tracing.
This namespace provides functions for:
- Tracking JVM heap allocations during benchmark execution
- Tracing method calls to build call graphs
Key Features:
- Allocation Tracking: Capture detailed information about object allocations
- Call Tracing: Record method entry/exit to build hierarchical call trees
Agent Loading:
Due to JVMTI limitations, the agent MUST be loaded at JVM startup using
-agentpath for full functionality. Start your JVM with:
clojure -J-agentpath:/path/to/libcriterium.dylib -M:dev
Or use (jvm-opts) to get the correct path, then restart your JVM with that option.
Example usage:
```clojure
;; Allocation tracking
(let [[allocations result] (with-allocation-tracing
(your-code-here))]
(let [thread-allocs (filter (allocation-on-thread?) allocations)]
(allocations-summary thread-allocs)))
;; Call tracing
(let [[call-tree result] (with-call-tracing
(your-code-here))]
;; call-tree is a nested map with :class, :method, :call-count, :children
call-tree)
```
For more details, see the README in projects/agent/.(allocation-freed? record)Predicate that returns true if the allocation record indicates the object was freed.
An object is considered freed when it has been garbage collected during the allocation tracking session. This helps identify temporary allocations vs retained objects.
Predicate that returns true if the allocation record indicates the object was freed. An object is considered freed when it has been garbage collected during the allocation tracking session. This helps identify temporary allocations vs retained objects.
(allocation-on-thread?)(allocation-on-thread? thread-id)Returns a predicate function for filtering allocation records by thread.
The returned function takes an allocation record and returns true if the allocation occurred on the specified thread. When called with no arguments, uses the current thread's ID.
Useful for composing with filter/remove to analyze allocations by thread
Returns a predicate function for filtering allocation records by thread. The returned function takes an allocation record and returns true if the allocation occurred on the specified thread. When called with no arguments, uses the current thread's ID. Useful for composing with filter/remove to analyze allocations by thread
(allocations-summary records)Returns a summary of allocation statistics for the given records.
Takes a sequence of allocation records and returns a map with: {:num-allocated - Total number of objects allocated :num-freed - Number of allocated objects that were freed :allocated-bytes - Total bytes allocated :freed-bytes - Total bytes from freed objects}
Useful for getting high-level metrics from allocation tracking results.
Returns a summary of allocation statistics for the given records.
Takes a sequence of allocation records and returns a map with:
{:num-allocated - Total number of objects allocated
:num-freed - Number of allocated objects that were freed
:allocated-bytes - Total bytes allocated
:freed-bytes - Total bytes from freed objects}
Useful for getting high-level metrics from allocation tracking results.(attached?)Predicate for whether the criterium native agent is properly attached.
Returns true if the agent was successfully loaded and initialized by the JVM, false otherwise. The agent must be attached for allocation tracking to work.
Predicate for whether the criterium native agent is properly attached. Returns true if the agent was successfully loaded and initialized by the JVM, false otherwise. The agent must be attached for allocation tracking to work.
Filter that stops traversal at clojure.core and clojure.lang boundaries. Shows calls into Clojure core but not the internal implementation.
Filter that stops traversal at clojure.core and clojure.lang boundaries. Shows calls into Clojure core but not the internal implementation.
Filter that excludes criterium's own infrastructure from call traces. Applied by default in with-call-tracing to avoid capturing the tracing machinery itself (method-tracing-stop!, agent-command, etc.).
Filter that excludes criterium's own infrastructure from call traces. Applied by default in with-call-tracing to avoid capturing the tracing machinery itself (method-tracing-stop!, agent-command, etc.).
(filter-call-tree call-tree opts)Filter a call tree according to filter options.
Options:
Returns the filtered call tree, or nil if the root is excluded. If multiple children are promoted, returns the one containing user code.
Filter a call tree according to filter options. Options: - :exclude-packages - Set of package prefixes to exclude entirely. Nodes with matching classes are removed, their children promoted up. - :stop-at-packages - Set of package prefixes where traversal stops. Matching nodes are kept but their children are truncated. - :max-depth - Maximum depth to include (1 = root only, 2 = root + children, etc.) Returns the filtered call tree, or nil if the root is excluded. If multiple children are promoted, returns the one containing user code.
(find-user-code-tree trees)Find the user code tree from collected call trees. Searches for the run-traced* wrapper node and extracts the user code from within it, skipping the wrapper's invoke/invokeStatic frames. Throws if the wrapper tree is not found - this indicates a bug in tracing.
Find the user code tree from collected call trees. Searches for the run-traced* wrapper node and extracts the user code from within it, skipping the wrapper's invoke/invokeStatic frames. Throws if the wrapper tree is not found - this indicates a bug in tracing.
Filter that excludes JDK internal packages. Use with filter-call-tree to remove JDK implementation details.
Filter that excludes JDK internal packages. Use with filter-call-tree to remove JDK implementation details.
(jvm-opts)Returns a vector of JVM arguments for loading the native agent.
Returns a vector like ["-agentpath:/tmp/criterium-agent-..."] that can be used when spawning subprocesses or configuring REPL JVM options. Returns an empty vector if the agent is unavailable or the platform is unsupported.
Useful for configuring JVM processes to use the bundled agent without manual -agentpath specification.
Returns a vector of JVM arguments for loading the native agent. Returns a vector like ["-agentpath:/tmp/criterium-agent-..."] that can be used when spawning subprocesses or configuring REPL JVM options. Returns an empty vector if the agent is unavailable or the platform is unsupported. Useful for configuring JVM processes to use the bundled agent without manual -agentpath specification.
(loaded?)Returns true if the Criterium native agent is currently loaded.
This is an alias for attached? and checks whether the agent was loaded via -agentpath JVM arguments or programmatically via load-agent!.
Use this before attempting allocation tracking operations.
Returns true if the Criterium native agent is currently loaded. This is an alias for attached? and checks whether the agent was loaded via -agentpath JVM arguments or programmatically via load-agent!. Use this before attempting allocation tracking operations.
(remove-tracing-infrastructure-trees trees)Remove trees that contain tracing infrastructure within the first few levels. This filters out call trees that are part of the tracing machinery itself, but preserves the run-traced* wrapper tree and any trees containing it (which may contain infrastructure as children but is the entry point for user code).
Remove trees that contain tracing infrastructure within the first few levels. This filters out call trees that are part of the tracing machinery itself, but preserves the run-traced* wrapper tree and any trees containing it (which may contain infrastructure as children but is the entry point for user code).
(run-traced* f)Wrapper function for traced code execution. Executes f and returns the result. This function becomes the root of the traced call tree, consolidating user code under a single tree. The wrapper itself is filtered out.
Wrapper function for traced code execution. Executes f and returns the result. This function becomes the root of the traced call tree, consolidating user code under a single tree. The wrapper itself is filtered out.
(with-allocation-tracing expr)Creates a scope in which all JVM heap allocations and releases are tracked.
Auto-loads the native agent if it's not already loaded and available for the current platform. If the agent cannot be loaded, returns [nil result] without allocation tracking.
Returns a vector of [allocation-records result] where:
Note that the allocations tracked are not limited to the current
thread. Filter the returned records with allocation-on-thread? if that
is all you are concerned with.
Creates a scope in which all JVM heap allocations and releases are tracked.
Auto-loads the native agent if it's not already loaded and available for the
current platform. If the agent cannot be loaded, returns [nil result] without
allocation tracking.
Returns a vector of [allocation-records result] where:
- allocation-records: A sequence of maps containing detailed allocation data:
{:object-type - Class of allocated object
:object_size - Size in bytes
:call-class - Class that triggered allocation
:call-method - Method that triggered allocation
:call-file - Source file of allocation
:call-line - Line number of allocation
:alloc-class - Class doing allocation
:alloc-method - Method doing allocation
:alloc-file - Source file of allocator
:alloc-line - Line number of allocator
:thread - Thread ID of allocation
:freed - Whether object was freed}
- result: The value returned by the expression
Note that the allocations tracked are not limited to the current
thread. Filter the returned records with `allocation-on-thread?` if that
is all you are concerned with.(with-call-tracing & body)Creates a scope in which all method calls are traced to build a call tree.
Captures method entry and exit events during execution of body forms and builds a hierarchical call tree representing the observed call graph.
If the agent is not attached, returns [nil result] without tracing.
Returns a vector of [call-tree result] where:
Note: Method tracing captures ALL method calls across all threads. The call tree represents the aggregated call graph, not per-thread traces.
Note: The body is evaluated twice - once for warmup (untraced) to trigger lazy initialization, then once while tracing. The returned result is from the traced execution.
Warning: Method tracing has significant overhead. Use for profiling and debugging, not for production benchmarks.
Creates a scope in which all method calls are traced to build a call tree.
Captures method entry and exit events during execution of body forms and
builds a hierarchical call tree representing the observed call graph.
If the agent is not attached, returns [nil result] without tracing.
Returns a vector of [call-tree result] where:
- call-tree: A nested map structure representing the call hierarchy:
{:class - Class name in standard format (e.g. "myapp.Core")
:method - Method name (e.g. "process")
:file - Source file name (may be nil)
:line - Line number (-1 if unknown)
:call-count - Number of times this call path was executed
:children - Vector of child call nodes}
- result: The value returned by the body forms
Note: Method tracing captures ALL method calls across all threads.
The call tree represents the aggregated call graph, not per-thread traces.
Note: The body is evaluated twice - once for warmup (untraced) to trigger
lazy initialization, then once while tracing. The returned result is from
the traced execution.
Warning: Method tracing has significant overhead. Use for profiling and
debugging, not for production benchmarks.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |