{'fraction_non_alphanumeric': 0.0374218914554518, 'fraction_numerical': 0.014902057150881134, 'mean_word_length': 4.818321078431373, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 0, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
What helped, and what did not? An Evaluation of the Strategies to Improve Continuous Integration

Continuous integration (CI) is a widely used practice in modern software engineering. Unfortunately, it is also an expensive practice - Google and Mozilla estimate their CI systems in millions of dollars. There are a number of techniques and tools designed to or having the potential to save the cost of CI or expand its benefit - reducing time to feedback. However, their benefits in some dimensions may also result in drawbacks in others. They may also be beneficial in other scenarios where they are not designed to help. In this paper, we perform the first exhaustive comparison of techniques to improve CI, evaluating 14 variants of 10 techniques using selection and prioritization strategies on build and test granularity. We evaluate their strengths and weaknesses with 10 different cost and time-tofeedback saving metrics on 100 real-world projects. We analyze the results of all techniques to understand the design decisions that helped different dimensions of benefit. We also synthesized those results to lay out a series of recommendations for the development of future research techniques to advance this area.


I. INTRODUCTION
Continuous Integration (CI) is a software development practice by which developers integrate code into a shared repository several times a day [13]. However, CI gains adoption in practice, difficulties e.g., [43] and pain points e.g., [61] have been discovered about it. As software companies adopt CI, they execute builds for many of projects, and they do so very frequently. As workload increases, two main problems appear: (1) the time to receive feedback from the build process increases, as software builds often outnumber the available computational resources -having to wait in build queues, and (2) the computational cost of running builds also becomes very high. Previous studies e.g., [38] have highlighted the long time that developers have to wait to receive feedback about their builds. For example, at Google, developers must wait 45 minutes to 9 hours to receive testing results [33]. Even just the dependency-retrieval step of CI can take up to an hour per build [8]. Regarding the high cost of running builds, that is also highlighted in other studies [21], [23], [24], [43], [61]. The cost of CI reaches millions of dollars, e.g., at Google [24] and Microsoft [21]. While other problems exist for CI, we focus on these two because they are the ones that most existing techniques have focused on addressing. They are also interrelated, since cost-reduction techniques may also reduce time-to-feedback -e.g., skipping some tests may cause other tests to fail earlier.
Multiple techniques have been proposed to improve CI. Most of them have the goal of reducing either its time-tofeedback or its computational cost. All such techniques consider the observation of build failures to be more valuable than build passes, because failures provide actionable feedback, i.e., they point to a problem that needs to be addressed. Timeto-feedback-reduction techniques aim to observe failures earlier -by prioritizing failing executions over passing ones. These techniques may operate in two different levels of granularity, by prioritizing: test executions e.g., [11], or build executions e.g., [33]. Computational-cost-reduction techniques aim to observe failures only -by selectively executing failing builds only, saving the cost of executing passing ones. They also may operate at two different levels of granularity, selecting: test executions e.g., [36], or build executions e.g., [2].
To the extent of our knowledge, the existing techniques to improve CI have been evaluated under different settings, making it hard to compare them. Previous studies used different software projects, different metrics, and rarely compared one technique to another. However, we expect that different choices of goal, granularity, and technique design will bring different trade-offs. For example, cost-reduction techniques at build-granularity may be more risky than a test-granularity one, i.e., it may save more cost when it skips all the tests in a build, but it may also make more mistakes if it skips many failing tests in a build. However, the opposite may be true, if test-granularity cost-reduction techniques also skip a large ratio of full builds (i.e., all the tests in the build). On another example, test-selection techniques may be a good alternative to test-prioritization techniques that also saves cost as an added benefit, or they may instead delay the observation of test failures if they mispredict too many of them. To the best of our knowledge, how these trade-offs manifest in practice is still mostly unknown. Empirically understanding these tradeoffs will have valuable practical implications for the design of future techniques and for practitioners adopting them.
In this paper, we perform the first evaluation of the existing strategies to improve CI. We aim to understand the tradeoffs between these techniques for three dimensions: (D1) computational-cost reduction, (D2) missed failure observation, and (D3) early feedback.
For this goal, we performed a large-scale evaluation. We replicated and evaluated all the existing 10 CI-improving techniques from the research literature, representing the two goals (time-to-feedback and computational-cost reduction) and the two levels of granularity (build-level and test-level) for which such techniques have been proposed. We evaluated these techniques under the same settings, using the state-of-the-art dataset of continuous-integration data: TravisTorrent [5]. To be able to study all techniques, we extended TravisTorrent in multiple ways, mining additional Travis logs, Github commits, and building dependency graphs for all our studied projects. Finally, we measured the effectiveness of all techniques with 10 metrics in 3 dimensions. We included every metric that any previous evaluation of our studied techniques used (7), refitted 2 others and designed an additional one.
We analyzed the results obtained by all techniques on all metrics across all 3 dimensions, and we synthesized our observations, to understand which design decisions helped and which ones did not for each dimension. Finally, we further reflect on our results to provide a wide set of recommendations for the design of future techniques in this research area.
The main contributions of this paper are: (1) the first comprehensive evaluation of CI-improving techniques; (2) a collection of metrics to measure the performance of CI-improving techniques over various dimensions; (3) an extended Travis Torrent dataset with: detailed test and commit, and dependencies information; (4) the replication of 14 variants of 10 CIimproving techniques; (5) evidence for researchers to design future CI-improving techniques.

II. APPROACHES TO IMPROVE CONTINUOUS INTEGRATION
We summarize technique families in Table I and discuss each technique in detail in §III-C. Figure 1 depicts a noninterventional example timeline of builds, a timeline in which a build-selection technique is applied, a timeline produced by build-prioritization technique, a timeline where a testselection technique is applied, and a timeline with applying a test-prioritization approach. The example timeline shows a chronological numbered sequence of builds in CI. Each build is made up of at least one test. We depict each test suite as a rectangle with a test number (e.g., t1). Failing tests are then highlighted in gray. The length of the rectangle refers to the time duration for the test to be executed. We depict skipped tests with a dashed rectangle. In the most ideal cost-saving scenario, all of the passing tests would be skipped and all of the failing tests would be observed as soon as possible.
A. Computational-cost Reduction 1) Test-level granularity: Test-selection techniques [18], [21], [36], [38], [55], [64], [66] aim at automatically detect and label tests that are not going to fail. These test-level approaches collect information from test history and project dependency along with the current commit and use some heuristic models to detect failing tests and skip the others. Figure 1 also illustrates how this type of techniques works in the simulation timeline. After a test-selection approach is activated, it selects a subset of tests (e.g., t2 in build #2, t4 in build #4) that it predicts to have a possibility to fail and decides to skip the others (e.g., t3 in build #1, t1 in build #5). For those tests that are not selected in the timeline and get skipped, we depict them as dashed rectangles. In this paper, we consider it can skip some builds when it selects no test in those builds.
2) Build-level granularity: Build-selection techniques [1], [2], [20], [27], [42] aim at automatically detect and label commits and builds that can be CI skipped. Some approaches [20], [27], [42] try to detect failing builds and skip those passing builds to achieve cost-saving. Others [1], [2] aim at identifying commits that can be CI skipped. Figure 1 illustrates how they work in the simulation timeline. As a build-level technique, when build-selection approach decides to skip a build (e.g., build #2, #4, #6), normally it skips all of the tests in that build. The inner test sequence is not changed and all of tests are run in an executed build.
B. Time-to-feedback Reduction 1) Test-level granularity: Test-prioritization techniques [11], [35], [37], [40], [57] try to give high priority to tests that are predicted to be failed so that developers could be informed in a shorter time. This family of approaches normally rearrange the execution order of tests within a build to make predictedto-fail tests run earlier by analyzing information such as test failing history and test context. Figure 1 depicts an example of how this type of techniques works in the simulation timeline. With a test-level approach being activated, the CI system gives different tests different priorities and firstly executes those tests with a higher priority (e.g., t4 in build #2, t2 in build #3) as well as delays low-priority tests (e.g., t1 in build #3, t2 in build #6). The sequence of test executions in this timeline gets rearranged and the start-time for tests that are more likely to fail move ahead in time. Also, all tests are executed at last.
2) Build-level granularity: Build-prioritization techniques [33] aim at automatically prioritizes commits that are waiting for being executed. They favor builds with a larger percentage of test suites that have been found to fail recently and builds including test suites that have not been executed recently as an alternative path. Figure 1 also shows how this family of techniques works in the simulation timeline. Build-prioritization techniques will only be activated when there is a collision of builds (i.e., there are multiple builds waiting to occupy the limited resource). The technique is build-level so it will not change the inner order of the test executions and it will normally change the sequence of tests across builds when the approach is activated (e.g., build #4, #5). None of tests become dashed in this timeline because they all eventually execute.

III. RESEARCH METHOD
In this paper, we replicated and evaluated 14 variants of 10 CI-improving techniques, covering their two goals (timeto-feedback and computational-cost reduction) and their two levels of granularity (build-level and test-level) with 1 perfect technique for the ideal timeline. We evaluate them over 100 software projects in TravisTorrent, which we extended to be able to run all such kinds of techniques.
Our goal is to understand the trade-offs between existing CI-improving techniques, and between the metrics that have been used to evaluate them. We perform 2 empirical studies to analyze these trade-offs for the following 3 dimensions of CI-improving techniques, using 10 metrics. We only include selection techniques in Empirical Study 1 since prioritization techniques have no power in cost saving by nature. We involve selection and prioritization techniques in Empirical Study 2 because both of them can have an impact on fault detection, e.g., wrongly-skipped failing builds by selection approaches can cause delay in fault detection.

A. Data Set
We perform our study over the Travis Torrent dataset [4], which includes 1,359 projects (402 Java projects and 898 Ruby projects) with data for 2,640,825 build instances. We remove "toy projects" from the data set by studying those that are more than one year old, and that have at least 200 builds and at least 1000 lines of source code, which is a criteria applied in multiple other works [42], [25]. To be able to evaluate testgranularity techniques, we also filter out those projects whose build logs do not contain any test information. We focused our study on builds with passing or failing result, rather than error or canceled -since they can be exceptions or may happen during the initialization and get aborted immediately before the real build starts. Besides, in Travis a single push or pullrequest can trigger a build with multiple jobs, and each job corresponds to a configuration of the building step. We did a preliminary investigation of these builds and found that these jobs with the same build identifier normally share the same build result and build duration. Thus, as many existing papers have done [14], [44], [26], we considered these jobs as a single build. After this filtering process, we obtained 82,427 builds from 100 projects (13,464 failing builds).
To be able to execute all our studied techniques, we extended the information in TravisTorrent of these 100 projects in multiple ways. First of all, we needed to know the duration of each individual test for the comparison and replication. Also, to replicate some techniques, e.g., [21], [11], we needed to capture the historical failure ratio for each individual test. To obtain these information, we built scripts to download the raw build logs from Travis and parse them to extract all of the information about test executions, such as test name, duration and outcome. Some techniques, e.g., [36], [2], require additional information that TravisTorrent does not provide for builds, such as the content of commit messages, changed source lines and changed file names. For that, we also mined additional information about commits in the projects' code repositories through Github. Then, we matched each test with its corresponding test file in the project. Finally, to be able to run other techniques, e.g., [18], [36], we built a dependency graph for the source code of each project using a static code analysis tool (Scitool Understand [48]) to determine the paths between the source files and test files.

B. Evaluation Process
We evaluate the techniques in a real-world scenario, to understand as best as possible the behavior that the techniques would show in practice. We take two measures for that.
First, we respect the original chronological order of build and test operations when training techniques. We achieve that by using an 11-fold, chronological variant of cross-validation. For each project, we split its chronological timeline into 11 folds. We use the first chronological fold only for testing, and we iteratively test the other 10 folds. For each testing fold, Build SB Hassan17 [20] SB Abd19 [2] SB Jin20 [27] we train on all the folds that precede it chronologically. This approach has been used in previous works e.g., [7], [52] to avoid training with information that would not be available in practice, i.e., it happens in the future. We follow this approach for all the techniques based on machine learning, e.g., [36]. For techniques that do not require training, e.g., [2], we simply execute them over the same last 10 folds. For techniques that train on data from other projects, i.e., for cross-project technique variants, we also executed them over the same last-10-fold timeline -and we divided them into 10 project folds to do cross-project cross-validation, i.e., for each project, the technique is trained on 90 other projects and tested on its last 10 fold data.
Second, we respect the real-world availability of information. That is, for selection-based techniques, when a build or test is skipped, the technique will not know its outcome. For techniques that rely on the last build or test outcome e.g., [19], we only inform them of the outcome of the last executed build or test. Additionally, when builds are skipped, we accumulate their code changes into the subsequent build.

C. Replicated Techniques
We replicated and studied all the techniques that have been proposed to improve CI by reducing the time to feedback or reducing its cost. In addition to these, there are other techniques that were proposed before CI and that could also be applied for these two goals: test prioritization techniques, and test selection techniques. Therefore, we also replicated and studied a state-of-the-art technique in each of these two categories that were not originally proposed for CI. We summarize all our studied techniques in Table I. In total, we studied 10 techniques, across two goals (reducing time to feedback and cost) and two granularities (test and build levels). Since we also studied multiple variants of some techniques, our evaluation included 14 total technique variants. To provide a reference point, we also studied a perfect technique: Perfect Technique. It achieves the goal of each metric perfectly -it predicts which tests or builds will fail with 100% accuracy, prioritizing or selecting them perfectly.
We include the detailed description for each technique in §IV-A and §V-A.
IV. EMPIRICAL STUDY 1: COST SAVING A. Studied Techniques 1) Test-selection Techniques: We replicated all the testselection techniques that were proposed for improving CI: ST Mach19 [36] and ST Herzig15 [21]. To provide even more context for our study, we also evaluate a state-of-the-art testselection technique: ST Gligoric15 [18] -since test-selection techniques have also been proposed outside the context of CI, e.g., [64], [18], [63], [62], [46], [45]. ST Gligoric15 [18] skips tests that cannot reach the changed files, by tracking dynamic dependencies of tests on files. A test can be skipped in the new revision if none of its dependent files changed. The rationale is that tests that cannot reach changed files cannot detect faults in them. ST Herzig15 [21] is based on a cost model, which dynamically skips tests when the expected cost of running the test exceeds the expected cost of removing it, considering both the machine cost and human inspection cost [3], [22]. This technique tends to skip tests that mostly passed in the past or that have long runtime. ST Mach19 [36] proposes a Machine Learning algorithm with combined features of commit changes and test historical information. We studied two variants of it: one is trained in the past builds within the same project in which it is applied (ST Mach19 W), and the other is trained in the builds of different software projects than the one in which it will be applied (ST Mach19 C). It uses the following features: file extensions, change history, failure rates, project name, number of tests and minimal distance.
2) Build-selection Techniques: We then replicated all buildselection techniques that jave been proposed for improving CI: SB Abd19 [2], and SB Jin20 [27]. To provide even more context for our study, we also replicated a state-of-the-art build-prediction technique: SB Hassan17 [20]. SB Hassan17 [20] predicts every build's outcome based on the information from last build. Builds can be skipped when they are predicted to pass. In our study, information from the previous build is blinded if the build does not get executed. We study two variants of this technique (SB Hassan17 W and SB Hassan17 C) as we did for ST Mach19. SB Abd19 [2] uses a rule-based approach to skip commits that only have safe changes, e.g., changes on configuration or document files. This technique is expected to capture most failing builds since it only skips builds considered safe to skip. SB Jin20 [27] aims at saving CI cost by skipping passing builds. Their strategy is to capture the first failing build in a subsequence of failing builds and continuously build until a passing build appears. We replicated this technique under the configuration that provided the optimal effectiveness [27]. We studied three variants of this technique: SB Jin20 W & SB Jin20 C as we did previously, and also a rule-of-thumb variant (SB Jin20 S) that skips builds with < 4 changed files.

B. D1: Computational-cost Reduction
We studied four metrics for D1. We plot the result of each metric in a box plot where each box represents the distribution of values for all the studied projects.
1) Studied Metrics: Build time saved measures the proportion of total build time that is skipped among all build time per project. It was covered in SB Abd19 [2]. Test time saved measures the same as the previous metric but in terms of test time. The previous work ST Gligoric15 [18] used this metric in its evaluation. It shows how much time applying a technique could save during the phase of test executions. Builds number saved measures the proportion of builds that are saved among all builds. It was studied by SB Abd19 [2] and SB Jin20 [27]. It represents how many resources could be saved as the number of builds. Tests number saved measures the same as the previous metric but in term of tests. Previous papers [18], [21] studied this metric. It represents how many resources could be saved during test executions.
2) Analysis of Results: Comparing Metrics. When we compare the techniques' test number vs. test time saved, most of them saved a very similar ratio of test time than ratio of tests (except ST Herzig15).
When comparing build number vs. build time, buildgranularity techniques saved a very similar ratio of build time as of builds. Also, test-granularity techniques saved a larger ratio of build time than of builds. This means that testgranularity techniques save build time when they skip builds partially -when they skipped some of their tests.
When comparing test number vs. build number, buildgranularity techniques saved a very similar ratio of builds and tests. Also, test-granularity techniques saved a much lower ratio of builds than of tests -some dramatically so (ST Herzig15 and ST Mach19 C). This means that testgranularity techniques saved a low ratio of full builds.
When comparing test time vs. build time, build-granularity techniques saved very similar ratios of test time and build time. Also, test-granularity techniques saved a much lower ratio of build time than of test time. This observation extends our earlier one: every build that these techniques did not skip fully, and thus did not skip its build-preparation time, reduced their ability to save build time to an important extent.
Comparing Granularities. By comparing test vs. buildgranularity techniques, build-granularity techniques generally saved higher build-time cost -except for SB Abd19. Build-granularity techniques have the advantage of skipping both test-execution and build-preparation time, while testgranularity techniques have the advantage of skipping tests spread over many builds, not only on those that get fully skipped. Our observation implies that skipping full builds was a better strategy for saving cost.

Comparing
Techniques. We first observed that SB Mach19 C and SB Jin20 C skipped fewer builds than their counterparts that were trained only with data within the same project (SB Mach19 W, SB Jin20 W). After having been trained with a more diverse set of build and tests (across many projects), these techniques became less confident to skip them. ST Herzig15 saved very low ratio of build time despite saving a large ratio of tests. This is because it very rarely skips tests that failed many times in the past -regardless of the code changes in the build. So, within each build, it very rarely skipped the tests with the most past failures -thus very rarely skipping builds fully. SB Abd19 saved a median 21% build time, which is a relatively high amount, considering that it only skipped builds with non-executable changes, e.g., that only changed formatting or comments. ST Mach19 W and ST Gligoric15 skipped a relatively high ratio of build time (competitively with build selection techniques) because they skipped many full builds. This is because they analyze the relationship between code changes and tests inside a build. ST Gligoric15 skips all tests that cannot execute the code changes, and ST Mach19 W considers the distance between the changes and the tests in its predictor. This allows both techniques to fully skip those builds in which no test can execute the code changes -i.e., when only non-executable code was changed, or when no tests exist to execute the changes. SB Jin20 W and SB Jin20 S saved high ratios of build time, since they both focused on skipping full builds. While SB Jin20 S provided higher savings, we expect it to also skip a higher ratio of skipped failing builds (see §IV-C) -SB Jin20 S simply skips builds with <4 commits. Finally, SB Hassan17 W and SB Hassan17 C skipped too much build time (higher than the perfect baseline). This is because they mostly rely on the status of the previous build, which is unknown if skipped. So, as soon as they observe a passing build, they recurrently skip all subsequent builds. This metric measures the undesired side effect of cost-saving techniques skipping some of the failing test cases. It was used by ST Herzig15 [21].
Proportion of skipped failing builds. This metric measures the proportion of failing builds that are skipped among all failing builds. It was covered in SB Jin20 [27].
2) Analysis of Results: Comparing Metrics. All techniques generally skipped a very similar ratio of failing tests than builds, with small differences.
ST Mach19 C, ST Herzig15, ST Gligoric15, SB Jin20 S skipped a slightly higher ratio of failing tests than builds. This is explained by test-granularity techniques skipping partial builds in addition to full builds, and thus they also skipped a higher ratio of failing tests. The case of SB Jin20 S is different: it skipped a higher ratio of tests because it skipped fewer builds with no failing tests -few changed < 4 files.
SB Abd19, SB Jin20 C, ST Mach19 W and SB Jin20 W skipped a slightly higher ratio of failing builds than tests. This means that these techniques skipped failing builds with lower than average (or no) failing tests, e.g., failing due to configuration or compilation errors (which amount to 35% of  Comparing Granularities. Build-granularity techniques generally skipped higher ratios of failing builds and tests than test-granularity techniques -except for SB Abd19. They generally skipped a higher ratio of all tests and builds. Comparing Techniques. If we rank techniques on these two metrics of side-effect, we observe that they rank almost exactly in the opposite order as they would according to build time saved (for D1). This shows a clear trade-off between costsaving and its side effect of skipping failures.

V. EMPIRICAL STUDY 2. D3: TIME-TO-FEEDBACK REDUCTION
In D3, we study how much prioritization techniques advance the observation of failures and how much the side effect in D2 will influence it. So, we study all the time-to-feedback and computational-cost reduction techniques.

A. Studied Techniques
We only describe here the techniques that we did not describe in earlier sections: prioritization techniques.
1) Test-prioritization Techniques: For this family of techniques, we replicated all the test-prioritization techniques that were proposed for improving CI: PT Elbaum14 [11] and PT Marijan13 [37]. To further extend this study, we also replicated the state-of-the-art test case prioritization (TCP) technique. We chose the technique that provided the highest effectiveness in the most recent evaluation of TCP techniques [35]: PT Thomas14 [57]. TCP was a rich research area before CI became a common practice, e.g., [40], [57], [10], [47]. We apply these techniques to prioritize tests within each build. PT Marijan13 [37] prioritizes tests that failed recently or have a shorter duration. Tests are ordered based on their historical failure data, test execution time and domain-specific heuristics. PT Elbaum14 [11] favors tests that failed either recently or a long time ago. PT Thomas14 [57] uses topic modeling to diversity the tests that get executed earlier. Every prioritized test is selected if it contains the most different topics from the previous test in its identifiers and comments. The rationale behind this is that similar tests often find similar problems.
2) Build-Prioritization Techniques: To the extent of our knowledge, only one technique has been proposed to prioritize software builds, PB Liang18 [33]. PB Liang18 [33] executes builds containing a recently-failing and recently-non-executed test in a collision queue. We apply PB Liang18 to prioritize builds within a build waiting queue, as its previous evaluation did [33]. Queues form when build executions overlap in time.

1) Positions shifted for observed failing tests within a build:
measures the shifted positions for all observed failing tests (prioritized or not). A similar metric to this one was used in the evaluations of PT Marijan13 [37], PT Elbaum14 [11], and PT Thomas14 [57]. For test-selection techniques, we measure the average number of shifted positions for all remaining tests -when a test is skipped, the next one can now run one position earlier.
2) Positions shifted for treated failing builds: measures the number of builds between every treated (delayed/advanced) failing build's original observation position and its new position. This metric was studied by SB Jin20 [27]. For testgranularity techniques, this metric is not impacted, since the build is still executed in the same position. For build-selection techniques, we consider that when a build is skipped, it will run as the next build (its tests will run on it).

3)
Positions shifted for all failing builds: measures the same as the previous one, but now across all failing builds. PB Liang18 used a similar metric in its evaluation [33]. Through this metric, we can understand the impact of the previous metric over all builds.
4) Build-queue-length saved: This is a metric designed by us to measure how applying a technique could relieve the collision problem: when multiple builds are waiting to be executed within a limited resource. We follow the same configuration in PB Liang18's paper. The build-queue-length refers to the median number of builds waiting ahead for each build in each project. With a pre-experiment on all projects, we find that for only one project -"Rails/Rails", the median value of every build's waiting queue is bigger than 0. Thus, we only report the result for this metric on that project.

C. Analysis of Results
Comparing Metrics. When comparing positions shifted for treated failing builds vs. all failing builds, for all techniques, the advance (PB Liang18) or delay (others) that they introduce in the observation of failing builds is much lower when measured across the whole population of failing builds. The upside of this is that the undesired effect of most techniques (i.e., delay of failure observation) is very low across all failing builds (median 0-2 builds). The downside is that the desired effect of PB Liang18 (i.e., advance of failure observation) is also very low across all failing builds (median 0 builds).
Next, we compare the performance of test selection techniques (i.e., the only overlapping technique family) in the positions that observed failing tests shifted within a build vs. the positions that failing builds shifted across all builds. We observe that test selection techniques provided some advancement in the observation of test failures (lower than most test prioritization techniques), while introducing a very low delay in observation of build failures (median 0-2).
Comparing Granularities. We did not observe a substantial difference when comparing granularities -we observed stronger differences when comparing techniques.
Comparing Technique Strategies. When comparing technique strategies (prioritization vs. selection), test-selection techniques provided some advancement in the observation of failing tests within a build, but test-prioritization techniques provided better results overall (except PT Elbaum14).
Comparing Techniques. PT Marijan3 and PT Thomas14 behave very similarly -despite their different approaches to prioritization -and they are both close to perfect, prioritizing most tests correctly. PT Elbaum14 provides a lower advancement of test failures (also lower than many testselection techniques), since it uses a simpler criterionprioritizing tests that were executed very recently or a long time ago. All test-selection techniques provided a very similar advancement of test-failure observation, except ST Herzig15 which was slightly better. Interestingly, ST Herzig15 was one of the techniques with the lowest delay in build-failure observation (median 0 for all failing builds). At the buildgranularity, PB Liang18 had a very low impact in prioritizing builds because builds very rarely occurred concurrently in our dataset -only the Rails project had a meaningful number of concurrent builds. An important metric in PB Liang18's original evaluation was the savings in the build-queue length. We plot the results for all techniques for this metric in Figure 4. Interestingly, we also observed that test-selection and build-selection techniques also had a strong impact in this metric -less so for test-selection techniques and SB Abd19 because they skip fewer full builds (see §IV-B2). Regarding build-selection techniques, those that saved more builds (see §IV-B2) also saved more in the build-queue-length metric, but also introduced higher delays in build-failure observation.

VI. ANSWERS FOR RESEARCH QUESTIONS AND IMPLICATIONS
We synthesize our observations and we lay out their implications to advance this area of research.
A. D1: Computational-cost Reduction 1) RQ1: What design decisions did not help?: First, we report on missed opportunities for saving more computational cost. Cost-saving techniques focused on skipping passing builds and tests, but they did not specifically target those that would provide the highest savings, i.e., slower tests, slower builds, or all tests in a build (in the case of tests-selection). This is demonstrated by the fact that build-granularity techniques saved similar ratios of test number, test time, build number, and build time; and that test-granularity techniques saved similar ratios of test number and test time, and lower ratios of build time than test time.
We also learned that training cost-saving techniques across projects harmed their predictions. In other fields, training with data from multiple projects is considered to increase the accuracy of predictors. For cost-saving techniques, though, this exposed the techniques to more diverse sets of failures, making more builds/tests "look like a failure", resulting on the predictors saving less cost (being less inclined to skip builds and tests).
Test-selection techniques were also limited in the cost that they could save when they did not target saving full builds -ST Mach19 C and ST Herzig15 saved very low build time despite saving a high ratio of tests. An additional aspect that contributed to ST Herzig15 saving limited build time (despite saving high number of tests) is that it only used features characterizing the tests, but not the code changes in the build e.g., missing the opportunity to skip full builds for no-code changes.
2) RQ2: What design decisions helped?: Other design decisions allowed techniques to save high cost. A particularly useful design decision was trying to predict seemingly-safe builds and tests -SB Abd19 saved 21% builds simply by skipping builds with no-code changes, and ST Gligoric15 saved 36% builds skipping tests that did not cover the code changed in the build.
Another decision that provided high cost savings was to skip full builds instead of individual tests -thus also saving build-preparation time. Skipping all tests in a build allows to skip the time to prepare the build (i.e., compilation and other overhead like virtual machine preparation), and we observed that build-preparation takes a large portion of build time. An illustrative example is how ST Gligoric15 and ST Herzig15 saved about the same ratio of test time, but ST Gligoric15 saved much higher build time because it saved a much higher ratio of full builds.
Test-selection techniques, however, performed really well in terms of saving a high ratio of tests (84% by ST Herzig15 and 80% by ST Machalica W). This is because they could save some cost spread out across many builds -i.e., skipping partial builds achieved high cost savings. However, the testselection techniques that skipped full builds also achieved high savings. Intentionally or not, ST Gligoric15 saved many full builds by simply skipping all tests that did not cover the changed code. ST Mach19 W also saved many full builds by approximating the same idea: one of its predictor's features is the distance between the changed code and the test.
3) Implications for Future Techniques: Our results have multiple implications for the design of future techniques. First, we encourage future techniques to consider hybrid approaches to save both full builds and also partial builds, i.e., to save cost at both build and test granularity. Future techniques should also leverage the beneficial factors that we already observed, such as skipping full builds with nocode changes or no tests to cover them. To save more full builds, novel prediction features could be designed, targeting slower builds if possible -which no existing technique attempts. To save more tests, existing techniques already provide very useful features (saving a high ratio of tests), but other new features could be designed to target saving more and slower tests, and considering the relationships between the tests and the code changes in the build. Finally, our observations also show that build time saved is the metric that most comprehensively shows the cost saved by all existing techniques -even though cross-referencing multiple metrics allows for additional observations, as we did in this study.
B. D2: Missed Failure Observation 1) RQ1: What design decisions did not help?: In terms of the proportion of builds and tests that were skipped by costsaving techniques, we generally observe that the decisions that made techniques save higher cost also made them make more mistakes, i.e., skip higher ratios of failing builds and tests. It was also particularly interesting that seeminglysafe techniques -SB Abd19 and ST Gligoric15 -still showed pretty high ratios of skipped failing builds and tests. Our study thus shows that skipping builds with no-code changes or without tests to execute them is not enough to guarantee that they will not fail. A quick look discovered that the builds and tests skipped by these techniques failed for different reasons, such as configuration or compilation errors (present in 35% of failing builds).
2) RQ2: What design decisions helped?: One design decision that reduced the skipped failing tests and builds was training techniques across projects. All the C variants skipped lower ratios than their W counterparts (except SB Hassan17 C). Also test-granularity techniques generally skipped lower ratios of failing tests than buildgranularity techniques did of builds.
3) Implications for Future Techniques: These results imply multiple recommendations for future techniques. First, future techniques should design novel features to predict failures that are caused by no-code changes, e.g., configuration changes, to avoid assuming that seemingly-safe builds will not fail. Second, future techniques should attempt to break this trade-off between saving cost and skipping failures. Existing techniques generally increase cost savings by also increasing missed failure observations. Future techniques should attempt to improve one of the two dimensions by keeping the other one fixed (or optimal). Finally, future studies should propose new metrics to better assess the trade-off between cost-saving and skipped-failures of various techniquessince most techniques succeed in one at the expense of the other. SB Jin20 [27] proposed the harmonic mean of the two as a balanced metric, but further study is granted to understand whether both should be valued equally or in a weighted manner -particularly considering the much higher ratio of passes to failures in CI datasets.
C. D3: Time-to-feedback Reduction 1) RQ1: What design decisions did not help?: Unsurprisingly, build-selection techniques did not advance the observation of build failures at all, but at least they introduced very low delays in the observation of failing builds (and also saved some computational cost). Similarly, test-selection techniques also introduced a small delay in the observation of test failures. Build-prioritization also showed very limited advancement in observing failing builds, but that was mainly because only one of our studied projects (open-source) had some contention in the build queue. We expect that industrial software project would obtain a much higher benefit from this approach. Finally, we also observed that the build-selection techniques that produced higher cost savings also introduced higher delays in build-failure observation, showing again the tension between both goals.
2) RQ2: What design decisions helped?: The best techniques to provide early feedback were test-prioritization techniques. In fact, PT Thomas14 provided near perfect results. We also found that test-selection techniques provided lower, but competitive advancement of test failure observation, while also providing some cost savings. For example, ST Herzig15 provided high advancement of test-failure observation within a build, with very low delay of buildfailure observation, while also saving some computational cost. Similarly, we observed that build-selection techniques could also provide reductions in build-queue-length that were competitive with build prioritization.
3) Implications for Future Techniques: For future techniques, we recommend to combine test prioritization with test selection techniques -since prioritization techniques could stop after the first failure is identified, and save the cost of running the remaining tests. We found that test-prioritization techniques already reached very high results (PT Thomas14 is near perfect), so the features that they use could be also very useful for test selection to save cost. Conversely, existing testselection techniques that already perform very well for costsavings (e.g., ST Herzig15) could be improved in their ability to advance failure observation. Similarly, we recommend to further study the application of build-selection techniques to provide early observation of build failures by reducing the build queue via skipping builds in industrial projects in which parallel build requests are a larger issue. Finally, there is also space to develop new metrics that could capture the balance that techniques provide across all dimensions D1-D3.

D. Standing on the Shoulders of Giants
Our findings confirm and extend previous work: 1) D1: Beller et al. [4] observed that test time is a low proportion of build time. We extend this observation by finding that our studied test-selection techniques infrequently skipped full (all tests within) builds, which strongly limited their costsaving ability. We thus recommend test-selection to incentivize skipping full builds to save higher cost in CI.
2) D2: Jin and Servant [27] observed a trade-off of higher cost savings incurring more missed build failures in their technique. We extend this observation by finding that all our studied techniques were affected by that trade-off (techniques ranked equally by cost savings as by missed failures). We additionally identified clear strategies that made techniques miss fewer failures: training across projects, and operating at test granularity. We also observed that a seemingly-safe technique [2] still missed a high ratio of failures. Finally, we elicited the need for better prediction of safe builds, and new metrics to compare trade-offs.
3) D3: Herzig et al. [21] found that their test-granularity technique incurs low delay in build-failure observations. We extend this observation by finding that all our other studied test-granularity techniques also incur low build-failureobservation delay, measured across all failing builds.

A. Internal Validity
To guard internal validity, we carefully tested our evaluation tools on subsets of our dataset while developing them.
Our analysis could also be influenced by incorrect information in our analyzed dataset. For this, we studied a popular dataset that is prevalent among continuous integration studies: TravisTorrent [6]. Furthermore, many of our studied techniques [2], [20], [27], [33] were originally evaluated on TravisTorrent projects. Additionally, we extensively curated TravisTorrent, removing: toy projects following standard practice [25], [42], unusable projects for test-granularity techniques, and cancelled builds as in past work [14], [26], [44]. Finally, we also followed the advice in Gallaba et al.'s study [14] to consider the nuance in the TravisTorrent dataset. We did so in the following ways: (1) We considered passing builds with ignored failures as passing. Developers manually flag such failures to be ignored when they cannot officially support them [14], and thus should not represent the status of the build. (2) We considered builds that fail after another failure as correctly labeled, because they flag an unsolved problem, being informative for developers. (3) We considered failing builds with passing jobs as failing builds. If at least one job fails, it signals a problem, informing developers.
Our results may also be affected by flaky tests causing spurious failing builds. However, CI systems are expected to function even in the presence of flaky tests, since most companies do not consider it economically viable to remove them, e.g., [36], [39]. Besides, cross validation may make unrealistic use of chronological events To address this problem, we used time-based cross validation [7].
Our observed build and test runtimes may have been influenced by the load experienced in the build server at the time. However, we consider this potential impact to be very low, since we observed that the standard variance in test duration across builds was 0.5 seconds.

B. External Validity
To increase external validity, we selected the popular dataset TravisTorrent, which has been analyzed by many other research works. The projects we chose were all Java or Ruby projects, because there are no projects with other programming languages in the data set. Although these two programming languages are popular, different CI habits in other languages may provide slightly different results to the ones in this study. Our observations may slightly vary for separate software projects, but our goal was to derive general observations for a real-world population of software projects.

C. Construct Validity
A threat to construct validity is whether we studied software projects that are similar to those that suffer most accutely from high CI cost and delays in failure observation, e.g., the projects at Google [24] and Microsoft [21]. We studied the TravisTorrent dataset, which is the standard dataset used in the literature to evaluate techniques to save cost in CI [2], [27], [33], [9]. One of our studied projects (Rails) is particularly similar to industrial software projects. Rails was used alongside two other Google datasets to evaluate PB Liang18 et al. [33], and it had similar magnitudes of test suites (thousands), test executions (millions) and test execution time (millions of seconds).
Nevertheless, early observation (or prediction) of build failures is beneficial, regardless of how much load a project's CI system experiences. It allows developers to not have to wait for builds to finish, which is the motivation of multiple previous works, e.g., [20], [2]. In particular, Abdalkareem et al. [2] found that developers from small projects -as small as 168 commits -also chose to manually skip commits in CI to save time. These savings can be substantial for the projects in our studied dataset: test-suite runtime varies from project to project (median 2.3 mins, 75th percentile 26 mins) but, more importantly, saving full builds could save much higher cost (median 14 mins, 75th percentile 52 mins). Also, many builds (20%) take longer than 30 minutes [4]. Test-selection could save higher cost if it leaned harder towards skipping full builds, but we found in this study that this incentive is not yet strongly leveraged by our studied test selection techniques.

A. Empirical Studies of CI and its Cost and Benefit
Multiple researchers focused on understanding the practice of CI, studying both practitioners e.g., [24] and software repositories [60]. Vasilescu et al. studied CI as a tool in social coding [59], and later studied its impact on software quality and productivity [60]. Zhao et al. studied the impact of CI in other development practices, like bug-fixing and testing [65]. Stahl et al. [56] and Hilton et al. [24] studied the benefits and costs of using CI, and the trade-offs between them [23]. Lepannen et al. similarly studied the costs and benefits of continuous delivery [31]. Felidré et al. [12] studied the adherence of projects to the original CI rules [13]. Other recent studies analyzed testing practices [16], difficulties [43] and pain points [61] in CI.
The high cost of running builds is highlighted by many empirical studies as an important problem in CI [24], [23], [43], [61], [21] -which reaches millions of dollars in large companies, e.g., at Google [24] and Microsoft [21]. People [23], [60] believe that the benefit of CI is mainly lying in the early fault detection. Others [24], [31] find that projects adopting CI are able to adopt pull requests and release in a shorter time. Some also find that CI can help developer team in other areas such as providing a common build environment [23] and increasing team communication [56].

B. Approaches to Reduce Time-to-feedback in CI
A related effort for improving CI aims at speeding up its feedback by prioritizing its tasks. The most common approach in this direction is to apply test case prioritization (TCP) techniques e.g., [35], [40], [11], [37], [10], [47], [67] so that builds fail faster. These techniques, even though not designed to work in CI environment, have been claimed to have a potential to provide CI users earlier fault observation. Another similar approach achieves faster feedback by prioritizing builds instead of tests [33]. Their paper grants higher priority to those builds that are more likely to fail according to the historical failing information and works well for those projects that have a ton of collision issues. Naturally, these kinds of techniques don't provide benefit in saving the cost. In this paper, we study both test-prioritization techniques as well as build-prioritization techniques in terms of advancement of failure observation and compare them with selection techniques.

C. Approaches to Reduce Cost of CI
A popular effort to reduce the cost of CI focuses on understanding what causes long build durations e.g., [17], [58]. Thus, most of the approaches that reduce the cost of CI aim at making builds faster by running fewer test cases on each build. It is found that a ton of passing tests could be saved in this way [29]. Some approaches use historical test failures to select tests [21], [11]. Others run tests with a small distance to code changes [38] or skip testing unchanged modules [55].
Recently, Machalica et al. predicted test case failures using a machine learning classifier [36]. These techniques are based on the broader field of regression test-selection (RTS) e.g., [66], [64], [18], [63], [62], [46], [45]. While these techniques focus on making every build cheaper, other work addresses the cost of CI differently: by reducing the total number of builds that get executed. A related recent technique saves cost in CI by not building when builds only include non-code changes [2], [1]. They firstly create a rule-based selection technique and then take advantage of machine learning algorithm to improve the accuracy. Then Jin and Servant propose a build strategy that developing team should skip those less informative passing builds through build outcome prediction. Finally, other complementary efforts to reduce build duration have targeted speeding up the compilation process e.g., [8] or the initiation of testing machines e.g., [15]. In this paper, we refer cost-reduction techniques as selection techniques. We pick techniques in both build-selection techniques and test-selection techniques and examines their performance in different costsaving and fault-observation metrics.

D. Evaluation frameworks for similar techniques
Multiple research works focus on comparing cross-tool performance with an evaluation framework. Zhu et al. [66] propose a regression test selection framework to check the output against rules inspired by existing test suites for three techniques. Leong et al. [30] propose a test selection algorithm evaluation method and evaluate five potential regression test selection algorithms, finding that the test selection problem remains largely open. Najafi et al. [41] studied the impact of test execution history on test selection and prioritization techniques. Luo et al. [35] conduct the first empirical study comparing the performance of eight test prioritization techniques applied to both real-world and mutation faults and find that the relative performance of the studied test prioritization techniques on mutants may not strongly correlate with performance on real faults. Lou et al. [34] systematically created a taxonomy of existing works in test-case prioritization, classifying them in: algorithms, criteria, measurements, constraints, scenarios, and empirical studies.
Differently to these works, our study in this paper specifically targets the context of CI, and it has a broader focus than test prioritization or selection. Our study is the first to compare all the techniques proposed to reduce time-to-feedback or cost in CI, including prioritization and selection techniques, at test and build granularities. We performed observations comparing across 2 goals, 3 dimensions, 10 metrics, 2 granularities, and 10 techniques. Most of our observations required comparisons at broad scope. For example: we revealed the need for a new incentive in test selection to skip full test suites (to also save build-preparation time), which would not be relevant in studies outside the scope of CI.

IX. CONCLUSIONS AND FUTURE WORK
In this article, we performed the most exhaustive evaluation of CI-improving techniques to date. We evaluated 14 variants of 10 CI-improving approaches from 4 families on 100 realworld projects. We compared their results across 10 metrics in 3 dimensions. We derived many observations from this evaluation, which we then synthesized to understand the design decisions that helped each dimension of metrics, as well as those that had a negative impact on it. Finally, we provide a set of recommendations for future techniques in this research area to take advantage of the factors that we observe were beneficial, and we lay out also future directions to improve on those factors that were not. We lay out plans to combine approaches at test and build granularities to save further costs, and to combine selection and prioritization approaches to improve on the early observation of failures while also saving some cost. Such techniques could consider additional historybased prediction features, such as the project's code-change history, e.g., [50], [51], [49], [53], [54], since test-execution history was beneficial for some techniques, e.g., [21]. We also discuss the need of future metrics to capture the various characteristics of these techniques in a more holistic way. In the future, we will work on designing a comprehensive technique that combines selection and prioritization as well as build and test granularities to maximize the benefit of CI while reducing its cost as much as possible.

X. REPLICATION
We include a replication package for our paper [28].