;;; -*- Mode:LISP; Package:TV; Readtable:CL; Base:10 -*- (defun setup-landscape-with-guages () (generate-gc-guages) (setup-guage-configuration) (start-guage-process)) (defun make-cheap-averager (averaging-factor) (let ((last-value 0) (inverse-factor (- 1 averaging-factor))) #'(lambda (next-value) (setq last-value (+ (* averaging-factor last-value) (* inverse-factor next-value))) last-value))) (defvar *disk-average-value* .8) (defun make-disk-usage-meter-function () (let ((averager (make-cheap-averager *disk-average-value*)) (last-time (time:fixnum-microsecond-time)) (last-disk-time (logand (read-meter 'sys:%disk-wait-time) (- (expt 2 24) 1)))) #'(lambda () (let ((now (time:fixnum-microsecond-time)) (this-wait (logand (read-meter 'sys:%disk-wait-time) (- (expt 2 24) 1)))) (prog1 (funcall averager (* 100. (/ (time:time-difference this-wait last-disk-time) (time:time-difference now last-time)))) (setq last-time now last-disk-time this-wait)))))) (defun total-processor-utilization (&aux (total 0)) (without-interrupts (dolist (ape si:active-processes) (when (car ape) (incf total (send (car ape) :percent-utilization))))) (values (round total))) (defvar *utilization-guage* (make-instance 'probe-map-guage :superior *control-panel* :label "Utilization" :mapping-function #'percent->guage :probe-function #'total-processor-utilization)) (defvar *disk-guage* (make-instance 'probe-map-guage :superior *control-panel* :label "Disk" :mapping-function #'percent->guage :probe-function (make-disk-usage-meter-function))) (defvar *big-guage-list* (list *disk-guage* *utilization-guage*)) (defconstant *number-of-volatility-levels* 4) (defconstant *gc-guages* (make-array *number-of-volatility-levels*)) (defun gc-probe (level) #'(lambda () (let ((lc (aref gc:*level-control* level)) (sdb (if (and (boundp 'gc:*gc-process*) gc:*gc-process* (send gc:*gc-process* :run-reasons)) gc:*most-recent-storage-distribution-block* ;; try to avoid costly gc computations. (gc:compute-storage-distribution)))) (cond ((numberp lc) (/ (aref sdb level)(float lc))) ((null lc) (/ (gc:committed-free-space level :batch sdb) (float si:virtual-memory-size))) (t (/ (gc:committed-free-space level :incremental sdb) (aref sdb 5))))))) (defun generate-gc-guages () (dotimes (v *number-of-volatility-levels*) (setf (aref *gc-guages* v) (make-instance 'probe-map-guage :superior tv:*control-panel* :mapping-function #'fraction->guage :label (format nil "Vol ~D" v) :probe-function (gc-probe v))))) (defun setup-guage-configuration () ;; stack the guages from bottom up (multiple-value-bind (left ignore right bottom) (send tv:*control-panel* :inside-edges) (let ((big-guage-size (- right left))) (do ((big-guages *big-guage-list* (cdr big-guages)) (bottom bottom top) (top (- bottom big-guage-size) (- top big-guage-size))) ((null big-guages) (let ((middle (truncate big-guage-size 2))) (do ((v 0 (1+ v)) (flag nil (not flag)) ;T if going to next layer (layer-bottom bottom (if flag layer-top layer-bottom)) (layer-top (- bottom middle) (if flag (- layer-top middle) layer-top))) ((= v *number-of-volatility-levels*) '()) (let ((this-guage (aref *gc-guages* v))) (send this-guage :activate) (send this-guage :expose) (send this-guage :set-edges (if flag left middle) layer-top (if flag middle right) layer-bottom) )))) (let ((this-guage (first big-guages))) (send this-guage :activate) (send this-guage :expose) (send this-guage :set-edges left top right bottom) ))))) (defvar *guage-process* (make-process "Guages" :arrest-reasons '(:guages-off))) (defvar *guage-process-sleep-time* 2.) (defun guage-process () (do-forever (sleep *guage-process-sleep-time*) (send *disk-guage* :update) (send *utilization-guage* :update) (dotimes (v *number-of-volatility-levels*) (send (aref *gc-guages* v) :update)))) (defun start-guage-process () (send *guage-process* :preset 'guage-process) (send *guage-process* :reset) (send *guage-process* :run-reason :enable) (send *guage-process* :revoke-arrest-reason :guages-off))