7
$\begingroup$

I work on a large programming team, and I run a suite of performance tests on every change that is made in our program, which basically measure time it takes to run the test. For every code change, we run these tests, and we calculate whether the change caused the test to run slower by doing a two-sample t test (against the results from the previous code change). This works decently, but the problem is that we only have a small number of sample data points, generally 5 per test, per code change. There are about 400 individual measurements that we track performance on, so we see some noise in our results (i.e. the t-test will yield a small p value for tests which are not actually any faster/slower due to the code change).

Even though we have a small number of sample points on each code change, we have a very large history of results. I want to use this historical data to help us, but I'm not sure how I can. A problem I'm worried about is that any code change may cause the tests to run faster or slower, so just blindly aggregating historical data will yield a poor result. Are there any statistical tests that will help me with this?

For a little more info: Most of the time code changes do not have any impact on performance, and those of them that do cause performance tests to run faster or slower only do so on a handful of the 400 tests. Which means that for any given test, it could be hundreds of code changes before a change actually makes the test run faster or slower.

To clarify, I want to figure out when a code change actually causes a test to run faster or slower. What options do I have?

$\endgroup$
9
  • 3
    $\begingroup$ Lots of unexplained jargon/abbreviations (I fixed some but stuff like 'dev' - is that 'developer', or some other thing?), the use of statistical jargon like 'regression' to mean something else without clearly flagging it as such; and lack of a clearly defined question all combine to make this a very hard question to answer. We're not software developers. $\endgroup$
    – Glen_b
    Commented Jun 17, 2013 at 5:04
  • $\begingroup$ My apologies. I'll try to clear it up in the morning. I was originally going to post this on stackoverflow when I saw a link to here and I didn't think to change my wording very much. I did not mean regression in the statistical sense but in the software definition. To use more general terms, regression=test ran slower, improvement =test ran faster. A checkin is a code change that a developer submits. I run tests using versions of our program that are built after every new piece of code is submitted, and I want to find when a code change has actually caused a test to actually run slower. $\endgroup$ Commented Jun 17, 2013 at 9:12
  • $\begingroup$ I suggest you use those phrases in place of the words each time, as annoying as that will probably be. At the least, define them as here. $\endgroup$
    – Glen_b
    Commented Jun 17, 2013 at 9:21
  • $\begingroup$ This is a really interesting question/problem. I am not fully qualified to tackle this; I think in a way your system is Markovian in the sense that all the "slow-down" effects due to a code change are compared with immediately previous condition of your system but on the other hand some changes would have a "delaying" effect regardless of the system previous state so it is not "memoryless". My first initial response would be that "naive" data aggregation is wrong. Maybe something related with Kalman filtering... I might think something and say more tomorrow. $Cool problem$! $\endgroup$
    – usεr11852
    Commented Jun 17, 2013 at 21:51
  • $\begingroup$ Just to see I understand: after you change the code, you run 400 different tests, running each of these 5 times? $\endgroup$
    – Bitwise
    Commented Jun 20, 2013 at 19:31

3 Answers 3

1
$\begingroup$

Here's something that's not really an answer to your question, but may be helpful for your problem:

One of the difficulties you mention is that you are doing ~400 t-tests, and so will end up with lots of spurious small p-values. One useful thing to use here is `false discovery rate' (FDR) analysis, which tries to determine what fraction of the small p-values are consistent with the null. If I were working on your problem, I'm pretty sure I'd use some FDR method.

FDR control is a big topic (http://en.wikipedia.org/wiki/False_discovery_rate) so I won't try to describe it fully, but here are some links to get you started if you're interested:

$\endgroup$
2
  • 1
    $\begingroup$ I wish they had a like-button that said "this isn't an answer, but it is worthwhile material". :) $\endgroup$ Commented Jun 27, 2013 at 12:04
  • $\begingroup$ @EngrStudent: vote up! $\endgroup$
    – nomen
    Commented Oct 26, 2013 at 0:00
1
$\begingroup$

HEre is something that isn't exactly an answer to the original question, but might be valuable and might also act as an answer to the question behind the question which is something to the effect of: "how do I make the most of my programming to speed up my code?"

I bet you can modify a section, and re-run several times, much more quickly than you can re-write parts of it. If that is the case, then randomly inserting random-length pauses, and recording both section placed, length of pause inserted, and impact to overall runtime you could determine how a delay to one part of the code propagates to the rest of it.

Is knowing which parts have the biggest impacts to overall speed your goal? Is the 'stochastic' intervention a plausible approach to something like this?

Best of luck.

$\endgroup$
8
  • $\begingroup$ There are plenty of tools out there that do this and more. It's called profiling. $\endgroup$ Commented Sep 25, 2013 at 15:39
  • $\begingroup$ @MarcClaesen - feel free to post links. I would like to learn more about this. $\endgroup$ Commented Sep 25, 2013 at 20:15
  • 1
    $\begingroup$ gprof and valgrind are open source and widely used. The two main approaches to profiling are instrumentation and sampling. Your idea resembles sampling. $\endgroup$ Commented Sep 25, 2013 at 20:36
  • $\begingroup$ I use MatLab and it has a profiler that looks like a gui interface to gprof. Might an interpreted program like MatLab/Python/R have an advantage here? I am also not seeing the Monte-Carlo analysis of inserted pauses. Is that done anywhere? $\endgroup$ Commented Sep 25, 2013 at 22:27
  • $\begingroup$ Sampling profilers simply interrupt the program on regular intervals and see which code is currently being executed. If a certain segment is a hot spot, it will inevitably be sampled often. This is similar to your idea. The only difference is that, in general, people don't care much about what if this code segment got slower, instead we want to know what is my current bottleneck to focus on improving that code segment. JIT-compiled programs can get additional benefits from dynamic profiling to assess which code fragments actually get executed. Native code is still faster, though. $\endgroup$ Commented Sep 26, 2013 at 6:17
0
$\begingroup$

First you want to know if there has been a statistically significant change in total testing time. Second, if there has been a change, which tests have changed?

This is what I would do: Within each code state compute the mean for each time variable. Then for each time variable compute the standard deviation of its means. This measure of variability is how you incorporate information from the entire history of testing.

Next use $t$-tests to check for changes from the previous code state (the null hypothesis is that the mean times in the current state equal the previous state means).

The primary test is simply if there has been a change in overall time, so you're not examining a joint hypothesis and a simple $t$-test is sufficient. If there has been a change in total time, then I would compute $t$-statistics for the separate tests to see which tests are responsible for the change.

A rough example written in R:

# Hypothetical time data over 100 states:
state <- rep(1:100, each = 5)
t1 <- 1 + runif(500)
t2 <- 2 + runif(500)
t3 <- 3 + runif(500)
total_time <- t1 + t2 + t3
d <- data.frame(state, total_time, t1, t2, t3)

# Suppose current state is 100, then we want to compare it to state 99
# while taking into account information on variability based on all historical data.

# Means within historical code states:
d_means <- aggregate(d, by=list(d$state), mean)

# Standard deviation of means up to current state:
d_stdev <- sapply(d_means[d_means$state < 100, ], sd)

# Central limit theorem tells us means are approx. normally distributed.
# So we can use t-tests.

# Test if total testing time has changed in current state:
previous <- subset(d_means, state == 99)
current  <- subset(d_means, state == 100)
t_total_time <- (current$total_time - previous$total_time) / d_stdev[['total_time']]

# Now, for example, if abs(t_total_time) > 1.96, then time change is statistically
# significant at roughly 5% level.

# Check each test to see which ones have statistically significant change from
# previous state:
t_test_1 <- (current$t1 - previous$t1) / d_stdev[['t1']]
t_test_2 <- (current$t2 - previous$t2) / d_stdev[['t2']]
t_test_3 <- (current$t3 - previous$t3) / d_stdev[['t3']]

print(t_total_time)
print(t_test_1)
print(t_test_2)
print(t_test_3)
$\endgroup$
3
  • 1
    $\begingroup$ This is interesting, but I don't think it is workable for us. We can't just add up total time. Since some tests might speed up and others might slow down and they could cancel each other out. Also, not all are on the same order of magnitude. Some tests run in 1ms, and others take 1000ms. So a change in the 1ms test case would almost certainly be overshadowed by variance from the 1000ms testcase. $\endgroup$ Commented Jun 25, 2013 at 19:03
  • $\begingroup$ I was thinking you cared most about total time but re-reading your question I see your focus is the individual test times. But that is fine, the code I posted still works for that. Just ignore the total time t-test and look at the t-stats for the individual tests. By using the individual test historical variation (the d_stdev variables in the R code) it accounts for differences in order of magnitude. $\endgroup$ Commented Jun 25, 2013 at 22:19
  • $\begingroup$ Good statistical process control looks at both the mean and the standard deviation. If you have a code change that substantially changes the variability of the run-time, that can be a significant change. itl.nist.gov/div898/handbook/pmc/pmc.htm $\endgroup$ Commented Jun 27, 2013 at 12:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.