Skip to content

Commit

Permalink
Merge pull request #570 from bdemers/bd-add-mutators
Browse files Browse the repository at this point in the history
Add delete-file and copy-file mutators
  • Loading branch information
lptr authored Sep 3, 2024
2 parents 1125b1e + 40cfff2 commit fcc1ecc
Show file tree
Hide file tree
Showing 31 changed files with 416 additions and 126 deletions.
32 changes: 19 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,27 +291,29 @@ Values are optional and default to the values provided on the command-line or de

A scenario can define changes that should be applied to the source before each build. You can use this to benchmark or profile an incremental build. The following mutations are available:

- `apply-build-script-change-to`: Add a statement to a Groovy or Kotlin DSL build script, init script or settings script. Each iteration adds a new statement and removes the statement added by the previous iteration.
- `apply-project-dependency-change-to`: Add project dependencies to a Groovy or a Kotlin DSL build script. Each iteration adds a new combination of projects as dependencies and removes the projects added by the previous iteration.
- `apply-abi-change-to`: Add a public method to a Java or Kotlin source class. Each iteration adds a new method and removes the method added by the previous iteration.
- `apply-non-abi-change-to`: Change the body of a public method in a Java or Kotlin source class.
- `apply-h-change-to`: Add a function to a C/C++ header file. Each iteration adds a new function declaration and removes the function added by the previous iteration.
- `apply-cpp-change-to`: Add a function to a C/C++ source file. Each iteration adds a new function and removes the function added by the previous iteration.
- `apply-property-resource-change-to`: Add an entry to a properties file. Each iteration adds a new entry and removes the entry added by the previous iteration.
- `apply-android-layout-change-to`: Add a hidden view with id to an Android layout file. Supports traditional layouts as well as Databinding layouts with a ViewGroup as the root element.
- `apply-android-manifest-change-to`: Add a permission to an Android manifest file.
- `apply-android-resource-change-to`: Add a string resource to an Android resource file. Each iteration adds a new resource and removes the resource added by the previous iteration.
- `apply-android-resource-value-change-to`: Change a string resource in an Android resource file.
- `apply-android-manifest-change-to`: Add a permission to an Android manifest file.
- `apply-android-layout-change-to`: Add a hidden view with id to an Android layout file. Supports traditional layouts as well as Databinding layouts with a ViewGroup as the root element.
- `apply-build-script-change-to`: Add a statement to a Groovy or Kotlin DSL build script, init script or settings script. Each iteration adds a new statement and removes the statement added by the previous iteration.
- `apply-cpp-change-to`: Add a function to a C/C++ source file. Each iteration adds a new function and removes the function added by the previous iteration.
- `apply-h-change-to`: Add a function to a C/C++ header file. Each iteration adds a new function declaration and removes the function added by the previous iteration.
- `apply-kotlin-composable-change-to`: Add a `@Composable` function to a Kotlin source file.
- `apply-non-abi-change-to`: Change the body of a public method in a Java or Kotlin source class.
- `apply-project-dependency-change-to`: Add project dependencies to a Groovy or a Kotlin DSL build script. Each iteration adds a new combination of projects as dependencies and removes the projects added by the previous iteration.
- `apply-property-resource-change-to`: Add an entry to a properties file. Each iteration adds a new entry and removes the entry added by the previous iteration.
- `clear-android-studio-cache-before`: Invalidates the Android Studio caches before the scenario is executed (`SCENARIO`) or before the build is executed (`BUILD`). Due to Android Studio client specifics before cleanup (`CLEANUP`) is not supported. Note: cleaning the Android Studio caches is run only when Android Studio sync (`android-studio-sync`) is used.
- `clear-build-cache-before`: Deletes the contents of the build cache before the scenario is executed (`SCENARIO`), before cleanup (`CLEANUP`) or before the build is executed (`BUILD`).
- `clear-gradle-user-home-before`: Deletes the contents of the Gradle user home directory before the scenario is executed (`SCENARIO`), before cleanup (`CLEANUP`) or before the build is executed (`BUILD`).
The mutator retains the `wrapper` cache in the Gradle user home, since the downloaded wrapper in that location is used to run Gradle.
Requires to use the `none` daemon option to use with `CLEANUP` or `BUILD`.
- `clear-configuration-cache-state-before`: Deletes the contents of the `.gradle/configuration-cache-state` directory before the scenario is executed (`SCENARIO`), before cleanup (`CLEANUP`) or before the build is executed (`BUILD`).
- `clear-gradle-user-home-before`: Deletes the contents of the Gradle user home directory before the scenario is executed (`SCENARIO`), before cleanup (`CLEANUP`) or before the build is executed (`BUILD`).
The mutator retains the `wrapper` cache in the Gradle user home, since the downloaded wrapper in that location is used to run Gradle.
Requires to use the `none` daemon option to use with `CLEANUP` or `BUILD`.
- `clear-jars-cache-before`: Deletes the contents of the instrumented jars cache before the scenario is executed (`SCENARIO`), before cleanup (`CLEANUP`) or before the build is executed (`BUILD`).
- `clear-project-cache-before`: Deletes the contents of the `.gradle` and `buildSrc/.gradle` project cache directories before the scenario is executed (`SCENARIO`), before cleanup (`CLEANUP`) or before the build is executed (`BUILD`).
- `clear-transform-cache-before`: Deletes the contents of the transform cache before the scenario is executed (`SCENARIO`), before cleanup (`CLEANUP`) or before the build is executed (`BUILD`).
- `clear-jars-cache-before`: Deletes the contents of the instrumented jars cache before the scenario is executed (`SCENARIO`), before cleanup (`CLEANUP`) or before the build is executed (`BUILD`).
- `clear-android-studio-cache-before`: Invalidates the Android Studio caches before the scenario is executed (`SCENARIO`) or before the build is executed (`BUILD`). Due to Android Studio client specifics before cleanup (`CLEANUP`) is not supported. Note: cleaning the Android Studio caches is run only when Android Studio sync (`android-studio-sync`) is used.
- `copy-file`: Copies a file or a directory from one location to another. Has to specify a `source` and a `target` path; relative paths are resolved against the project directory.
- `delete-file`: Deletes a file or a directory. Has to specify a `target` path; when relative it is resolved against the project directory.
- `git-checkout`: Checks out a specific commit for the build step, and a different one for the cleanup step.
- `git-revert`: Reverts a given set of commits before the build and resets it afterward.
- `iterations`: Number of builds to actually measure
Expand Down Expand Up @@ -344,6 +346,10 @@ They can be added to a scenario file like this:
clear-build-cache-before = SCENARIO
clear-transform-cache-before = BUILD
show-build-cache-size = true
copy-file {
source = "../develocity.xml"
target = ".mvn/develocity.xml"
}
git-checkout = {
cleanup = "efb43a1"
build = "master"
Expand Down
12 changes: 6 additions & 6 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,25 @@ val profilerPlugins by configurations.creating
dependencies {
implementation(libs.toolingApi)
implementation("com.google.code.findbugs:annotations:3.0.1")
implementation("com.google.guava:guava:27.1-android") {
because("Gradle uses the android variant as well and we are running the same code there.")
}
implementation("com.google.guava:guava:32.1.2-jre")
implementation("com.typesafe:config:1.3.3")
implementation("org.apache.commons:commons-math3:3.6.1")
implementation("com.github.javaparser:javaparser-core:3.18.0")
implementation("net.sf.jopt-simple:jopt-simple:5.0.4")
implementation("org.apache.ant:ant-compress:1.5")
implementation("commons-io:commons-io:2.6")
implementation("org.apache.commons:commons-compress:1.27.1") {
because("Avoid old version of commons-compress introduced by ant-compress")
}
implementation("commons-io:commons-io:2.16.1")
implementation("org.openjdk.jmc:flightrecorder:8.0.1")
implementation("com.googlecode.plist:dd-plist:1.23") {
because("To extract launch details from Android Studio installation")
}
implementation("com.google.code.gson:gson:2.8.6") {
implementation("com.google.code.gson:gson:2.11.0") {
because("To write JSON output")
}
implementation(project(":client-protocol"))


gradleRuntime(gradleApi())
gradleRuntime(libs.toolingApi)
profilerPlugins(project(":chrome-trace"))
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/gradle/profiler/ScenarioDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void validate() {
}

/**
* A specific title defined for the scenario to be used in reports (defaults to {@link #getName()}.
* A specific title defined for the scenario to be used in reports (defaults to {@link #getName()}).
*/
public String getTitle() {
return title != null ? title : name;
Expand Down
12 changes: 10 additions & 2 deletions src/main/java/org/gradle/profiler/ScenarioLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,18 @@
import org.gradle.profiler.mutations.ApplyValueChangeToAndroidResourceFileMutator;
import org.gradle.profiler.mutations.BuildMutatorConfigurator;
import org.gradle.profiler.mutations.BuildMutatorConfigurator.BuildMutatorConfiguratorSpec;
import org.gradle.profiler.mutations.DefaultBuildMutatorConfiguratorSpec;
import org.gradle.profiler.mutations.ClearArtifactTransformCacheMutator;
import org.gradle.profiler.mutations.ClearBuildCacheMutator;
import org.gradle.profiler.mutations.ClearConfigurationCacheStateMutator;
import org.gradle.profiler.mutations.ClearGradleUserHomeMutator;
import org.gradle.profiler.mutations.ClearJarsCacheMutator;
import org.gradle.profiler.mutations.ClearProjectCacheMutator;
import org.gradle.profiler.mutations.CopyFileMutator;
import org.gradle.profiler.mutations.FileChangeMutatorConfigurator;
import org.gradle.profiler.mutations.GitCheckoutMutator;
import org.gradle.profiler.mutations.GitRevertMutator;
import org.gradle.profiler.mutations.DeleteFileMutator;
import org.gradle.profiler.mutations.ShowBuildCacheSizeMutator;
import org.gradle.profiler.studio.AndroidStudioSyncAction;
import org.gradle.profiler.studio.invoker.StudioGradleScenarioDefinition;
Expand Down Expand Up @@ -91,6 +94,8 @@ class ScenarioLoader {
private static final String ANDROID_STUDIO_JVM_ARGS = "studio-jvm-args";
private static final String ANDROID_STUDIO_IDEA_PROPERTIES = "idea-properties";
private static final String JVM_ARGS = "jvm-args";
private static final String DELETE_FILE = "delete-file";
private static final String COPY_FILE = "copy-file";

private static final Map<String, BuildMutatorConfigurator> BUILD_MUTATOR_CONFIGURATORS = ImmutableMap.<String, BuildMutatorConfigurator>builder()
.put(APPLY_BUILD_SCRIPT_CHANGE_TO, new FileChangeMutatorConfigurator(ApplyBuildScriptChangeFileMutator.class))
Expand All @@ -115,6 +120,8 @@ class ScenarioLoader {
.put(SHOW_BUILD_CACHE_SIZE, new ShowBuildCacheSizeMutator.Configurator())
.put(GIT_CHECKOUT, new GitCheckoutMutator.Configurator())
.put(GIT_REVERT, new GitRevertMutator.Configurator())
.put(DELETE_FILE, new DeleteFileMutator.Configurator())
.put(COPY_FILE, new CopyFileMutator.Configurator())
.build();

private static final List<String> ALL_SCENARIO_KEYS = ImmutableList.<String>builder()
Expand Down Expand Up @@ -257,8 +264,9 @@ static List<ScenarioDefinition> loadScenarios(File scenarioFile, InvocationSetti
File mavenHome = getToolHome(executionInstructions);
File outputDir = new File(scenarioBaseDir, "maven");
int warmUpCount = getWarmUpCount(settings, scenario);
Map<String, String> systemProperties = ConfigUtil.map(scenario, SYSTEM_PROPERTIES, settings.getSystemProperties());
List<BuildMutator> mutators = getMutators(scenario, scenarioName, settings, warmUpCount, buildCount);
definitions.add(new MavenScenarioDefinition(scenarioName, title, targets, mutators, warmUpCount, buildCount, outputDir, mavenHome));
definitions.add(new MavenScenarioDefinition(scenarioName, title, targets, systemProperties, mutators, warmUpCount, buildCount, outputDir, mavenHome));
} else if (!settings.isBazel() && !settings.isBuck() && !settings.isMaven()) {
List<GradleBuildConfiguration> versions = ConfigUtil.strings(scenario, VERSIONS, settings.getVersions()).stream().map(inspector::readConfiguration).collect(
Collectors.toList());
Expand Down Expand Up @@ -314,7 +322,7 @@ private static StudioGradleScenarioDefinition newStudioGradleScenarioDefinition(
}

private static List<BuildMutator> getMutators(Config scenario, String scenarioName, InvocationSettings settings, int warmUpCount, int buildCount) {
BuildMutatorConfiguratorSpec spec = new BuildMutatorConfiguratorSpec(scenario, scenarioName, settings, warmUpCount, buildCount);
BuildMutatorConfiguratorSpec spec = new DefaultBuildMutatorConfiguratorSpec(scenario, scenarioName, settings, warmUpCount, buildCount);
return BUILD_MUTATOR_CONFIGURATORS.entrySet().stream()
.filter(entry -> scenario.hasPath(entry.getKey()))
.map(entry -> entry.getValue().configure(entry.getKey(), spec))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,26 @@

import javax.annotation.Nullable;
import java.io.File;
import java.io.PrintStream;
import java.util.List;
import java.util.Map;

public class MavenScenarioDefinition extends BuildToolCommandLineScenarioDefinition {
private final Map<String, String> systemProperties;

public MavenScenarioDefinition(
String scenarioName,
@Nullable String title,
List<String> targets,
Map<String, String> systemProperties,
List<BuildMutator> buildMutators,
int warmUpCount,
int buildCount,
File outputDir,
@Nullable File mavenHome
) {
super(scenarioName, title, targets, buildMutators, warmUpCount, buildCount, outputDir, mavenHome);
this.systemProperties = systemProperties;
}

@Override
Expand Down Expand Up @@ -56,4 +62,19 @@ protected String getExecutableName() {
protected String getToolHomeEnvName() {
return "MAVEN_HOME";
}

public Map<String, String> getSystemProperties() {
return systemProperties;
}

@Override
protected void printDetail(PrintStream out) {
super.printDetail(out);
if (!getSystemProperties().isEmpty()) {
out.println(" System properties:");
for (Map.Entry<String, String> entry : getSystemProperties().entrySet()) {
out.println(" " + entry.getKey() + "=" + entry.getValue());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package org.gradle.profiler.maven;

import org.gradle.profiler.BuildToolCommandLineInvoker;
import org.gradle.profiler.GradleBuildConfiguration;
import org.gradle.profiler.InvocationSettings;
import org.gradle.profiler.Logging;
import org.gradle.profiler.result.BuildInvocationResult;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

public class MavenScenarioInvoker extends BuildToolCommandLineInvoker<MavenScenarioDefinition, BuildInvocationResult> {
Expand All @@ -14,6 +17,8 @@ public void run(MavenScenarioDefinition scenario, InvocationSettings settings, C
List<String> commandLine = new ArrayList<>();
commandLine.add(scenario.getExecutablePath());
commandLine.addAll(scenario.getTargets());
scenario.getSystemProperties().forEach((key, value) ->
commandLine.add(String.format("-D%s=%s", key, value)));

doRun(scenario, settings, resultConsumer, commandLine);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package org.gradle.profiler.mutations;

import org.gradle.profiler.BuildMutator;
import org.gradle.profiler.InvocationSettings;

public abstract class AbstractBuildMutatorWithoutOptionsConfigurator implements BuildMutatorConfigurator {

abstract BuildMutator createBuildMutator(InvocationSettings settings);
abstract BuildMutator createBuildMutator(BuildMutatorConfiguratorSpec spec);

@Override
public BuildMutator configure(String key, BuildMutatorConfiguratorSpec spec) {
boolean enabled = spec.getScenario().getBoolean(key);
return enabled ? createBuildMutator(spec.getInvocationSettings()) : BuildMutator.NOOP;
return enabled ? createBuildMutator(spec) : BuildMutator.NOOP;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package org.gradle.profiler.mutations;

import com.typesafe.config.Config;
import org.apache.commons.io.FileUtils;
import org.gradle.profiler.BuildContext;
import org.gradle.profiler.BuildInvoker;
import org.gradle.profiler.BuildMutator;
import org.gradle.profiler.ConfigUtil;
import org.gradle.profiler.InvocationSettings;
import org.gradle.profiler.ScenarioContext;

import java.io.File;
Expand Down Expand Up @@ -70,10 +68,10 @@ public BuildMutator configure(String key, BuildMutatorConfiguratorSpec spec) {
if (schedule == null) {
throw new IllegalArgumentException("Schedule for cleanup is not specified");
}
return newInstance(spec.getScenario(), spec.getScenarioName(), spec.getInvocationSettings(), key, schedule);
return newInstance(spec, key, schedule);
}

protected abstract BuildMutator newInstance(Config scenario, String scenarioName, InvocationSettings settings, String key, CleanupSchedule schedule);
protected abstract BuildMutator newInstance(BuildMutatorConfiguratorSpec spec, String key, CleanupSchedule schedule);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.gradle.profiler.mutations;

import org.gradle.profiler.BuildMutator;

import java.io.File;

public class AbstractFileSystemMutator implements BuildMutator {
protected static File resolveProjectFile(File projectDir, String path) {
File file = new File(path);
if (file.isAbsolute()) {
return file;
}
return new File(projectDir, path);
}

@Override
public String toString() {
return getClass().getSimpleName();
}
}
Loading

0 comments on commit fcc1ecc

Please sign in to comment.