Module: common-dylan-internals Author: Paul Haahr Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND /// Table definition macro define macro table-definer { define table ?table-name:name = { ?entries } } => { define constant ?table-name :: = make(
); begin let the-table = ?table-name; ?entries end; } { define table ?table-name:name :: ?table-type:name = { ?entries } } => { define constant ?table-name :: ?table-type = make(?table-type); begin let the-table = ?table-name; ?entries end; } entries: { } => { } { ?key:expression => ?value:expression, ... } => { the-table[ ?key ] := ?value; ... } end macro table-definer; /// Generic profiling macro // Syntax: // profiling // (cpu-time-seconds, // cpu-time-microseconds, // allocation) // ... // results // [bind cpu-time-seconds to CPU time in seconds] // [bind cpu-time-microseconds to CPU time in microseconds] // [bind allocation to total allocation] // ... // end /// Profiling macro define macro profiling { profiling (?options:*) ?body:body results ?result-body:body end } => { do-with-profiling(method () ?body end, profiling-keywords (?options) end, profiling-results (?options) ?result-body end) } end macro profiling; define macro profiling-keywords { profiling-keywords (?options:*) end } => { vector(?options) } options: { } => { } { ?keyword:name, ... } => { ?#"keyword", ... } { ?keyword:name = ?args:expression, ... } => { ?#"keyword", ... } end macro profiling-keywords; define macro profiling-results { profiling-results (?options:*) ?body:body end } => { method (state) ?options; ?body end } options: { } => { } { ?keyword:name, ... } => { let ?keyword = profiling-type-result(state, ?#"keyword"); ...} { ?keyword:name = ?args:expression, ... } => { let ?keyword = apply(profiling-type-result, state, ?#"keyword", ?args); ...} end macro profiling-results; /// Profiling protocols define constant = ; define open generic start-profiling-type (state :: , keyword :: ) => (); define open generic stop-profiling-type (state :: , keyword :: ) => (); define open generic profiling-type-result (state :: , keyword :: , #key, #all-keys) => (value); define function start-profiling (keywords :: ) => (state :: ) let state = make(); do(curry(start-profiling-type, state), keywords); state end function start-profiling; define function stop-profiling (state :: , keywords :: ) => () do(curry(stop-profiling-type, state), keywords) end function stop-profiling; define function do-with-profiling (body :: , keywords :: , result-function :: ) => (#rest results) let state = start-profiling(keywords); block () body() afterwards stop-profiling(state, keywords); result-function(state) end end function do-with-profiling; /// CPU time profiling define constant = one-of(#"cpu-time-seconds", #"cpu-time-microseconds"); define method profiling-type-result (state :: , keyword :: , #key) => (seconds :: ) state[keyword] end method profiling-type-result; define method start-profiling-type (state :: , keyword :: ) => () unless (element(state, #"cpu-profiling", default: #f)) primitive-start-timer(); state[#"cpu-profiling"] := #t end; end method start-profiling-type; define method stop-profiling-type (state :: , keyword :: ) => () when (element(state, #"cpu-profiling", default: #f)) let elapsed-time = primitive-stop-timer(); state[#"cpu-time-seconds"] := elapsed-time[0]; state[#"cpu-time-microseconds"] := elapsed-time[1]; state[#"cpu-profiling"] := #f end end method stop-profiling-type; /// Allocation profiling define method start-profiling-type (state :: , keyword == #"allocation") => () // To avoid possible overflow of allocation-count primitive-initialize-allocation-count(); end method start-profiling-type; define method stop-profiling-type (state :: , keyword == #"allocation") => () #f end method stop-profiling-type; define method profiling-type-result (state :: , keyword == #"allocation", #key) => (allocation :: ) raw-as-integer(primitive-allocation-count()); end method profiling-type-result; /// Allocation profiling statistics define constant $buffer-max = 8192; define thread variable dylan-string-buffer :: = ""; define method start-profiling-type (state :: , keyword == #"allocation-stats") => () primitive-begin-heap-alloc-stats(); end method start-profiling-type; define method stop-profiling-type (state :: , keyword == #"allocation-stats") => () #f end method stop-profiling-type; define method profiling-type-result (state :: , keyword == #"allocation-stats", #key description :: = "") => (allocation-stats) if (dylan-string-buffer.empty?) dylan-string-buffer := make(, size: $buffer-max, fill: '\0'); end if; let actual-buffer-size :: = raw-as-integer(primitive-end-heap-alloc-stats(primitive-string-as-raw(dylan-string-buffer))); format-out("\nProfiling Results: Heap Allocation Statistics: %s\n", description); write-console(dylan-string-buffer, end: actual-buffer-size); #f end method profiling-type-result;