On Aug 11, 2023, at 4:03 AM, Sven Hartrumpf hartrumpf@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) ,@rest))) (else `(##define ,pattern ,@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