The DISPATCH-PROFILER library

The dispatch profiler library exposes the multimethod dispatch profiling capability built in to the Open Dylan run-time library, making it possible to identify costly function calls in code. While dispatch coloring can identify calls that could and could not be optimized at compile time, dispatch profiling shows which calls have an actual effect on dynamic performance.

While this library can be quite useful, it was originally built as part of prototyping the dispatch mechanisms in Open Dylan, rather than as a polished tool. We hope that in the future this functionality can be incorporated into the debugger, making direct use of this library unnecessary.

Preparing for Profiling

Before dispatch profiling can be enabled during program execution, you will need to request that the compiler generate generic function call data structures (with slightly higher overhead) that are capable of collecting profile counts. This can be done by setting the OPEN_DYLAN_PROFILE_ALL_CALLS environment variable to a non-empty string when invoking the compiler:

$ OPEN_DYLAN_PROFILE_ALL_CALLS=1 dylan-compiler -build write-100mb

Report Output Format

After a profiling run, upon collection of dispatch statistics a profiling report can be written out. The report, sorted by COST field, lists generic functions and call sites for which any method invocations are present in the dispatch cache. The following fields appear in the report:

GENERICS

The count of generic functions in an application or library appearing in the report.

CLASSES

The total number of classes appearing in the application.

DEP-GFS

Not currently supported (based on an analysis currently commented out in the compiler).

CT-S-CALLS

Count of static calls (i.e., to a specific known method or slot accessor) as determined by the compiler for a library or application.

CT-D-CALLS

Count of dynamic calls (i.e., using full run-time dispatch through the <generic-function> object) as determined by the compiler for a library or application.

S/D

The ratio of (compile-time) static to dynamic calls.

RT-S-CALLS

The number of call sites in the library or application where a method was called but the COST was 0.

E-RT-S/D

The ratio of the total number of static calls (RT-S-CALLS plus CT-S-CALLS) to the total number of call sites identified by the compiler (CT-S-CALLS plus CT-D-CALLS).

POLY

The degree of polymorphism. For a given call site, represents the number of distinct methods called. For a generic function, library, or application, represents the total call site polymorphism divided by the number of call sites.

TOT SIZE

The memory storage size (in units of pointer-sized object slots) used by method dispatch cache nodes.

AVG SIZE

The average memory storage size (in units of pointer-sized object slots) of each associated method dispatch cache node.

HITS

The number of times that the dispatched method was found in the method dispatch cache.

COST

The total number of discriminator nodes traversed in order to locate the dispatched method in the cache. Useful as an approximation for the cost of method dispatch for a given call site or generic function.

COST/HIT

The average number of discriminator nodes that needed to be traversed in order to dispatch to the given method.

C-HITS

The total number of discriminator nodes traversed with successful discrimination tests.

C-TRIES

The total number of discriminator nodes traversed (identical to COST).

HIT-RATE

The ratio of C-HITS to C-TRIES.

The DISPATCH-PROFILER module

with-dispatch-profiling-report Statement Macro

Performs dispatch profiling over a body of code and prints out a profiling report.

Macro Call:

with-dispatch-profiling-report (#key keys)
  body
end

Parameters:
Discussion:

Executes the body with dispatch profiling enabled. Clears dispatch profiling counters before beginning execution, disables profiling and collects statistics at the end, and then writes out a report using print-dispatch-statistics.

Example:
define function main()
  with-dispatch-profiling-report (by-library?: #t, profile-base: "write-100mb-")
    let string = make(<string>, size: 100, fill: 'x');
    with-open-file (stream = "/tmp/100mb.dylan.txt", direction: #"output")
      for (i from 1 to 1024 * 1024)
        write(stream, string);
      end;
    end;
  end;
end function;
decache-all-generics Generic function

Restores dispatch caches of generic functions in the given library and dependent libraries to their initial states.

Signature:

decache-all-generics (library) => ()

Parameters:
  • library – An instance of <library>.

clear-dispatch-profiling Generic function

Resets call site profile counts and discriminator hit counts.

Signature:

clear-dispatch-profiling (library) => ()

Discussion:

Resets the call site profile counts and discriminator hit counts of all dispatch cache nodes for generic functions in the given library and dependent libraries.

Parameters:
  • library – An instance of <library>.

make-dispatch-statistics Generic function

Instantiates a new object for collecting dispatch statistics in preparation for report output.

Signature:

make-dispatch-statistics (shared-generic-caches?) => (#rest results)

Parameters:
  • shared-generic-caches? – An instance of <object>.

Values:
  • results – An instance of <application-profile-results>.

clear-dispatch-statistics! Generic function

Resets a <application-profile-results> to its initial state.

Signature:

clear-dispatch-statistics! (profile) => ()

Parameters:
  • profile – An instance of <application-profile-results>.

collect-dispatch-statistics Generic function

Traverses generic function call sites in the given library and collects dispatch statistics into the given profile results object.

Signature:

collect-dispatch-statistics (library profile) => ()

Parameters:
  • library – An instance of <library>.

  • profile – An instance of <application-profile-results>.

print-dispatch-statistics Generic function

Prints out a summary of dispatch profiling results.

Signature:

print-dispatch-statistics (app-results #key library profile-base full? by-library? hits-only? app-results-only? uncalled-methods? app-details?) => ()

Parameters:
  • app-results – An instance of <application-profile-results>.

  • library (#key) – An instance of false-or(<symbol>).

  • profile-base (#key) – An instance of false-or(<string>).

  • full? (#key) – An instance of <object>. Defaults to #t.

  • by-library? (#key) – An instance of <object>.

  • hits-only? (#key) – An instance of <object>. Defaults to #t.

  • app-results-only? (#key) – An instance of <object>.

  • uncalled-methods? (#key) – An instance of <object>.

  • app-details? (#key) – An instance of <object>. Defaults to #t.

Discussion:

If a particular library is requested (by name) and if by-library? is not false, then then profile-base must be provided, and the output is placed in files with names based on the profile base name, the library name, and the extension .prf. Otherwise, the results summary is written to *standard-output*.

If hits-only? is not false (the default) then call sites that never successfully used the method dispatch cache will be omitted from the report. If uncalled-methods? is true, then the report will list methods in the dispatch cache that were never invoked.

enable-generic-caches-only Generic function
Signature:

enable-generic-caches-only (library) => ()

Disable call-site method dispatch caches.

Parameters:
  • library

    An instance of <library>.

    Configures the dispatch mechanisms in the Open Dylan run-time to only use per-<generic-function> caches for method dispatch rather than call-site specific caches. This was intended to be used for comparison purposes during the development of the dispatch mechanisms.

enable-call-site-caches-only Generic function

Configures the dispatch mechanisms in the Open Dylan run-time to use call-site specific method dispatch caches.

Signature:

enable-call-site-caches-only (library) => ()

Parameters:
  • library – An instance of <library>.