changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > core / annotate lisp/lib/rt/tracing.lisp

changeset 698: 96958d3eb5b0
parent: 12287fab15d0
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 04 Oct 2024 22:04:59 -0400
permissions: -rw-r--r--
description: fixes
215
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
1
 ;;; lib/rt/tracing.lisp --- Tracing Framework
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
2
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
3
 ;; This package provides utilities for tracing Lisp code and
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
4
 ;; displaying traces to the user. In addition to extending the
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
5
 ;; built-in TRACE macro and SB-DEBUG functionality we have a tracer
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
6
 ;; which works with Chrome's built-in tracer: chrome://trace.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
7
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
8
 ;; The chrome tracer is a slightly modernized version of TeMPOraL's
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
9
 ;; work available here: https://github.com/TeMPOraL/tracer.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
10
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
11
 ;; ref: https://www.chromium.org/developers/how-tos/trace-event-profiling-tool/
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
12
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
13
 ;; - sb-debug manual: https://www.sbcl.org/manual/#Debugger
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
14
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
15
 ;; - sb-debug notes: https://gist.github.com/nikodemus/659495
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
16
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
17
 ;;; Code:
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
18
 (in-package :rt/tracing)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
19
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
20
 (defmacro traced-flet (functions &body body)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
21
   (flet ((add-traces (function) 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
22
            (destructuring-bind 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
23
                (name lambda-list &body body) function 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
24
              `(,name ,lambda-list 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
25
                      ,@(cons `(format t 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
26
                                       "Calling ~a with ~@{~a=~a, ~}~%" 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
27
                                       ',name 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
28
                                       ,@(loop for symbol in lambda-list 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
29
                                           collecting `(quote ,symbol) 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
30
                                           collecting symbol)) 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
31
                               body)))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
32
     `(flet ,(mapcar #'add-traces functions) ,@body)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
33
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
34
 ;;; This is an implementation of a chromium-based Lisp tracer authored
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
35
 ;;; by TeMPOraL. The source is available here:
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
36
 ;;; https://github.com/TeMPOraL/tracer/tree/master
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
37
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
38
 (defvar *trace-events* nil "A list of trace entries, pushed onto from the beginning.")
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
39
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
40
 (defvar *original-trace-start-breakpoint-fun* #'sb-debug::trace-start-breakpoint-fun "Original SBCL function being overwritten by the tracer.")
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
41
 (defvar *original-trace-end-breakpoint-fun* #'sb-debug::trace-end-breakpoint-fun "Original SBCL function being overwritten by the tracer.")
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
42
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
43
 (defvar *clock-reset-fun* nil)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
44
 (defvar *clock-get-time-fun* nil)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
45
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
46
 (defvar *trace-event-default-pid* 1 "The default value for PID for the trace events. This library is currently intended for use within a single process only.")
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
47
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
48
 (defvar +arg-converter-ignore-all+ (constantly nil) "A converter that rejects all parameters.")
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
49
 (defvar +arg-converter-passthrough+ (lambda (&rest args) args) "A converter that remembers all args as is, without modifying them.")
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
50
 (defvar +arg-converter-store-only-simple-objects+ (lambda (&rest args)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
51
                                                     (mapcar (lambda (arg)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
52
                                                               (typecase arg
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
53
                                                                 ((or boolean character number symbol)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
54
                                                                  arg)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
55
                                                                 (t
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
56
                                                                  (type-of arg))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
57
                                                             args))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
58
   "A converter that remembers directly only objects of simple types, that cannot or are very unlikely to be destructively modified.")
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
59
 (defvar +arg-converter-store-only-simple-objects-and-strings+ (lambda (&rest args)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
60
                                                                 (mapcar (lambda (arg)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
61
                                                                           (typecase arg
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
62
                                                                             ((or boolean character number symbol string)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
63
                                                                              arg)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
64
                                                                             (t
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
65
                                                                              (type-of arg))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
66
                                                                         args))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
67
   "Like `+ARG-CONVERTER-STORE-ONLY-SIMPLE-OBJECTS+', but also records strings as-is, hoping they don't get destructively modified too much.")
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
68
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
69
 (defvar *default-arg-converter* +arg-converter-ignore-all+)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
70
 (defvar *tracing-arg-converters* (make-hash-table :test 'equal))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
71
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
72
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
73
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
74
 ;;; The format of trace event; created primarily for reference, though later on we might upgrade to vector storage, and then it'll come helpful.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
75
 (defstruct (trace-event (:type list))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
76
   "A single event being traced. "
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
77
   (phase :undefined :type keyword)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
78
   (name nil :type (or symbol cons))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
79
   (thread 0 :type t)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
80
   (timestamp 0 :type fixnum)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
81
   (args nil :type t)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
82
   (duration 0 :type (or null (unsigned-byte 62)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
83
   (id nil :type t))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
84
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
85
 ;;; TODO: define accessors manually, to save performance? or somehow optimize it.  -- Jacek Złydach, 2019-11-04
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
86
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
87
 (declaim (inline convert-args))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
88
 (defun convert-args (traced-fn-name args)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
89
   "Depending on the function being traced, named `TRACED-FN-NAME', and the value of `*DEFAULT-ARG-CONVERTER*'
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
90
 convert the list of arguments `ARGS' to a form suitable for storing with the trace event, using a converter
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
91
 registered under `*TRACING-ARG-CONVERTERS*'.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
92
 Returns the representation of `ARGS' to store."
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
93
   (declare (optimize (speed 3)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
94
   (apply (the function (gethash traced-fn-name *tracing-arg-converters* *default-arg-converter*))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
95
          args))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
96
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
97
 (declaim (inline make-trace-event-fast))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
98
 (defun make-trace-event-fast (phase name thread timestamp args duration id)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
99
   "Like `MAKE-TRACE-EVENT', but inlined, unsafe and without typechecking."
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
100
   (declare (optimize (speed 3)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
101
   (list phase name thread timestamp (convert-args name args) duration id))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
102
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
103
 ;;; Timer
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
104
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
105
 ;;; TODO: make it so that user can plug a high-resolution timer here. -- Jacek Złydach, 2019-10-18
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
106
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
107
 (sb-ext:defglobal *hack-clock-jitter* 0 "A crude hack because our clock has too little resolution.")
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
108
 (declaim (type fixnum *hack-clock-jitter*))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
109
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
110
 ;;; TODO: this needs to be a function that can be changed between invocations of tracing!
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
111
 ;;; I want to allow for injecting higher resolution clocks if available.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
112
 ;;; -- Jacek Złydach, 2019-11-01
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
113
 
448
a37b1d3371fc fasl tweaks
Richard Westhaver <ellis@rwest.io>
parents: 215
diff changeset
114
 (defun get-current-time-usec* ()
215
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
115
   "Get current time with microsecond resolution."
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
116
   (sb-ext:atomic-incf *hack-clock-jitter*)
448
a37b1d3371fc fasl tweaks
Richard Westhaver <ellis@rwest.io>
parents: 215
diff changeset
117
   (the (unsigned-byte 62)
a37b1d3371fc fasl tweaks
Richard Westhaver <ellis@rwest.io>
parents: 215
diff changeset
118
        (+ (* (get-internal-real-time) 1000)
a37b1d3371fc fasl tweaks
Richard Westhaver <ellis@rwest.io>
parents: 215
diff changeset
119
           *hack-clock-jitter*)))
215
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
120
 
448
a37b1d3371fc fasl tweaks
Richard Westhaver <ellis@rwest.io>
parents: 215
diff changeset
121
 (declaim (ftype (function () (unsigned-byte 62)) get-current-time-usec*)
a37b1d3371fc fasl tweaks
Richard Westhaver <ellis@rwest.io>
parents: 215
diff changeset
122
          (inline get-current-time-usec*))
215
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
123
 (defun get-current-time-usec-nojitter ()
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
124
   "Get current time with microsecond resolution. No extra jitter involved."
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
125
   (declare (optimize (speed 3)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
126
   (the (unsigned-byte 62) (* (get-internal-real-time) 1000)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
127
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
128
 ;;; XXX: below is our new, usec clock -- Jacek Złydach, 2019-11-02
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
129
 (let ((clock-offset 0))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
130
   (declare (type (unsigned-byte 62) clock-offset))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
131
   (defun %%start-clock ()
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
132
     (setf clock-offset (sb-kernel::get-time-of-day)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
133
   (defun %%get-time-usec ()
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
134
     (multiple-value-bind (sec usec)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
135
         (sb-kernel::get-time-of-day)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
136
       (+ (* (- sec clock-offset) 1000000) usec)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
137
   (defun %%time (thunk)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
138
     (let ((start (%%get-time-usec)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
139
       (funcall thunk)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
140
       (- (%%get-time-usec)  start)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
141
   (setf *clock-reset-fun* #'%%start-clock
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
142
         *clock-get-time-fun* #'%%get-time-usec))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
143
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
144
 (declaim (ftype (function () (values (unsigned-byte 62) &optional)) get-current-time)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
145
          (inline get-current-time))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
146
 (defun get-current-time ()
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
147
   (funcall *clock-get-time-fun*))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
148
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
149
 (defun post-process-entries (entries &key correct-zero-duration)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
150
   "Destructively modify `ENTRIES', making it more compact and, if `CORRECT-ZERO-DURATION' is T,
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
151
 changing zero-length events to have 1us length, also modifying other times to offset for that.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
152
 `ENTRIES' is expected to be in order entries were added. The function maintain separate offsets per (process, thread) pair.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
153
 Returns a processed list, to replace old value `ENTRIES'. As additional values, returns the total accumulated clock offset,
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
154
 and the stacks containing unclosed duration entries, keyed by thread."
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
155
   (let ((offset 0)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
156
         (stacks (make-hash-table :test 'equal)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
157
     (dolist (entry entries entries)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
158
       ;; Always update event time to account for clock offset.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
159
       (incf (trace-event-timestamp entry) offset)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
160
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
161
       ;; Match starting and ending events to offset clock in case of zero-length events, and to convert
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
162
       ;; matching pairs of Duration events into Complete events.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
163
       (let ((entry-ht-id (cons 1 (trace-event-thread entry)))) ;1 is the currently supported PID
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
164
         (ecase (trace-event-phase entry)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
165
           (:enter
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
166
            ;; Push the :enter entry to stack.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
167
            (push entry (gethash entry-ht-id stacks)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
168
           (:exit
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
169
            (let ((begin-event (first (gethash entry-ht-id stacks))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
170
              (if (equalp (trace-event-name begin-event)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
171
                          (trace-event-name entry))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
172
                  (progn
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
173
                    ;; Actual post-processing happens here.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
174
                    ;; If zero-length and correct-zero-duration is on, update close time and offset.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
175
                    (when (and correct-zero-duration
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
176
                               (= (trace-event-timestamp begin-event)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
177
                                  (trace-event-timestamp entry)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
178
                      (incf (trace-event-timestamp entry))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
179
                      (incf offset))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
180
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
181
                    ;; Convert task into complete task + counter
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
182
                    (setf (trace-event-phase begin-event) :complete
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
183
                          (trace-event-phase entry) :skip ;TODO: counters, if any, go here -- Jacek Złydach, 2019-11-04
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
184
                          (trace-event-duration begin-event) (- (trace-event-timestamp entry) (trace-event-timestamp begin-event))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
185
                          (trace-event-args begin-event) `(:in ,(trace-event-args begin-event) :out ,(trace-event-args entry)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
186
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
187
                    ;; Pop the updated entry from stack.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
188
                    (pop (gethash entry-ht-id stacks)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
189
                  (warn "Recorded entries misordered; expected ~A, got ~A." (trace-event-name begin-event) (trace-event-name entry))))))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
190
     ;; Go over the list again, and remove "skip" entries.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
191
     (deletef entries :skip :key #'trace-event-phase)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
192
     (values entries
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
193
             offset
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
194
             stacks)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
195
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
196
 ;;; Tracing process
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
197
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
198
 (defun %trace-start-breakpoint-fun (info)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
199
   (let (conditionp)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
200
     (values
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
201
      (lambda (frame bpt &rest args)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
202
        (declare (ignore bpt))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
203
        (sb-debug::discard-invalid-entries frame)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
204
        (let ((condition (sb-debug::trace-info-condition info))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
205
              (wherein (sb-debug::trace-info-wherein info)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
206
          (setq conditionp
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
207
                (and (not sb-debug::*in-trace*)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
208
                     (or (not condition)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
209
                         (apply (cdr condition) frame args))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
210
                     (or (not wherein)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
211
                         (sb-debug::trace-wherein-p frame wherein nil)))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
212
        (when conditionp
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
213
          (when (sb-debug::trace-info-encapsulated info)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
214
            (sb-ext:atomic-push (make-trace-event-fast :enter
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
215
                                                       (sb-debug::trace-info-what info)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
216
                                                       sb-thread:*current-thread*
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
217
                                                       (get-current-time)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
218
                                                       args
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
219
                                                       nil
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
220
                                                       nil)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
221
                                *trace-events*))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
222
          ;; TODO: perhaps remove this, it seems unneeded -- Jacek Złydach, 2019-11-05
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
223
          (with-standard-io-syntax
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
224
            (apply #'sb-debug::trace-maybe-break info (sb-debug::trace-info-break info) "before"
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
225
                   frame args))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
226
      (lambda (frame cookie)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
227
        (declare (ignore frame))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
228
        (push (cons cookie conditionp) sb-debug::*traced-entries*)))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
229
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
230
 (declaim (ftype (function (sb-debug::trace-info) function) %trace-end-breakpoint-fun))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
231
 (defun %trace-end-breakpoint-fun (info)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
232
   (lambda (frame bpt values cookie)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
233
     (declare (ignore bpt))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
234
     (unless (eq cookie (caar sb-debug::*traced-entries*))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
235
       (setf sb-debug::*traced-entries*
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
236
             (member cookie sb-debug::*traced-entries* :key #'car)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
237
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
238
     (let ((entry (pop sb-debug::*traced-entries*)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
239
       (when (and (not (sb-debug::trace-info-untraced info))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
240
                  (or (cdr entry)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
241
                      (let ((cond (sb-debug::trace-info-condition-after info)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
242
                        (and cond (apply #'funcall (cdr cond) frame values)))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
243
         (sb-ext:atomic-push (make-trace-event-fast :exit
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
244
                                                    (sb-debug::trace-info-what info)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
245
                                                    sb-thread:*current-thread*
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
246
                                                    (get-current-time)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
247
                                                    values
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
248
                                                    nil
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
249
                                                    nil)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
250
                             *trace-events*)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
251
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
252
         (apply #'sb-debug::trace-maybe-break info (sb-debug::trace-info-break-after info) "after"
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
253
                frame values)))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
254
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
255
 (defun install-tracing-overrides ()
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
256
   (sb-ext:unlock-package (find-package 'sb-debug))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
257
   (setf (symbol-function 'sb-debug::trace-start-breakpoint-fun) #'%trace-start-breakpoint-fun
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
258
         (symbol-function 'sb-debug::trace-end-breakpoint-fun) #'%trace-end-breakpoint-fun)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
259
   (sb-ext:lock-package (find-package 'sb-debug)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
260
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
261
 (defun uninstall-tracing-overrides ()
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
262
   (sb-ext:unlock-package (find-package 'sb-debug))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
263
   (setf (symbol-function 'sb-debug::trace-start-breakpoint-fun) *original-trace-start-breakpoint-fun*
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
264
         (symbol-function 'sb-debug::trace-end-breakpoint-fun) *original-trace-end-breakpoint-fun*)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
265
   (sb-ext:lock-package (find-package 'sb-debug)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
266
 
679
12287fab15d0 rocksdb load opts and env updates
Richard Westhaver <ellis@rwest.io>
parents: 448
diff changeset
267
 (defun start-tracing (specs)
215
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
268
   (install-tracing-overrides)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
269
   `(progn
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
270
      (trace :encapsulate t :methods t ,@specs)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
271
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
272
 (defun stop-tracing ()
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
273
   (untrace)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
274
   (uninstall-tracing-overrides)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
275
   #+nil(setf *trace-events* (nreverse *trace-events*))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
276
   (multiple-value-bind (events offset stacks)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
277
       (post-process-entries (nreverse *trace-events*))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
278
     (declare (ignore offset stacks))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
279
     (setf *trace-events* events))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
280
   ;; TODO: report offsets and stacks -- Jacek Złydach, 2019-11-05
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
281
   (values))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
282
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
283
 (defun reset-tracing ()
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
284
   (setf *trace-events* nil
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
285
         *hack-clock-jitter* 0))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
286
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
287
 (defun get-tracing-report-data ()
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
288
   *trace-events*)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
289
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
290
 ;;; Trace operations:
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
291
 ;;; 1. Reset
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
292
 ;;; 2. Trace
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
293
 ;;; 2.5 snapshot tracing?
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
294
 ;;; 3. Stop tracing
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
295
 ;;; 4. Save report
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
296
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
297
 (defvar *tracing-p* nil "Is currently tracing activity happening?")
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
298
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
299
 ;;; Trace info entry type, for function call
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
300
 ;;; - Timestamp
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
301
 ;;; - Function name
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
302
 ;;; - Function args maybe? (trace-with-args), on enter
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
303
 ;;; - Function return value, on exit
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
304
 ;;; - Beginning or ending
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
305
 ;;; - Thread ID
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
306
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
307
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
308
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
309
 ;;; This prints a representation of the return values delivered.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
310
 ;;; First, this checks to see that cookie is at the top of
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
311
 ;;; *TRACED-ENTRIES*; if it is not, then we need to adjust this list
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
312
 ;;; to determine the correct indentation for output. We then check to
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
313
 ;;; see whether the function is still traced and that the condition
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
314
 ;;; succeeded before printing anything.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
315
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
316
 (defmacro with-tracing ((&rest specs) &body body)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
317
   `(unwind-protect
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
318
         (progn
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
319
           (reset-tracing)
679
12287fab15d0 rocksdb load opts and env updates
Richard Westhaver <ellis@rwest.io>
parents: 448
diff changeset
320
           (start-tracing ',specs)
215
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
321
           (progn
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
322
             ,@body))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
323
      (stop-tracing)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
324
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
325
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
326
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
327
 (defun function-name->name-and-category (function-name)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
328
   (etypecase function-name
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
329
     (symbol
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
330
      (values (symbol-name function-name) (package-name (symbol-package function-name))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
331
     (cons
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
332
      (ecase (first function-name)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
333
        (setf
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
334
         (values (format nil "~S" function-name) (package-name (symbol-package (second function-name)))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
335
        ;; TODO investigate
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
336
        ((method sb-pcl::combined-method)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
337
         (values (remove #\Newline (format nil "~S" function-name))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
338
                 (if (consp (second function-name))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
339
                     (package-name (symbol-package (second (second function-name))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
340
                     (package-name (symbol-package (second function-name))))))))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
341
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
342
 (defgeneric post-process-arg (arg)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
343
   (:method ((arg t))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
344
     "Passthrough method."
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
345
     (or (ignore-errors
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
346
           (prin1-to-string arg))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
347
         "!!Error printing argument!!"))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
348
   (:documentation "A hook useful for changing the printed representation of input and return values."))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
349
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
350
 (defmethod post-process-arg ((arg sequence))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
351
   (if (every (lambda (el)  (typep el 'number)) arg)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
352
       (format nil "[~{~F~^, ~}]" (coerce arg 'list))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
353
       (call-next-method)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
354
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
355
 ;;; FIXME: Something breaks if not collecting args, and :skip-args is NIL. Probably the getf in printing. -- Jacek Złydach, 2019-11-05
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
356
 (defun trace-event->json (trace-event &key (skip-args nil))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
357
   (flet ((sanitize-and-format-args-list (argslist)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
358
            (if skip-args "\"_\""
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
359
                (substitute #\Space #\Newline (format nil "[~{~S~^, ~}]" (mapcar #'post-process-arg argslist))))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
360
     (ecase (trace-event-phase trace-event)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
361
       (:enter
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
362
        (multiple-value-bind (name category)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
363
            (function-name->name-and-category (trace-event-name trace-event))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
364
          (format nil
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
365
                  "{ \"name\" : ~S, \"cat\" : ~S, \"ph\" : \"B\", \"pid\" : 1, \"tid\" : ~D, \"ts\" : ~D, \"args\" : { \"in\" : ~A }}"
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
366
                  name
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
367
                  category
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
368
                  (sb-impl::get-lisp-obj-address (trace-event-thread trace-event))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
369
                  (trace-event-timestamp trace-event)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
370
                  (sanitize-and-format-args-list (trace-event-args trace-event)))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
371
       (:exit
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
372
        (multiple-value-bind (name category)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
373
            (function-name->name-and-category (trace-event-name trace-event))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
374
          (format nil
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
375
                  "{ \"name\" : ~S, \"cat\" : ~S, \"ph\" : \"E\", \"pid\" : 1, \"tid\" : ~D, \"ts\" : ~D, \"args\" : { \"out\" : ~A }}"
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
376
                  name
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
377
                  category
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
378
                  (sb-impl::get-lisp-obj-address (trace-event-thread trace-event))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
379
                  (trace-event-timestamp trace-event)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
380
                  (sanitize-and-format-args-list (trace-event-args trace-event)))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
381
       (:complete
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
382
        (multiple-value-bind (name category)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
383
            (function-name->name-and-category (trace-event-name trace-event))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
384
          (format nil
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
385
                  "{ \"name\" : ~S, \"cat\" : ~S, \"ph\" : \"X\", \"pid\" : 1, \"tid\" : ~D, \"ts\" : ~D, \"dur\" : ~D,  \"args\" : { \"in\" : ~A, \"out\" : ~A }}"
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
386
                  name
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
387
                  category
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
388
                  (sb-impl::get-lisp-obj-address (trace-event-thread trace-event))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
389
                  (trace-event-timestamp trace-event)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
390
                  (trace-event-duration trace-event)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
391
                  (sanitize-and-format-args-list (getf (trace-event-args trace-event) :in))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
392
                  (sanitize-and-format-args-list (getf (trace-event-args trace-event) :out))))))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
393
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
394
 (defun thread->json (thread)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
395
   (format nil
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
396
           "{ \"name\" : \"thread_name\", \"ph\" : \"M\", \"pid\" : 1, \"tid\" : ~D, \"args\" : { \"name\" : ~S }}"
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
397
           (sb-impl::get-lisp-obj-address thread)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
398
           (sb-thread:thread-name thread)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
399
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
400
 (defun extract-threads (events)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
401
   (loop
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
402
      with uniques-ht = (make-hash-table :test #'eq)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
403
      for event in events
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
404
      do
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
405
        (setf (gethash (trace-event-thread event) uniques-ht) t)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
406
      finally
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
407
        (return (hash-table-keys uniques-ht))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
408
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
409
 ;;; FIXME: save with streams instead? -- Jacek Złydach, 2019-10-14
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
410
 (defun save-report (output-file-name &key (skip-args t))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
411
   (with-open-file (stream output-file-name :direction :output :if-exists :supersede)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
412
     ;; TODO: preamble -- Jacek Złydach, 2019-10-14
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
413
     (format stream "{~%\"traceEvents\" :  [~%")
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
414
     (loop
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
415
        for (entry . restp) on *trace-events*
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
416
        do
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
417
          (write-string (trace-event->json entry :skip-args skip-args) stream)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
418
          (when restp
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
419
            (write-string "," stream)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
420
            (terpri stream)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
421
     (loop
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
422
        for (thread . restp) on (extract-threads *trace-events*)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
423
        initially
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
424
          (write-string "," stream)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
425
          (terpri stream)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
426
        do
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
427
          (write-string (thread->json thread) stream)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
428
          (when restp
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
429
            (write-string "," stream)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
430
            (terpri stream)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
431
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
432
     (format stream "~&],
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
433
 \"displayTimeUnit\" : \"ms\",
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
434
 \"application\" : \"FIXME\",
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
435
 \"version\" : \"FIXME\",
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
436
 \"traceTime\" : ~S
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
437
 }"
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
438
             " TODO local-time independent time"
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
439
             ;;(local-time:format-timestring nil (local-time:now))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
440
             ))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
441
   (values))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
442
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
443
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
444
 
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
445
 ;;; Helper function for blacklisting symbols when tracing whole packages.
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
446
 (defun package-symbols-except (name &rest exceptions)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
447
   (let (symbols
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
448
         (package (sb-impl::find-undeleted-package-or-lose name)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
449
     (do-all-symbols (symbol (find-package name))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
450
       (when (eql package (symbol-package symbol))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
451
         (when (and (fboundp symbol)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
452
                    (not (macro-function symbol))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
453
                    (not (special-operator-p symbol)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
454
           (push symbol symbols))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
455
         (let ((setf-name `(setf ,symbol)))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
456
           (when (fboundp setf-name)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
457
             (push setf-name symbols)))))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
458
     (set-difference symbols exceptions :key (lambda (x)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
459
                                               (if (consp x)
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
460
                                                   (string (second x))
0d11384aae81 rt tests
Richard Westhaver <ellis@rwest.io>
parents:
diff changeset
461
                                                   (string x))) :test #'string-equal)))