"tools.disassembler"
"tools.dispatch"
"tools.memory"
- "tools.profiler"
+ "tools.counting-profiler"
"tools.test"
"tools.time"
"tools.threads"
"tools.dispatch"
"tools.errors"
"tools.memory"
- "tools.profiler"
+ "tools.counting-profiler"
"tools.test"
"tools.threads"
"tools.time"
combinators.short-circuit locals locals.backend locals.types
combinators.private stack-checker.values generic.single
generic.single.private alien.libraries tools.dispatch.private
-tools.profiler.private macros
+tools.counting-profiler.private macros
stack-checker.alien
stack-checker.state
stack-checker.errors
--- /dev/null
+Slava Pestov
--- /dev/null
+USING: tools.counting-profiler.private tools.time tools.crossref
+help.markup help.syntax quotations io strings words definitions ;
+IN: tools.counting-profiler
+
+ARTICLE: "profiler-limitations" "Profiler limitations"
+"Certain optimizations performed by the compiler can inhibit accurate call counting:"
+{ $list
+ "Calls to open-coded intrinsics are not counted. Certain words are open-coded as inline machine code, and in some cases optimized out altogether; this includes stack shuffling operations, conditionals, and many object allocation operations."
+ { "Calls to " { $link POSTPONE: inline } " words are not counted." }
+ { "Calls to methods which were inlined as a result of type inference are not counted." }
+ "Tail-recursive loops will only count the initial invocation of the word, not every tail call."
+} ;
+
+ARTICLE: "profiling" "Profiling code"
+"The " { $vocab-link "tools.counting-profiler" } " vocabulary implements a simple call counting profiler."
+$nl
+"Quotations can be passed to a combinator which calls them with the profiler enabled:"
+{ $subsections profile }
+"After a quotation has been profiled, call counts can be presented in various ways:"
+{ $subsections
+ profile.
+ vocab-profile.
+ usage-profile.
+ vocabs-profile.
+ method-profile.
+ "profiler-limitations"
+}
+{ $see-also "ui.tools.profiler" "tools.annotations" "timing" } ;
+
+ABOUT: "profiling"
+
+HELP: counters
+{ $values { "words" "a sequence of words" } { "alist" "an association list mapping words to integers" } }
+{ $description "Outputs an association list of word call counts." } ;
+
+HELP: counters.
+{ $values { "assoc" "an association list mapping words to integers" } }
+{ $description "Prints an association list of call counts to " { $link output-stream } "." } ;
+
+HELP: profile
+{ $values { "quot" quotation } }
+{ $description "Calls the quotation while collecting word call counts, which can then be displayed using " { $link profile. } " or related words." } ;
+
+HELP: profile.
+{ $description "Prints a table of call counts from the most recent invocation of " { $link profile } "." } ;
+
+HELP: vocab-profile.
+{ $values { "vocab" string } }
+{ $description "Prints a table of call counts from the most recent invocation of " { $link profile } ", for words in the " { $snippet "vocab" } " vocabulary only." }
+{ $examples { $code "\"math\" vocab-profile." } } ;
+
+HELP: usage-profile.
+{ $values { "word" word } }
+{ $description "Prints a table of call counts from the most recent invocation of " { $link profile } ", for words which directly call " { $snippet "word" } " only." }
+{ $notes "This word obtains the list of static usages with the " { $link smart-usage } " word, and is not aware of dynamic call history. Consider the following scenario. A word " { $snippet "X" } " can execute word " { $snippet "Y" } " in a conditional branch, and " { $snippet "X" } " is executed many times during the profiling run, but this particular branch executing " { $snippet "Y" } " is never taken. However, some other word does execute " { $snippet "Y" } " multiple times. Then " { $snippet "\\ Y usage-profile." } " will list a number of calls to " { $snippet "X" } ", even though " { $snippet "Y" } " was never executed " { $emphasis "from" } " " { $snippet "X" } "." }
+{ $examples { $code "\\ + usage-profile." } } ;
+
+HELP: vocabs-profile.
+{ $description "Print a table of cumilative call counts for each vocabulary. Vocabularies whose words were not called are supressed from the output." } ;
+
+HELP: method-profile.
+{ $description "Print a table of cumilative call counts for each method. Methods which were not called are supressed from the output." } ;
+
+HELP: profiling
+{ $values { "?" "a boolean" } }
+{ $description "Internal primitive to switch on call counting. This word should not be used; instead use " { $link profile } "." } ;
+
+{ time profile } related-words
--- /dev/null
+USING: accessors tools.counting-profiler tools.test kernel memory math
+threads alien alien.c-types tools.counting-profiler.private sequences
+compiler.test compiler.units words arrays ;
+IN: tools.counting-profiler.tests
+
+[ t ] [
+ \ length counter>>
+ 10 [ { } length drop ] times
+ \ length counter>> =
+] unit-test
+
+[ ] [ [ 3 [ gc ] times ] profile ] unit-test
+
+[ ] [ [ 1000000 sleep ] profile ] unit-test
+
+[ ] [ profile. ] unit-test
+
+[ ] [ vocabs-profile. ] unit-test
+
+[ ] [ "kernel.private" vocab-profile. ] unit-test
+
+[ ] [ \ + usage-profile. ] unit-test
+
+: callback-test ( -- callback ) void { } cdecl [ ] alien-callback ;
+
+: indirect-test ( callback -- ) void { } cdecl alien-indirect ;
+
+: foobar ( -- ) ;
+
+[
+ [ ] [ callback-test indirect-test ] unit-test
+ foobar
+] profile
+
+[ 1 ] [ \ foobar counter>> ] unit-test
+
+: fooblah ( -- ) { } [ ] like call( -- ) ;
+
+: foobaz ( -- ) fooblah fooblah ;
+
+[ foobaz ] profile
+
+[ 1 ] [ \ foobaz counter>> ] unit-test
+
+[ 2 ] [ \ fooblah counter>> ] unit-test
+
+: recompile-while-profiling-test ( -- ) ;
+
+[ ] [
+ [
+ 333 [ recompile-while-profiling-test ] times
+ { recompile-while-profiling-test } compile
+ 333 [ recompile-while-profiling-test ] times
+ ] profile
+] unit-test
+
+[ 666 ] [ \ recompile-while-profiling-test counter>> ] unit-test
+
+[ ] [ [ [ ] compile-call ] profile ] unit-test
+
+[ [ gensym execute ] profile ] [ undefined? ] must-fail-with
+
+: crash-bug-1 ( -- x ) "hi" <uninterned-word> ;
+: crash-bug-2 ( -- ) 100000 [ crash-bug-1 drop ] times ;
+
+[ ] [ [ crash-bug-2 ] profile ] unit-test
+
+[ 1 ] [
+ [
+ [ [ ] ( -- ) define-temp ] with-compilation-unit
+ dup execute( -- )
+ ] profile
+ counter>>
+] unit-test
+
+! unwind_native_frames() would fail if profiling was enabled
+! because the jit-profiling stub would clobber a parameter register
+! on x86-64
+[ [ -10 f <array> ] profile ] must-fail
--- /dev/null
+! Copyright (C) 2007, 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors words sequences math prettyprint kernel arrays
+io io.styles namespaces assocs kernel.private strings
+combinators sorting math.parser vocabs definitions
+tools.counting-profiler.private tools.crossref continuations generic
+compiler.units compiler.crossref sets classes fry ;
+FROM: sets => members ;
+IN: tools.counting-profiler
+
+: profile ( quot -- )
+ [ t profiling call ] [ f profiling ] [ ] cleanup ; inline
+
+: filter-counts ( alist -- alist' )
+ [ second 0 > ] filter ;
+
+: map-counters ( obj quot -- alist )
+ { } map>assoc filter-counts ; inline
+
+: counters ( words -- alist )
+ [ dup counter>> ] map-counters ;
+
+: cumulative-counters ( obj quot -- alist )
+ '[ dup @ [ counter>> ] map-sum ] map-counters ; inline
+
+: vocab-counters ( -- alist )
+ vocabs [ words [ predicate? not ] filter ] cumulative-counters ;
+
+: generic-counters ( -- alist )
+ all-words [ subwords ] cumulative-counters ;
+
+: methods-on ( class -- methods )
+ dup implementors [ lookup-method ] with map ;
+
+: class-counters ( -- alist )
+ classes [ methods-on ] cumulative-counters ;
+
+: method-counters ( -- alist )
+ all-words [ subwords ] map concat counters ;
+
+: profiler-usage ( word -- words )
+ [ smart-usage [ word? ] filter ]
+ [ generic-call-sites-of keys ]
+ [ effect-dependencies-of keys ]
+ tri 3append members ;
+
+: usage-counters ( word -- alist )
+ profiler-usage counters ;
+
+: counters. ( assoc -- )
+ sort-values simple-table. ;
+
+: profile. ( -- )
+ "Call counts for all words:" print
+ all-words counters counters. ;
+
+: vocab-profile. ( vocab -- )
+ "Call counts for words in the " write
+ dup dup lookup-vocab write-object
+ " vocabulary:" print
+ words counters counters. ;
+
+: usage-profile. ( word -- )
+ "Call counts for words which call " write
+ dup pprint
+ ":" print
+ usage-counters counters. ;
+
+: vocabs-profile. ( -- )
+ "Call counts for all vocabularies:" print
+ vocab-counters counters. ;
+
+: generic-profile. ( -- )
+ "Call counts for methods on generic words:" print
+ generic-counters counters. ;
+
+: class-profile. ( -- )
+ "Call counts for methods on classes:" print
+ class-counters counters. ;
+
+: method-profile. ( -- )
+ "Call counts for all methods:" print
+ method-counters counters. ;
--- /dev/null
+Call counting profiler
+++ /dev/null
-Slava Pestov
+++ /dev/null
-USING: tools.profiler.private tools.time tools.crossref
-help.markup help.syntax quotations io strings words definitions ;
-IN: tools.profiler
-
-ARTICLE: "profiler-limitations" "Profiler limitations"
-"Certain optimizations performed by the compiler can inhibit accurate call counting:"
-{ $list
- "Calls to open-coded intrinsics are not counted. Certain words are open-coded as inline machine code, and in some cases optimized out altogether; this includes stack shuffling operations, conditionals, and many object allocation operations."
- { "Calls to " { $link POSTPONE: inline } " words are not counted." }
- { "Calls to methods which were inlined as a result of type inference are not counted." }
- "Tail-recursive loops will only count the initial invocation of the word, not every tail call."
-} ;
-
-ARTICLE: "profiling" "Profiling code"
-"The " { $vocab-link "tools.profiler" } " vocabulary implements a simple call counting profiler."
-$nl
-"Quotations can be passed to a combinator which calls them with the profiler enabled:"
-{ $subsections profile }
-"After a quotation has been profiled, call counts can be presented in various ways:"
-{ $subsections
- profile.
- vocab-profile.
- usage-profile.
- vocabs-profile.
- method-profile.
- "profiler-limitations"
-}
-{ $see-also "ui.tools.profiler" "tools.annotations" "timing" } ;
-
-ABOUT: "profiling"
-
-HELP: counters
-{ $values { "words" "a sequence of words" } { "alist" "an association list mapping words to integers" } }
-{ $description "Outputs an association list of word call counts." } ;
-
-HELP: counters.
-{ $values { "assoc" "an association list mapping words to integers" } }
-{ $description "Prints an association list of call counts to " { $link output-stream } "." } ;
-
-HELP: profile
-{ $values { "quot" quotation } }
-{ $description "Calls the quotation while collecting word call counts, which can then be displayed using " { $link profile. } " or related words." } ;
-
-HELP: profile.
-{ $description "Prints a table of call counts from the most recent invocation of " { $link profile } "." } ;
-
-HELP: vocab-profile.
-{ $values { "vocab" string } }
-{ $description "Prints a table of call counts from the most recent invocation of " { $link profile } ", for words in the " { $snippet "vocab" } " vocabulary only." }
-{ $examples { $code "\"math\" vocab-profile." } } ;
-
-HELP: usage-profile.
-{ $values { "word" word } }
-{ $description "Prints a table of call counts from the most recent invocation of " { $link profile } ", for words which directly call " { $snippet "word" } " only." }
-{ $notes "This word obtains the list of static usages with the " { $link smart-usage } " word, and is not aware of dynamic call history. Consider the following scenario. A word " { $snippet "X" } " can execute word " { $snippet "Y" } " in a conditional branch, and " { $snippet "X" } " is executed many times during the profiling run, but this particular branch executing " { $snippet "Y" } " is never taken. However, some other word does execute " { $snippet "Y" } " multiple times. Then " { $snippet "\\ Y usage-profile." } " will list a number of calls to " { $snippet "X" } ", even though " { $snippet "Y" } " was never executed " { $emphasis "from" } " " { $snippet "X" } "." }
-{ $examples { $code "\\ + usage-profile." } } ;
-
-HELP: vocabs-profile.
-{ $description "Print a table of cumilative call counts for each vocabulary. Vocabularies whose words were not called are supressed from the output." } ;
-
-HELP: method-profile.
-{ $description "Print a table of cumilative call counts for each method. Methods which were not called are supressed from the output." } ;
-
-HELP: profiling
-{ $values { "?" "a boolean" } }
-{ $description "Internal primitive to switch on call counting. This word should not be used; instead use " { $link profile } "." } ;
-
-{ time profile } related-words
+++ /dev/null
-USING: accessors tools.profiler tools.test kernel memory math
-threads alien alien.c-types tools.profiler.private sequences
-compiler.test compiler.units words arrays ;
-IN: tools.profiler.tests
-
-[ t ] [
- \ length counter>>
- 10 [ { } length drop ] times
- \ length counter>> =
-] unit-test
-
-[ ] [ [ 3 [ gc ] times ] profile ] unit-test
-
-[ ] [ [ 1000000 sleep ] profile ] unit-test
-
-[ ] [ profile. ] unit-test
-
-[ ] [ vocabs-profile. ] unit-test
-
-[ ] [ "kernel.private" vocab-profile. ] unit-test
-
-[ ] [ \ + usage-profile. ] unit-test
-
-: callback-test ( -- callback ) void { } cdecl [ ] alien-callback ;
-
-: indirect-test ( callback -- ) void { } cdecl alien-indirect ;
-
-: foobar ( -- ) ;
-
-[
- [ ] [ callback-test indirect-test ] unit-test
- foobar
-] profile
-
-[ 1 ] [ \ foobar counter>> ] unit-test
-
-: fooblah ( -- ) { } [ ] like call( -- ) ;
-
-: foobaz ( -- ) fooblah fooblah ;
-
-[ foobaz ] profile
-
-[ 1 ] [ \ foobaz counter>> ] unit-test
-
-[ 2 ] [ \ fooblah counter>> ] unit-test
-
-: recompile-while-profiling-test ( -- ) ;
-
-[ ] [
- [
- 333 [ recompile-while-profiling-test ] times
- { recompile-while-profiling-test } compile
- 333 [ recompile-while-profiling-test ] times
- ] profile
-] unit-test
-
-[ 666 ] [ \ recompile-while-profiling-test counter>> ] unit-test
-
-[ ] [ [ [ ] compile-call ] profile ] unit-test
-
-[ [ gensym execute ] profile ] [ undefined? ] must-fail-with
-
-: crash-bug-1 ( -- x ) "hi" <uninterned-word> ;
-: crash-bug-2 ( -- ) 100000 [ crash-bug-1 drop ] times ;
-
-[ ] [ [ crash-bug-2 ] profile ] unit-test
-
-[ 1 ] [
- [
- [ [ ] ( -- ) define-temp ] with-compilation-unit
- dup execute( -- )
- ] profile
- counter>>
-] unit-test
-
-! unwind_native_frames() would fail if profiling was enabled
-! because the jit-profiling stub would clobber a parameter register
-! on x86-64
-[ [ -10 f <array> ] profile ] must-fail
+++ /dev/null
-! Copyright (C) 2007, 2010 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors words sequences math prettyprint kernel arrays
-io io.styles namespaces assocs kernel.private strings
-combinators sorting math.parser vocabs definitions
-tools.profiler.private tools.crossref continuations generic
-compiler.units compiler.crossref sets classes fry ;
-FROM: sets => members ;
-IN: tools.profiler
-
-: profile ( quot -- )
- [ t profiling call ] [ f profiling ] [ ] cleanup ; inline
-
-: filter-counts ( alist -- alist' )
- [ second 0 > ] filter ;
-
-: map-counters ( obj quot -- alist )
- { } map>assoc filter-counts ; inline
-
-: counters ( words -- alist )
- [ dup counter>> ] map-counters ;
-
-: cumulative-counters ( obj quot -- alist )
- '[ dup @ [ counter>> ] map-sum ] map-counters ; inline
-
-: vocab-counters ( -- alist )
- vocabs [ words [ predicate? not ] filter ] cumulative-counters ;
-
-: generic-counters ( -- alist )
- all-words [ subwords ] cumulative-counters ;
-
-: methods-on ( class -- methods )
- dup implementors [ lookup-method ] with map ;
-
-: class-counters ( -- alist )
- classes [ methods-on ] cumulative-counters ;
-
-: method-counters ( -- alist )
- all-words [ subwords ] map concat counters ;
-
-: profiler-usage ( word -- words )
- [ smart-usage [ word? ] filter ]
- [ generic-call-sites-of keys ]
- [ effect-dependencies-of keys ]
- tri 3append members ;
-
-: usage-counters ( word -- alist )
- profiler-usage counters ;
-
-: counters. ( assoc -- )
- sort-values simple-table. ;
-
-: profile. ( -- )
- "Call counts for all words:" print
- all-words counters counters. ;
-
-: vocab-profile. ( vocab -- )
- "Call counts for words in the " write
- dup dup lookup-vocab write-object
- " vocabulary:" print
- words counters counters. ;
-
-: usage-profile. ( word -- )
- "Call counts for words which call " write
- dup pprint
- ":" print
- usage-counters counters. ;
-
-: vocabs-profile. ( -- )
- "Call counts for all vocabularies:" print
- vocab-counters counters. ;
-
-: generic-profile. ( -- )
- "Call counts for methods on generic words:" print
- generic-counters counters. ;
-
-: class-profile. ( -- )
- "Call counts for methods on classes:" print
- class-counters counters. ;
-
-: method-profile. ( -- )
- "Call counts for all methods:" print
- method-counters counters. ;
+++ /dev/null
-Call counting profiler
USING: help.tips help.markup help.syntax ui.operations
-tools.walker tools.time tools.profiler ui.tools.operations ;
+tools.walker tools.time tools.counting-profiler ui.tools.operations ;
TIP: "Press " { $operation com-stack-effect } " to print the stack effect of the code in the input field without executing it (" { $link "inference" } ")." ;
USING: continuations definitions generic help.topics threads
stack-checker summary io.pathnames io.styles kernel namespaces
parser prettyprint quotations tools.crossref tools.annotations
-editors tools.profiler tools.test tools.time tools.walker vocabs
+editors tools.counting-profiler tools.test tools.time tools.walker vocabs
vocabs.loader words sequences classes compiler.errors
compiler.units accessors vocabs.parser macros.expander ui
ui.tools.browser ui.tools.listener ui.tools.listener.completion
USING: accessors arrays assocs combinators.short-circuit
combinators.smart definitions.icons fry kernel locals
math.order models models.search models.sort present see
-sequences tools.profiler ui.baseline-alignment ui.commands
+sequences tools.counting-profiler ui.baseline-alignment ui.commands
ui.gadgets ui.gadgets.borders ui.gadgets.buttons
ui.gadgets.labeled ui.gadgets.labels ui.gadgets.packs
ui.gadgets.search-tables ui.gadgets.status-bar
USING: editors help.markup help.syntax summary inspector io io.styles
-listener parser prettyprint tools.profiler tools.walker ui.commands
+listener parser prettyprint tools.counting-profiler tools.walker ui.commands
ui.gadgets.panes ui.gadgets.presentations ui.operations
ui.tools.operations ui.tools.profiler ui.tools.common vocabs see
help.tips ;
"threads.private"
"tools.dispatch.private"
"tools.memory.private"
- "tools.profiler.private"
+ "tools.counting-profiler.private"
"words"
"words.private"
"vectors"
{ "retainstack-for" "threads.private" "primitive_retainstack_for" ( context -- array ) }
{ "dispatch-stats" "tools.dispatch.private" "primitive_dispatch_stats" ( -- stats ) }
{ "reset-dispatch-stats" "tools.dispatch.private" "primitive_reset_dispatch_stats" ( -- ) }
- { "profiling" "tools.profiler.private" "primitive_profiling" ( ? -- ) }
+ { "profiling" "tools.counting-profiler.private" "primitive_counting_profiler" ( ? -- ) }
{ "optimized?" "words" "primitive_optimized_p" ( word -- ? ) }
{ "word-code" "words" "primitive_word_code" ( word -- start end ) }
{ "(word)" "words.private" "primitive_word" ( name vocab hashcode -- word ) }