[gambit-list] Profiling for memory usage
Marc Feeley
feeley at iro.umontreal.ca
Sat Aug 12 07:41:40 EDT 2023
> On Aug 11, 2023, at 4:03 AM, Sven Hartrumpf <hartrumpf at gmx.net> wrote:
>
> Hi.
>
> I profile Gambit-compiled programs for runtime of functions
> by using the "perf" tool.
>
> But how can I profile programs for memory usage (allocations)
> of functions?
>
> Greetings
> Sven
There is no standard way to profile a program to discover which procedures do the most memory allocations. The “time” macro can be used to determine how much is allocated for the evaluation of a specific expression, but that is a rather blunt tool. There is a ##get-bytes-allocated! primitive that can be used to measure how much memory has been allocated by the program up to now. A profiling tool can then be built on top of that. For example below is the file prof-space.scm which defines a “define-prof” macro that behaves like “define” but that calculates the amount of memory allocated by the defined procedure. You could modify this code to your specific needs.
Marc
;; file: prof-space.scm
(define ##space-usage (make-table size: 100))
(define ##ba-cell (f64vector 0.0))
(define (##profile-space var thunk)
(let* ((_ (##get-bytes-allocated! ##ba-cell 0))
(before (##flonum->fixnum (f64vector-ref ##ba-cell 0)))
(result (thunk))
(_ (##get-bytes-allocated! ##ba-cell 0))
(after (##flonum->fixnum (f64vector-ref ##ba-cell 0)))
(bytes-allocated (- (- after before) ##profile-space-offset)))
(if var
(begin
(table-set! ##space-usage
var
(+ bytes-allocated (table-ref ##space-usage var 0)))
result)
bytes-allocated)))
(define ##profile-space-offset 0)
(set! ##profile-space-offset (##profile-space #f (##lambda () 42)))
(define (##display-space-usage)
(for-each
(lambda (bucket)
(println (car bucket) " = " (cdr bucket)))
(list-sort (lambda (x y) (< (cdr x) (cdr y))) (table->list ##space-usage))))
(define-macro (define-prof pattern . rest)
;; Note: the name "define-prof" could be replaced by "define" to
;; profile all procedure definitions.
(define (should-profile? var) #t) ;; profile everything
(define (procedure-definition var lambda-expr)
`(##define ,var
,(if (should-profile? var)
`(##lambda ,(cadr lambda-expr)
(##profile-space ',var
(##lambda () ,@(cddr lambda-expr))))
lambda-expr)))
(cond ((and (symbol? pattern)
(pair? rest)
(not (pair? (cdr rest)))
(pair? (car rest))
(memq (caar rest) '(lambda ##lambda)))
(procedure-definition pattern (car rest)))
((pair? pattern)
(procedure-definition (car pattern) `(##lambda ,(cdr pattern) , at rest)))
(else
`(##define ,pattern , at rest))))
;; code being profiled
(define-prof (f n) (make-vector n)) ;; allocates an n element vector
(define-prof (g n) (make-u8vector n)) ;; allocates an n element u8vector
(define-prof (h n) (iota n)) ;; allocates n pairs
(f 1000)
(g 1000)
(h 1000)
(##display-space-usage)
;; execution:
;;
;; $ gsc -exe prof-space.scm
;; $ ./prof-space
;; g = 2016
;; f = 8048
;; h = 48000
More information about the Gambit-list
mailing list