usage info and comments
This commit is contained in:
parent
d38f8225fb
commit
04b7adbd89
|
@ -1,8 +1,73 @@
|
||||||
;; Does profiling things, mainly space measurements
|
;; Does space measurements using spatial
|
||||||
;; Copyright Andreas Bernauer, 2002
|
;; Copyright Andreas Bernauer, 2002
|
||||||
|
|
||||||
|
;;; Entry points:
|
||||||
|
;;;
|
||||||
|
;;; (PROFILE-SPACE [file-name])
|
||||||
|
;;;
|
||||||
|
;;; Save output of (SPACE) to a file. The file is either a (fresh)
|
||||||
|
;;; temporary file (created with CREATE-TEMP-FILE) or the one
|
||||||
|
;;; specified by FILE-NAME. In either cases the FILE-NAME is returned.
|
||||||
|
;;;
|
||||||
|
;;;
|
||||||
|
;;; (PROFILE-RESULT file-name nth)
|
||||||
|
;;;
|
||||||
|
;;; Return the result of the NTH output in the file named FILE-NAME as
|
||||||
|
;;; as SPACE-INFO object (see below for SPACE-INFO).
|
||||||
|
;;;
|
||||||
|
;;;
|
||||||
|
;;; (PROFILE-RESULTS file-name)
|
||||||
|
;;;
|
||||||
|
;;; Perform a repeated PROFILE-RESULT on FILE-NAME, returning a list
|
||||||
|
;;; that contains all SPACE-INFO objects (see below for SPACE-INFO).
|
||||||
|
;;;
|
||||||
|
;;;
|
||||||
|
;;; (MAKE-GNUPLOT-DATA output-file selector space-info-list)
|
||||||
|
;;;
|
||||||
|
;;; Creates a file named OUTPUT-FILE out of SPACE-INFO-LIST. The
|
||||||
|
;;; created file can be used with GNUPLOT (external program, not part
|
||||||
|
;;; of SUnet, http://www.gnuplot.info/) to create plot images.
|
||||||
|
;;; SELECTOR is a procedure that gets a SPACE-INFO object and returns
|
||||||
|
;;; an integer number. See below for possible SELECTORS on SPACE-INFO
|
||||||
|
;;; objects.
|
||||||
|
;;;
|
||||||
|
;;;
|
||||||
|
;;; SPACE-INFO object
|
||||||
|
;;;
|
||||||
|
;;; A container for all the information (SPACE) returns. Try
|
||||||
|
;;;
|
||||||
|
;;; > ,open spatial
|
||||||
|
;;; > (space)
|
||||||
|
;;;
|
||||||
|
;;; to see, what I mean. See the following record definition for
|
||||||
|
;;; selectors and mutators. The lists returned by the selectors may be
|
||||||
|
;;; inspected with PURE-COUNT, PURE-BYTES, IMPURE-COUNT, IMPURE-BYTES,
|
||||||
|
;;; TOTAL-COUNT, TOTAL-BYTES
|
||||||
|
;;;
|
||||||
|
;;;
|
||||||
|
;;; Possible strategy to profile space usage: Spread calls to
|
||||||
|
;;; PROFILE-SPACE throughout your program. After you've finished, call
|
||||||
|
;;; PROFILE-RESULTS and feed the resulting list into
|
||||||
|
;;; WRITE-GNUPLOT-DATA-FILE. Run GNUPLOT (external program) with this
|
||||||
|
;;; file to get a plot image.
|
||||||
|
;;;
|
||||||
|
;;;
|
||||||
|
;;;
|
||||||
|
;;; Example:
|
||||||
|
;;; (write-gnuplot-data-file "result.dat"
|
||||||
|
;;; (lambda (space-info)
|
||||||
|
;;; (total-bytes (space-info-total space-info)))
|
||||||
|
;;; (profile-results "concatenated-profile-files"))
|
||||||
|
;;;
|
||||||
|
;;; in GNUPLOT:
|
||||||
|
;;; set terminal png
|
||||||
|
;;; set output "result.png"
|
||||||
|
;;; plot "result.dat" title "My profile" with lines
|
||||||
|
|
||||||
|
|
||||||
(define *debug* #f)
|
(define *debug* #f)
|
||||||
|
|
||||||
|
;; SPACE-INFO
|
||||||
(define-record-type space-info :space-info
|
(define-record-type space-info :space-info
|
||||||
(make-space-info pair symbol vector closure location cell channel port
|
(make-space-info pair symbol vector closure location cell channel port
|
||||||
ratnum record continuation extended-number template
|
ratnum record continuation extended-number template
|
||||||
|
@ -32,6 +97,7 @@
|
||||||
(bignum space-info-bignum set-space-info-bignum!)
|
(bignum space-info-bignum set-space-info-bignum!)
|
||||||
(total space-info-total set-space-info-total!))
|
(total space-info-total set-space-info-total!))
|
||||||
|
|
||||||
|
;; FIELD-INSPECTORS
|
||||||
(define pure-count first)
|
(define pure-count first)
|
||||||
(define pure-bytes second)
|
(define pure-bytes second)
|
||||||
(define impure-count third)
|
(define impure-count third)
|
||||||
|
@ -41,9 +107,8 @@
|
||||||
|
|
||||||
|
|
||||||
(define *run-count* 0)
|
(define *run-count* 0)
|
||||||
(define (set-run-count! x)
|
|
||||||
(set! *run-count* x))
|
|
||||||
|
|
||||||
|
;; PROFILE-SPACE writes result of call to (SPACE) to a file
|
||||||
(define (profile-space . maybe-file-name)
|
(define (profile-space . maybe-file-name)
|
||||||
(let ((file-name
|
(let ((file-name
|
||||||
(:optional maybe-file-name
|
(:optional maybe-file-name
|
||||||
|
@ -55,13 +120,48 @@
|
||||||
(close out))
|
(close out))
|
||||||
file-name))
|
file-name))
|
||||||
|
|
||||||
|
;; PROFILE-RESULT returns a SPACE-INFO object representing the output
|
||||||
|
;; of (SPACE) of the NTH run. If there is no such run, 'EOF is returned.
|
||||||
(define (profile-result file-name nth)
|
(define (profile-result file-name nth)
|
||||||
(let* ((in (open-input-file file-name))
|
(let* ((in (open-input-file file-name))
|
||||||
(result (get-space-info in nth)))
|
(result (get-space-info in nth)))
|
||||||
(close in)
|
(close in)
|
||||||
result))
|
result))
|
||||||
|
|
||||||
|
;; PROFILE-RESULTS returns a list of all SPACE-INFO objects that may
|
||||||
|
;; be represented in FILE-NAME.
|
||||||
|
(define (profile-results file-name)
|
||||||
|
(let ((in (open-input-file file-name)))
|
||||||
|
(let loop ((space-info (get-space-info in 'first))
|
||||||
|
(result '()))
|
||||||
|
(if (eq? 'eof space-info)
|
||||||
|
(reverse result)
|
||||||
|
(loop (get-space-info in 'first)
|
||||||
|
(cons space-info result))))))
|
||||||
|
|
||||||
|
|
||||||
|
;; WRITE-GNUPLOT-DATA-FILE converts a SPACE-INFO-LIST into a data file
|
||||||
|
;; for a simple 2D plot, readable by GNUPLOT (external program, not
|
||||||
|
;; part of SUnet, http://www.gnuplot.info/)
|
||||||
|
(define (write-gnuplot-data-file output-file selector space-info-list)
|
||||||
|
(let ((out (open-output-file output-file)))
|
||||||
|
(display "# generated by profile.scm\n" out)
|
||||||
|
(let loop ((count 0)
|
||||||
|
(space-info-list space-info-list))
|
||||||
|
(if (null? space-info-list)
|
||||||
|
(close out)
|
||||||
|
(begin
|
||||||
|
(display count out)
|
||||||
|
(display " " out)
|
||||||
|
(display (selector (car space-info-list)) out)
|
||||||
|
(newline out)
|
||||||
|
(loop (+ 1 count)
|
||||||
|
(cdr space-info-list)))))))
|
||||||
|
|
||||||
|
;; GET-SPACE-INFO returns the result of the NTH call to (SPACE) stored
|
||||||
|
;; in IN. If NTH is 'FIRST, the SPACE-INFO object representing the
|
||||||
|
;; next run is returned. If EOF is reached before a run is found, 'EOF
|
||||||
|
;; is returned.
|
||||||
(define (get-space-info in nth)
|
(define (get-space-info in nth)
|
||||||
(if (eof-object? (skip-runs in nth))
|
(if (eof-object? (skip-runs in nth))
|
||||||
'eof
|
'eof
|
||||||
|
@ -92,19 +192,26 @@
|
||||||
(get-record "bignum" assoc-list)
|
(get-record "bignum" assoc-list)
|
||||||
(get-record "total" assoc-list))))))
|
(get-record "total" assoc-list))))))
|
||||||
|
|
||||||
|
;; GET-RECORD returns the data of the element in ASSOC-LIST indexed by KEY.
|
||||||
(define (get-record key assoc-list)
|
(define (get-record key assoc-list)
|
||||||
(let ((record (assoc key assoc-list)))
|
(let ((record (assoc key assoc-list)))
|
||||||
(if record
|
(if record
|
||||||
(cdr record)
|
(cdr record)
|
||||||
(error "wrong data format - field missing" 'pair))))
|
(error "wrong data format - field missing" 'pair))))
|
||||||
|
|
||||||
|
;; SKIP-HEADERS just skips two lines in IN (the header lines of a
|
||||||
|
;; (SPACE) outpout)
|
||||||
(define (skip-headers in)
|
(define (skip-headers in)
|
||||||
(read-line in)
|
(read-line in)
|
||||||
(read-line in))
|
(read-line in))
|
||||||
|
|
||||||
;; skip runs until write-out is reached
|
;; RUN-REGEXP matches the run number in the output file of
|
||||||
|
;; PROFILE-SPACE
|
||||||
(define run-regexp (rx "Run #" (submatch (* digit))))
|
(define run-regexp (rx "Run #" (submatch (* digit))))
|
||||||
|
|
||||||
|
;; SKIP-RUNS goes forward in IN, until a run in IN with number NTH is
|
||||||
|
;; found. If NTH is 'FIRST, just the next reachable run is reached. If
|
||||||
|
;; EOF occurs while searching, 'EOF is returned.
|
||||||
(define (skip-runs in nth)
|
(define (skip-runs in nth)
|
||||||
(let loop ((line (read-line in)))
|
(let loop ((line (read-line in)))
|
||||||
(if (eof-object? line)
|
(if (eof-object? line)
|
||||||
|
@ -117,9 +224,14 @@
|
||||||
#t
|
#t
|
||||||
(loop (read-line in)))))))
|
(loop (read-line in)))))))
|
||||||
|
|
||||||
|
;; TRIM-STRING->NUMBER returns the number stored in S, perhaps padded
|
||||||
|
;; with spaces on its left: (TRIM-STRING->NUMBER " 123") ==> 123
|
||||||
(define (trim-string->number s)
|
(define (trim-string->number s)
|
||||||
(string->number (string-trim s)))
|
(string->number (string-trim s)))
|
||||||
|
|
||||||
|
;; READ-DATA parses the output of (SPACES). It expects the next line
|
||||||
|
;; in IN to be the first data line (not a header). It returns an
|
||||||
|
;; a-list (row name . data-list)
|
||||||
(define (read-data in)
|
(define (read-data in)
|
||||||
(let loop ((count 0)
|
(let loop ((count 0)
|
||||||
(line (read-line in))
|
(line (read-line in))
|
||||||
|
@ -140,27 +252,3 @@
|
||||||
assoc-list))
|
assoc-list))
|
||||||
assoc-list)))
|
assoc-list)))
|
||||||
|
|
||||||
(define (profile-results file-name)
|
|
||||||
(let ((in (open-input-file file-name)))
|
|
||||||
(let loop ((space-info (get-space-info in 'first))
|
|
||||||
(result '()))
|
|
||||||
(if (eq? 'eof space-info)
|
|
||||||
(reverse result)
|
|
||||||
(loop (get-space-info in 'first)
|
|
||||||
(cons space-info result))))))
|
|
||||||
|
|
||||||
|
|
||||||
(define (make-gnuplot-data output-file selector space-info-list)
|
|
||||||
(let ((out (open-output-file output-file)))
|
|
||||||
(display "# generated by profile.scm\n" out)
|
|
||||||
(let loop ((count 0)
|
|
||||||
(space-info-list space-info-list))
|
|
||||||
(if (null? space-info-list)
|
|
||||||
(close out)
|
|
||||||
(begin
|
|
||||||
(display count out)
|
|
||||||
(display " " out)
|
|
||||||
(display (selector (car space-info-list)) out)
|
|
||||||
(newline out)
|
|
||||||
(loop (+ 1 count)
|
|
||||||
(cdr space-info-list)))))))
|
|
Loading…
Reference in New Issue