Implement statistical errortrace-based profiling.
Add a mode to the profiler to use continuation marks inserted by the errortrace annotator instead of the runtime. Split `syntax/source-syntax` out from Typed Racket as a separate package, and use it to give better names for errortrace stack frames. Use caching to speed it up substantially when called repeatedly (as errortrace does). Also, document (internally) the format used by errortrace marks. original commit: 1e7eb34ba170b6aad77ee67c0f4b802950ff1a4b
This commit is contained in:
parent
88b9272144
commit
9f5169175b
|
@ -5,6 +5,8 @@
|
||||||
(define build-deps '("base"
|
(define build-deps '("base"
|
||||||
"scribble-lib"
|
"scribble-lib"
|
||||||
"profile-lib"
|
"profile-lib"
|
||||||
|
"errortrace-doc"
|
||||||
|
"errortrace-lib"
|
||||||
"racket-doc"))
|
"racket-doc"))
|
||||||
|
|
||||||
(define pkg-desc "documentation part of \"profile\"")
|
(define pkg-desc "documentation part of \"profile\"")
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#lang scribble/doc
|
#lang scribble/doc
|
||||||
|
|
||||||
@(require scribble/manual
|
@(require scribble/manual
|
||||||
(for-label racket/base racket/contract profile/sampler profile/analyzer))
|
(for-label racket/base racket/contract profile/sampler profile/analyzer
|
||||||
|
errortrace/errortrace-key))
|
||||||
|
|
||||||
@title[#:tag "sampler"]{Collecting Profile Information}
|
@title[#:tag "sampler"]{Collecting Profile Information}
|
||||||
|
|
||||||
|
@ -11,7 +12,8 @@
|
||||||
(listof (or/c thread? custodian?)))]
|
(listof (or/c thread? custodian?)))]
|
||||||
[delay (>=/c 0.0)]
|
[delay (>=/c 0.0)]
|
||||||
[super-cust custodian? (current-custodian)]
|
[super-cust custodian? (current-custodian)]
|
||||||
[custom-keys (listof any/c) '()])
|
[custom-keys (listof any/c) '()]
|
||||||
|
[#:use-errortrace? use-errortrace? any/c #f])
|
||||||
((symbol?) (any/c) . ->* . any/c)]{
|
((symbol?) (any/c) . ->* . any/c)]{
|
||||||
|
|
||||||
Creates a stack-snapshot collector thread, which tracks the given
|
Creates a stack-snapshot collector thread, which tracks the given
|
||||||
|
@ -26,6 +28,10 @@ When @racket[custom-keys] are provided, the sampler takes snapshots of the
|
||||||
continuation marks corresponding to the given keys, in addition to taking
|
continuation marks corresponding to the given keys, in addition to taking
|
||||||
snapshots of the stack.
|
snapshots of the stack.
|
||||||
|
|
||||||
|
When @racket[use-errortrace?] is not @racket[#f], the @racket[errortrace-key] is
|
||||||
|
used to sample snapshots instead of the implicit key used by
|
||||||
|
@racket[continuation-mark-set->context].
|
||||||
|
|
||||||
The resulting value is a controller function, which consumes a message
|
The resulting value is a controller function, which consumes a message
|
||||||
consisting of a symbol and an optional argument, and can affect the
|
consisting of a symbol and an optional argument, and can affect the
|
||||||
sampler. The following messages are currently supported:
|
sampler. The following messages are currently supported:
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
@(require scribble/manual
|
@(require scribble/manual
|
||||||
(for-label racket/base racket/contract profile profile/sampler
|
(for-label racket/base racket/contract profile profile/sampler
|
||||||
|
errortrace/errortrace-lib
|
||||||
(only-in profile/analyzer analyze-samples profile?)
|
(only-in profile/analyzer analyze-samples profile?)
|
||||||
(prefix-in text: profile/render-text)))
|
(prefix-in text: profile/render-text)))
|
||||||
|
|
||||||
|
@ -23,7 +24,8 @@ intended as a convenient tool for profiling code.
|
||||||
[#:periodic-renderer periodic-renderer
|
[#:periodic-renderer periodic-renderer
|
||||||
(or/c #f (list/c (>=/c 0.0)
|
(or/c #f (list/c (>=/c 0.0)
|
||||||
(profile? . -> . any/c)))
|
(profile? . -> . any/c)))
|
||||||
#f])
|
#f]
|
||||||
|
[#:use-errortrace? use-errortrace? any/c #f])
|
||||||
void?]{
|
void?]{
|
||||||
|
|
||||||
Executes the given @racket[thunk] and collect profiling data during
|
Executes the given @racket[thunk] and collect profiling data during
|
||||||
|
@ -40,6 +42,14 @@ can customize the profiling:
|
||||||
actually sampled. (The @racket[delay] value is passed on to
|
actually sampled. (The @racket[delay] value is passed on to
|
||||||
@racket[create-sampler], which creates the sampler thread.)}
|
@racket[create-sampler], which creates the sampler thread.)}
|
||||||
|
|
||||||
|
@item{When @racket[use-errortrace?] is not @racket[#f], more accurate
|
||||||
|
stack snapshots are captured using
|
||||||
|
@other-doc['(lib "errortrace/scribblings/errortrace.scrbl")]. Note that
|
||||||
|
when this is provided, it will only profile uncompiled files and files
|
||||||
|
compiled while using @racket[errortrace-compile-handler], and the profiled program
|
||||||
|
must be run using @commandline{racket -l errortrace -t program.rkt}
|
||||||
|
Removing compiled files (with extension @tt{.zo}) is sufficient to enable this.}
|
||||||
|
|
||||||
@item{Due to the statistical nature of the profiler, longer executions
|
@item{Due to the statistical nature of the profiler, longer executions
|
||||||
result in more accurate analysis. You can specify a number of
|
result in more accurate analysis. You can specify a number of
|
||||||
@racket[iterations] to repeat the @racket[thunk] to collect more
|
@racket[iterations] to repeat the @racket[thunk] to collect more
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#lang info
|
#lang info
|
||||||
|
|
||||||
(define collection "profile")
|
(define collection "profile")
|
||||||
(define deps '("base"))
|
(define deps '("base" "errortrace-lib"))
|
||||||
(define build-deps '("at-exp-lib"
|
(define build-deps '("at-exp-lib"
|
||||||
"rackunit-lib"))
|
"rackunit-lib"))
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,14 @@
|
||||||
#:repeat [rpt 1]
|
#:repeat [rpt 1]
|
||||||
#:threads [threads? #f]
|
#:threads [threads? #f]
|
||||||
#:render [renderer text:render]
|
#:render [renderer text:render]
|
||||||
#:periodic-renderer [periodic-renderer #f])
|
#:periodic-renderer [periodic-renderer #f]
|
||||||
|
#:use-errortrace? [et? #f])
|
||||||
(define cust (and threads? (make-custodian (current-custodian))))
|
(define cust (and threads? (make-custodian (current-custodian))))
|
||||||
(define sampler (create-sampler (if threads?
|
(define sampler (create-sampler (if threads?
|
||||||
(list cust (current-thread))
|
(list cust (current-thread))
|
||||||
(current-thread))
|
(current-thread))
|
||||||
delay))
|
delay
|
||||||
|
#:use-errortrace? et?))
|
||||||
(define periodic-thread
|
(define periodic-thread
|
||||||
(and periodic-renderer
|
(and periodic-renderer
|
||||||
(let ([delay (car periodic-renderer)]
|
(let ([delay (car periodic-renderer)]
|
||||||
|
|
|
@ -6,8 +6,24 @@
|
||||||
|
|
||||||
(provide create-sampler)
|
(provide create-sampler)
|
||||||
|
|
||||||
|
(require errortrace/errortrace-key)
|
||||||
|
|
||||||
|
;; (cons sexp srcloc) -> (cons symbol srcloc)
|
||||||
|
;; just take the first symbol we find
|
||||||
|
(define (errortrace-preprocess frame)
|
||||||
|
(cons (and (car frame)
|
||||||
|
(let loop ([e (car frame)])
|
||||||
|
(cond [(symbol? e) e]
|
||||||
|
[(pair? e) (loop (car e))]
|
||||||
|
[else (error 'errortrace-preprocess
|
||||||
|
"unexpected frame: ~a" frame)])))
|
||||||
|
(and (cdr frame)
|
||||||
|
(apply srcloc (cdr frame)))))
|
||||||
|
|
||||||
;; create-sampler : creates a sample collector thread, which tracks the given
|
;; create-sampler : creates a sample collector thread, which tracks the given
|
||||||
;; `to-track' value every `delay' seconds.
|
;; `to-track' value every `delay' seconds.
|
||||||
|
;; Uses errortrace annotations when #:use-errortrace? is specified, otherwise
|
||||||
|
;; uses the native stack traces provided by `cms->context`.
|
||||||
;; * The input value can be either a thread (track just that thread), a
|
;; * The input value can be either a thread (track just that thread), a
|
||||||
;; custodian (track all threads managed by the custodian), or a list of
|
;; custodian (track all threads managed by the custodian), or a list of
|
||||||
;; threads and/or custodians. If a custodian is given, it must be
|
;; threads and/or custodians. If a custodian is given, it must be
|
||||||
|
@ -57,7 +73,8 @@
|
||||||
;; same format as the output of continuation-mark-set->list*.
|
;; same format as the output of continuation-mark-set->list*.
|
||||||
(define (create-sampler to-track delay
|
(define (create-sampler to-track delay
|
||||||
[super-cust (current-custodian)]
|
[super-cust (current-custodian)]
|
||||||
[custom-keys #f])
|
[custom-keys #f]
|
||||||
|
#:use-errortrace? [do-errortrace #f])
|
||||||
;; the collected data
|
;; the collected data
|
||||||
(define snapshots '())
|
(define snapshots '())
|
||||||
;; listof (cons continuation-mark-key value/#f)
|
;; listof (cons continuation-mark-key value/#f)
|
||||||
|
@ -116,9 +133,15 @@
|
||||||
(set! snapshots
|
(set! snapshots
|
||||||
(cons (list* (thread-id t)
|
(cons (list* (thread-id t)
|
||||||
(current-process-milliseconds t)
|
(current-process-milliseconds t)
|
||||||
|
(if do-errortrace
|
||||||
|
(for/list ([frame (in-list
|
||||||
|
(continuation-mark-set->list
|
||||||
|
(continuation-marks t)
|
||||||
|
errortrace-key))])
|
||||||
|
(intern-entry (errortrace-preprocess frame)))
|
||||||
(map intern-entry
|
(map intern-entry
|
||||||
(continuation-mark-set->context
|
(continuation-mark-set->context
|
||||||
(continuation-marks t))))
|
(continuation-marks t)))))
|
||||||
snapshots)))]
|
snapshots)))]
|
||||||
[(custodian? t)
|
[(custodian? t)
|
||||||
(for-each loop (custodian-managed-list t super-cust))]
|
(for-each loop (custodian-managed-list t super-cust))]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user