Attempts to fix uth_disable_notif()
[akaros.git] / scripts / lock_test.R
1 # brho: 2014-10-13
2 #
3 # this is partly fleshed out.  to use, i've just been sourcing the script in R,
4 # then overriding the tsc overhead and freq.  then just running various
5 # functions directly, like print_stats, plot_densities, plot_tput, etc.  don't
6 # expect any command line options to work.
7
8 # library that includes the pwelch function
9 suppressPackageStartupMessages(library(oce))
10 # library for command line option parsing
11 suppressPackageStartupMessages(library(optparse))
12
13 # file format: thread_id attempt pre acq(uire) un(lock) tsc_overhead
14
15 g_tsc_overhead <- 0
16 g_tsc_frequency <- 0
17
18 ######################################
19 ### Functions
20 ######################################
21
22 # takes any outliers 2 * farther than the 99th quantile and rounds them down to
23 # that limit.  the limit is pretty arbitrary.  useful for not having
24 # ridiculously large graphs, but still is lousy for various datasets.
25 round_outlier <- function(vec)
26 {
27         vec99 = quantile(vec, .99)
28         lim = vec99 + 2 * (vec99 - median(vec))
29         return(sapply(vec, function(x) min(x, lim)))
30 }
31
32 # computes acquire latency, using global tsc freq if there isn't one in the
33 # data
34 acq_latency <- function(data)
35 {
36         tsc_overhead = data$V6
37         if (tsc_overhead[1] == 0)
38                 tsc_overhead = sapply(tsc_overhead, function(x) g_tsc_overhead)
39         return (data$V4 - data$V3 - tsc_overhead)
40 }
41
42 # computes hold latency, using global tsc freq if there isn't one in the data
43 hld_latency <- function(data)
44 {
45         tsc_overhead = data$V6
46         if (tsc_overhead[1] == 0)
47                 tsc_overhead = sapply(tsc_overhead, function(x) g_tsc_overhead)
48         return (data$V5 - data$V4 - tsc_overhead)
49 }
50
51 # histogram, bins based on percentiles, with limits of the graph based on the
52 # outermost bins.  somewhat works.  can get a 'need finite ylim' if the bins
53 # are too small.  maybe since there are no values in it.
54 #
55 # with density and percentiles for bins, keep in mind the area of a rectangle
56 # is the fraction of data points in the cell.  since all bins have the same
57 # amount of data points, taller cells show a denser concentration in a skinnier
58 # bin
59 #
60 # i don't actually like this much.  using a round_outlier with 20-bin hist or a
61 # density plot look nicer.
62 quant_hist <- function(vec)
63 {
64         vec_quant = c(quantile(vec, probs=seq(0, 1, .01)))
65         print(vec_quant)
66         # keep the 100 in sync with the 0.01 above
67         hist(vec, breaks=vec_quant, xlim=c(vec_quant[2], vec_quant[100]))
68 }
69
70 plot_densities <- function(vecs, names=NULL, outfile="",
71                            title="Lock Acquisition Latency",
72                            xlab="TSC Ticks")
73 {
74         nr_vecs = length(vecs)
75         densities = list()
76         max_y = 0
77         min_x = Inf
78         max_x = 0
79
80         for (i in 1:nr_vecs) {
81                 # [[ ]] chooses the actual element.  [] just subsets
82                 dense_i = density(vecs[[i]])
83                 densities = c(densities, list(dense_i))
84                 max_y = max(max_y, dense_i$y)
85                 max_x = max(max_x, dense_i$x)
86                 min_x = min(min_x, dense_i$x)
87         }
88
89         # http://www.statmethods.net/graphs/line.html
90         colors <- rainbow(nr_vecs) # not a huge fan.  color #2 is light blue.
91         linetype <- c(1:nr_vecs)
92         plotchar <- seq(18, 18 + nr_vecs, 1)
93
94         # http://stackoverflow.com/questions/8929663/r-legend-placement-in-a-plot
95         # can manually move it if we don't want to waste space
96         if (!is.null(names)) {
97                 plot(c(min_x,max_x), c(0, max_y), type="n", xaxt="n", yaxt="n")
98                 legend_sz = legend("topright", legend=names, lty=linetype, plot=FALSE)
99                 max_y = 1.04 * (max_y + legend_sz$rect$h)
100                 invisible(dev.off())
101         }
102
103         if (outfile != "")
104                 pdf(outfile)
105
106         plot(c(min_x,max_x), c(0, max_y), type="n", xlab=xlab, main=title,
107              ylab="Density")
108
109         for (i in 1:nr_vecs) {
110                 # too many points, so using "l" and no plotchar.
111                 #lines(densities[[i]], type="b", lty=linetype[i], col=colors[i],
112                 #      pch=plotchar[i], lwd=1.5)
113                 lines(densities[[i]], type="l", lty=linetype[i], lwd=1.5)
114         }
115
116         #legend(x=min_x, y=max_y, legend=names, lty=linetype, col=colors)
117         if (!is.null(names))
118                 legend("topright", legend=names, lty=linetype)
119
120         if (outfile != "")
121                 invisible(dev.off())
122 }
123
124
125 plot_density <- function(vec, outfile="",
126                          title="Lock Acquisition Latency",
127                          xlab="TSC Ticks")
128 {
129         vecs = list(vec)
130         plot_densities(vecs=vecs, outfile=outfile, title=title, xlab=xlab)
131 }
132
133
134 plot_acq_times <- function(data, outfile="")
135 {
136         if (outfile != "")
137                 pdf(outfile)
138
139     # all acquire times, timestamps starting at 0
140         time0 = min(data$V4)
141         total_acq <- data$V4 - time0
142
143         threadid <- unique(data$V1)
144
145         acq_n <- list()
146         names <- c()
147         for (i in threadid) {
148                 thread_data <- subset(data, data$V1 == i) - time0
149                 acq_n <- c(acq_n, list(thread_data$V4))
150                 names <- c(names, paste("Thread ", i))
151         }
152         # can adjust ylim, default are from 1..nr_items
153         stripchart(acq_n, group.names=names, pch='.', xlab="Time (TSC Ticks)",
154                    main="Lock Acquisition Timestamps")
155
156         if (outfile != "")
157                 invisible(dev.off())
158 }
159
160 print_vec <- function(vec)
161 {
162         # this whole str, paste dance is nasty
163         print("---------------")
164         str = paste("Average: ", round(mean(vec), 4))
165         print(str)
166         str = paste("Stddev: ", round(sd(vec), 4))
167         print(str)
168         quants = round(quantile(vec, c(.5, .75, .9, .99, .999)))
169         str = paste("50/75/90/99/99.9: ", quants[[1]], quants[[2]], quants[[3]],
170                     quants[[4]], quants[[5]])
171         print(str)
172         str = paste("Min: ", min(vec), " Max: ", max(vec))
173         print(str)
174 }
175
176 # using something like the tables package to output latex booktab's would be
177 # much nicer
178 print_stats <- function(data)
179 {
180         acq_lat = acq_latency(data)
181         hld_lat = hld_latency(data)
182
183         print("Acquire Latency")
184         print_vec(acq_lat)
185         print("")
186         print("Hold Latency")
187         print_vec(hld_lat)
188 }
189
190 # if you know how many msec there are, this is like doing:
191 #     hist(total_acq/1000000, breaks=50)
192 # except it gives you a line, with points being the top of the hist bars
193 plot_tput <- function(data, title="Lock Acquisition Throughput", outfile="")
194 {
195         if (outfile != "")
196                 pdf(outfile)
197
198         total_acq = sort(data$V4 - min(data$V4))
199
200         if (g_tsc_frequency == 0)
201                 stop("WARNING: global TSC freq not set!")
202         # convert to nsec? XXX
203         total_acq = total_acq / (g_tsc_frequency / 1e9)
204
205         # rounds down all times to the nearest msec, will collect into a table,
206         # which counts the freq of each bucket, as per:
207         # http://stackoverflow.com/questions/5034513/how-to-graph-requests-per-second-from-web-log-file-using-r
208         msec_times = trunc(total_acq/1e6)
209
210         # if we just table directly, we'll lose the absent values (msec where no
211         # timestamp happened).  not sure if factor is the best way, the help says
212         # it should be a small range.
213         # http://stackoverflow.com/questions/1617061/including-absent-values-in-table-results-in-r
214         msec_times = factor(msec_times, 0:max(msec_times))
215
216         # without the c(), it'll be a bunch of bars at each msec
217         tab = c(table(msec_times))
218         plot(tab, type="o", main=title, xlab="Time (msec)", ylab="Locks per msec")
219
220         if (outfile != "")
221                 invisible(dev.off())
222 }
223
224
225 # extract useful information from the raw data file
226 extract_data <- function(filename) {
227         mydata = read.table(filename, comment.char="#")
228
229         work_amt = mydata$V2
230
231         # calculate time steps and mean time step (all in ns)
232         times = as.numeric(as.character(mydata$V1))
233         N_entries = length(times)
234         time_steps_ns = times[2:N_entries] - times[1:(N_entries-1)]
235         avg_time_step_ns = mean(time_steps_ns)
236
237         return(list(work_amt=work_amt, time_steps_ns=time_steps_ns,
238                 N_entries=N_entries, avg_time_step_ns=avg_time_step_ns))
239 }
240
241
242 ######################################
243 ### Main
244 ######################################
245
246 ### collect command line arguments
247 # establish optional arguments
248 # "-h" and "--help" are automatically in the list
249 option_list <- list(
250   make_option(c("-i", "--input"), type="character",
251     default="welch_input.dat",
252     help="Input data file"),
253   make_option(c("-o", "--output"), type="character",
254     default="welch_plot.pdf",
255     help="Output file for plotting"),
256   make_option("--xmin", type="double", default=0,
257     help=paste("Minimum frequency (horizontal axis) ",
258       "in output plot [default %default]",sep="")),
259   make_option("--xmax", type="double", default=40,
260     help=paste("Maximum frequency (horizontal axis) ",
261       "in output plot [default %default]",sep="")),
262   make_option("--ymin", type="double", default=-1,
263     help=paste("Minimum spectrum (vertical axis) ",
264       "in output plot [default adaptive]",sep="")),
265   make_option("--ymax", type="double", default=-1,
266     help=paste("Maximum spectrum (vertical axis) ",
267       "in output plot [default adaptive]",sep=""))
268 )
269
270 ## read command line
271 #opt <- parse_args(OptionParser(option_list=option_list))
272 #  
273 ##max_freq = as.numeric(as.character(args[3]))
274 #
275 #### read in data
276 #mydata = extract_data(opt$input)
277
278 #round_outlier <- function(vec)
279 #acq_latency <- function(data)
280 #hld_latency <- function(data)
281 #plot_densities <- function(vecs, names=NULL, outfile="",
282 #plot_density <- function(vec, outfile="",
283 #plot_acq_times <- function(data, outfile="")
284 #print_vec <- function(vec)
285 #print_stats <- function(data)
286 #plot_tput <- function(data)
287 #mydata = read.table(filename, comment.char="#")
288