]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - cddl/contrib/dtracetoolkit/Misc/wpm.d
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / cddl / contrib / dtracetoolkit / Misc / wpm.d
1 #!/usr/sbin/dtrace -s
2 /*
3  * wpm.d - Measure words per minute of typing.
4  *         Written in DTrace (Solaris 10 3/05).
5  *
6  * $Id: wpm.d 52 2007-09-24 04:28:01Z brendan $
7  *
8  * USAGE:       wpm.d commandname
9  *   eg,
10  *              wpm.d bash
11  *              wpm.d vim
12  *
13  * This script assumes that keystrokes arrive one at a time on STDIN. This
14  * isn't the case for all processes that read keyboard input (eg, sh).
15  *
16  * COPYRIGHT: Copyright (c) 2007 Brendan Gregg.
17  *
18  * CDDL HEADER START
19  *
20  *  The contents of this file are subject to the terms of the
21  *  Common Development and Distribution License, Version 1.0 only
22  *  (the "License").  You may not use this file except in compliance
23  *  with the License.
24  *
25  *  You can obtain a copy of the license at Docs/cddl1.txt
26  *  or http://www.opensolaris.org/os/licensing.
27  *  See the License for the specific language governing permissions
28  *  and limitations under the License.
29  *
30  * CDDL HEADER END
31  *
32  * 05-Aug-2007  Brendan Gregg   Created this.
33  */
34
35 #pragma D option quiet
36 #pragma D option switchrate=10
37 #pragma D option defaultargs
38
39 inline int STDIN = 0;
40
41 enum tracing_state {
42         BEGIN,
43         TRACING
44 };
45
46 dtrace:::BEGIN
47 /$$1 == ""/
48 {
49         trace("USAGE: wpm.d commandname\n");
50         trace("  eg,\n");
51         trace("       wpm.d bash\n");
52         trace("       wpm.d vim\n");
53         exit(1);
54 }
55
56 dtrace:::BEGIN
57 {
58         state = BEGIN;
59         keys = 0;
60         words = 0;
61         wordsize = 0;
62         countdown = 5;
63         last = 0;
64         printf("Measuring will start in : %2d seconds", countdown);
65 }
66
67 profile:::tick-1sec
68 /--countdown >= 0/
69 {
70         printf("\b\b\b\b\b\b\b\b\b\b%2d seconds", countdown);
71 }
72
73 profile:::tick-1sec
74 /state == BEGIN && countdown == -1/
75 {
76         state = TRACING;
77         countdown = 60;
78         printf("\nMeasuring will stop in  : %2d seconds", countdown);
79 }
80
81 syscall::read:entry
82 /state == TRACING && execname == $$1 && arg0 == STDIN/
83 {
84         self->buf = arg1;
85 }
86
87 syscall::read:return
88 /self->buf && last/
89 {
90         this->elapsed = (timestamp - last) / 1000000;
91         @dist = quantize(this->elapsed);
92         @avg = avg(this->elapsed);
93         @min = min(this->elapsed);
94         @max = max(this->elapsed);
95 }
96
97 syscall::read:return
98 /self->buf/
99 {
100         keys++;
101         wordsize++;
102         this->key = stringof(copyin(self->buf, arg0));
103         last = timestamp;
104 }
105
106 syscall::read:return
107 /self->buf && (this->key == " " || this->key == "\n" || this->key == "\r") &&
108     wordsize == 1/
109 {
110         /* recurring space */
111         wordsize = 0;
112         self->buf = 0;
113 }
114
115 syscall::read:return
116 /self->buf && (this->key == " " || this->key == "\n" || this->key == "\r")/
117 {
118         words++;
119         @sizes = lquantize(wordsize - 1, 0, 32, 1);
120         wordsize = 0;
121 }
122
123 syscall::read:return
124 /self->buf/
125 {
126         self->buf = 0;
127 }
128
129 profile:::tick-1sec
130 /state == TRACING && countdown == -1/
131 {
132         printf("\n\nCharacters typed : %d\n", keys);
133         printf("Words per minute : %d\n\n", words);
134
135         printa("Minimum keystroke latency : %@d ms\n", @min);
136         printa("Average keystroke latency : %@d ms\n", @avg);
137         printa("Maximum keystroke latency : %@d ms\n\n", @max);
138
139         printa("Word size distribution (letters),\n%@d\n", @sizes);
140         printa("Keystroke latency distribution (ms),\n%@d\n", @dist);
141
142         exit(0);
143 }