├── .github └── workflows │ ├── ci.yml │ ├── memory-releases.yml │ └── memorycheck.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE.txt ├── Makefile ├── README.md ├── bench-tools-maven ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── quickperf │ │ └── maven │ │ └── bench │ │ ├── AllocationCsvExporter.java │ │ ├── AllocationTimePair.java │ │ ├── ExecutionContextTextExporter.java │ │ ├── commands │ │ ├── InstallMavenVersionIfNotExists.java │ │ └── MavenBuildFromGitSourceInstall.java │ │ ├── config │ │ ├── BenchConfiguration.java │ │ ├── BenchConfigurationFileBasedResolver.java │ │ └── DefaultBenchConfigurationResolver.java │ │ └── projects │ │ ├── Maven3Version.java │ │ └── TestingProject.java │ └── test │ ├── java │ └── org │ │ └── quickperf │ │ └── maven │ │ └── bench │ │ └── config │ │ ├── BenchConfigurationFileBasedResolverTestCase.java │ │ └── DefaultBenchConfigurationResolverTest.java │ └── resources │ ├── log4j.properties │ ├── maven-bench.properties │ └── org │ └── quickperf │ └── maven │ └── bench │ └── config │ └── test.properties ├── bench-tools ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── quickperf │ │ └── maven │ │ └── bench │ │ ├── Command.java │ │ ├── commands │ │ ├── GitClone.java │ │ ├── HttpGet.java │ │ ├── InstallWithHttpGet.java │ │ └── ZipExtractor.java │ │ └── config │ │ └── BenchConfigurationResolver.java │ └── test │ ├── java │ └── org.quickperf.maven.bench.commands │ │ ├── GitCloneTest.java │ │ ├── HttpGetTest.java │ │ ├── PropertiesUtils.java │ │ └── PropertiesUtilsTest.java │ └── resources │ ├── bench-tools.properties │ ├── data │ └── index.txt │ ├── download │ └── .gitkeep │ └── log4j.properties ├── maven-perf ├── NEXT_STEP.md ├── measures │ ├── Maven3.2.5-JMC.5.5JPG.jpg │ ├── execution-context-2019-09-01-18-48-41.txt │ ├── maven-memory-allocation-2019-09-01-18-48-41.csv │ └── mvn-validate-on-camel.png ├── pom.xml └── src │ └── test │ ├── java │ └── org │ │ └── quickperf │ │ └── maven │ │ └── bench │ │ ├── MvnValidateAllocationByMaven3VersionTest.java │ │ ├── MvnValidateMaxAllocation.java │ │ └── MvnValidateProfilingTest.java │ └── resources │ ├── log4j.properties │ └── maven-bench.properties └── pom.xml /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | env: 13 | TESTING_PROJECT_VERSION: camel-3.0.0 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Set up JDK 11 17 | uses: actions/setup-java@v1 18 | with: 19 | java-version: 11 20 | - name: Cache Maven dependencies 21 | uses: actions/cache@v2 22 | with: 23 | path: ~/.m2 24 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 25 | restore-keys: ${{ runner.os }}-m2 26 | - name: Build 27 | run: make ci 28 | -------------------------------------------------------------------------------- /.github/workflows/memory-releases.yml: -------------------------------------------------------------------------------- 1 | name: Releases Memory Bench 2 | 3 | on: workflow_dispatch 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | env: 9 | TESTING_PROJECT_VERSION: camel-3.0.0 10 | MAVEN_VERSION_FROM: 3.6.0 11 | MAVEN_VERSION_TO: master 12 | WARM_UP_NUMBER: 1 13 | MEASURES_NUMBER_BY_MAVEN_VERSION: 10 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Set up JDK 11 17 | uses: actions/setup-java@v1 18 | with: 19 | java-version: 11 20 | - name: Cache Maven dependencies 21 | uses: actions/cache@v2 22 | with: 23 | path: ~/.m2 24 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 25 | restore-keys: ${{ runner.os }}-m2 26 | - name: Bench allocation of Maven Releases 27 | run: make runMeasures 28 | -------------------------------------------------------------------------------- /.github/workflows/memorycheck.yml: -------------------------------------------------------------------------------- 1 | name: Daily Memory Check 2 | 3 | on: 4 | schedule: 5 | - cron: '0 6 * * *' 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | env: 11 | TESTING_PROJECT_VERSION: camel-3.0.0 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Set up JDK 11 15 | uses: actions/setup-java@v1 16 | with: 17 | java-version: 11 18 | - name: Cache Maven dependencies 19 | uses: actions/cache@v2 20 | with: 21 | path: ~/.m2 22 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 23 | restore-keys: ${{ runner.os }}-m2 24 | - name: Run validation max allocation 25 | run: make runValidateMaxAllocation 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Maven 2 | target 3 | 4 | # IntelliJ 5 | .idea 6 | *.iml 7 | out 8 | 9 | # Eclipse 10 | .classpath 11 | .project 12 | .settings 13 | 14 | # NetBeans 15 | .nbattrs 16 | 17 | # local conf 18 | local.*.properties -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at jean.bisutti@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash # Use bash syntax 2 | 3 | .PHONY: help build runMeasures runValidateMaxAllocation 4 | 5 | help: 6 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 7 | 8 | clean: ## Cleanup project files (basically run `mvn clean`) 9 | mvn clean 10 | 11 | build: ## Build project with running all tests (basically run `mvn package`) 12 | mvn package -B 13 | 14 | ci: 15 | mvn package -B -P ci 16 | 17 | install-only-bench-tools: ## Install locally all tools lib necessary to run maven perf tests. 18 | mvn install -DskipTests -pl bench-tools-maven -am -B 19 | 20 | runValidateMaxAllocation: install-only-bench-tools ## Running only memory allocation needed for last commit from Maven GIT Repository on master branch 21 | mvn test -pl maven-perf -Dtest=org.quickperf.maven.bench.MvnValidateMaxAllocation -B 22 | 23 | runMeasures: install-only-bench-tools ## Running only measures 24 | mvn test -pl maven-perf -Dtest=org.quickperf.maven.bench.MvnValidateAllocationByMaven3VersionTest -B 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 |

Measure and investigate heap memory allocation of Apache Maven

5 | Heap allocation of Maven head 6 |

7 |
8 |
9 | 10 |

11 | General setup • 12 | Benchmark heap allocation of several Maven releases 13 |

14 |

15 | Investigate where heap allocation comes from • 16 | Perspectives • 17 | Contributors • 18 | License 19 |

20 | 21 | This project is a test bench based on [QuickPerf](https://github.com/quick-perf/quickperf) to benchmark and understand heap memory allocation caused by `mvn validate` on a project source code. 22 | 23 | Feel free to use this project re-execute measures, play with it on measuring any build, tweak its code and contribute back to it! 24 | 25 | # Overview 26 | 27 | This project contains two types of measures against Maven build execution, each provided as a JUnit unit test (in ```src/test/java```): 28 | - `MvnValidateProfilingTest` can be used to investigate the origin of memory allocation (using QuickPerf [@ProfileJvm](https://github.com/quick-perf/doc/wiki/JVM-annotations#Profile-or-check-your-JVM)) during one build with a given Maven version, 29 | - `MvnValidateAllocationByMaven3VersionTest` can be used to measure the heap allocation (using QuickPerf [@MeasureHeapAllocation](https://github.com/quick-perf/doc/wiki/JVM-annotations#Verify-heap-allocation)) for every Maven release in a version range. 30 | 31 | # General setup 32 | 33 | This general setup part describes configuration common to both tests, done in `src/test/resourrces/maven-bench.properties` file: 34 | - the `testing.project.path` represents the path of the project on which `mvn validate` will be applied, 35 | - the `maven.binaries.path` property corresponds to the path where the needed Maven distributions will be automatically downloaded by the tests. 36 | The other properties are only used by `MvnValidateAllocationByMaven3VersionTest`. 37 | 38 | The measures shown here are done against the Apache Camel project because it contains more than 800 Maven modules: such a huge build is perfect to get significant measures. But you can choose your own target. 39 | 40 | _Note: currently, every day, a job @TravisCI run `org.quickperf.maven.bench.MvnValidateMaxAllocation` in order to watch 41 | over Apache Maven project and observe if new features on Apache Maven needs more memory then yesterday._ 42 | 43 | 44 | For reproducibility of our measures, a precisely defined commit of this project was chosen: 45 | ``` 46 | git clone -n https://github.com/apache/camel.git 47 | git checkout c409ab7aabb971065fc8384a861904d2a2819be5 48 | ``` 49 | 50 | If you want to apply measures on build done with Maven HEAD, that cannot be downloaded from public releases, you can execute the following commands where {maven-distrib-location} has to be replaced with the url given by the `maven.binaries.path` property of `maven-bench.properties` file: 51 | ``` 52 | git clone https://github.com/apache/maven.git 53 | cd maven 54 | mvn -DdistributionTargetDir="{maven-distrib-location}/apache-maven-head" package 55 | ``` 56 | 57 | Heap size is fixed with the help of [@HeapSize](https://github.com/quick-perf/doc/wiki/JVM-annotations#heapsize). 58 | 59 | # Contributing 60 | 61 | ## Building the project 62 | 63 | ```bash 64 | git clone https://github.com/pcavezzan/maven-test-bench.git 65 | make build 66 | ``` 67 | 68 | The above commandline will run behind the scene several actions: 69 | * run ```mvn package -B``` 70 | 71 | During the test phase, we are going to : 72 | * clone Apache Camel project (commit ```c409ab7aabb971065fc8384a861904d2a2819be5```) into ```test-classes/camel``` 73 | * install different version of maven into ```test-classes/maven``` 74 | * for Releases version, we are going to : 75 | * download releases from ```https://archive.apache.org/dist/maven/maven-3//binaries/apache-maven--bin.zip``` 76 | * unzip into ```test-classes/maven/apache-maven-``` 77 | * for HEAD version, we are going to : 78 | * clone Apache Maven mainstream from ```https://gitbox.apache.org/repos/asf/maven-sources.git``` 79 | * build from source Apache Maven latest development version, 80 | * rename the built maven to ```test-classes/maven/apache-maven-master```, 81 | 82 | __*Note:*__ *the build above could be stuck depending on your machine settings. If it is the case, I would suggest you to create a custom build (see below).* 83 | 84 | ## Custom Build 85 | 86 | If you prefer to override some settings without editing the default configuration (```maven-bench.propertiers```), 87 | you have several options: 88 | 89 | * environment variable 90 | * you can create a local configuration files ```local.maven-bench.properties``` without any risk to version it because 91 | this file is ignored by GIT. In this file, just override the settings you want. 92 | 93 | ### Overriding by setting environment variable 94 | 95 | ```bash 96 | export MAVEN_VERSION_FROM=3.6.1 97 | export MAVEN_VERSION_TO=3.6.2 98 | make build 99 | ``` 100 | 101 | ### Overriding by creating local.maven-bench.properties 102 | 103 | ```bash 104 | cat << EOF > src/main/resources/local.maven-bench.properties 105 | maven.version.from=3.6.1 106 | maven.version.to=3.6.2 107 | EOF 108 | make build 109 | ``` 110 | 111 | ### Running only some tests 112 | 113 | This project contains a Makefile to easily orchestrate how to build or run specific test. 114 | To get more info, do not hesitate to run basic ```make``` or ```make help```: 115 | 116 | ```bash 117 | $ make 118 | build Build project with running all tests (basically run `mvn package`) 119 | clean Cleanup project files (basically run `mvn clean`) 120 | runMeasures Running only measures 121 | runValidateMaxAllocation Running only memory allocation needed for last commit from Maven GIT Repository on master branch 122 | ``` 123 | 124 | #### Memory allocation on head maven version 125 | 126 | ```bash 127 | $ make runValidateMaxAllocation 128 | ``` 129 | 130 | 131 | #### Measures maven version 132 | 133 | ```bash 134 | $ make runMeasureOnHead 135 | ``` 136 | 137 | 138 | ## Developing 139 | 140 | If you want to help us and make some code, you can easily get the project and open it up with your favorite IDE. 141 | 142 | 143 | ### NOTE: if you want to debug head version of Maven 144 | 145 | First configure the project to use only head version of maven. For example, by creating a ```local.maven-bench.properties``` 146 | in ```src/main/resources``` directory: 147 | 148 | ```bash 149 | cat << EOF > src/main/resources/local.maven-bench.properties 150 | maven.version.from=head 151 | maven.version.to=head 152 | EOF 153 | make build 154 | ``` 155 | 156 | Then just open your favorite IDE or running your test. 157 | 158 | 159 | # Benchmark heap allocation of several Maven releases 160 | 161 | `org.quickperf.maven.bench.MvnValidateAllocationByMaven3VersionTest` test allows to benchmark the heap allocation level on several Maven 3 distributions. 162 | 163 | Heap allocation level is measured with the help of [@MeasureHeapAllocation](https://github.com/quick-perf/doc/wiki/JVM-annotations#Verify-heap-allocation) QuickPerf annotation. This annotation measures the heap allocation level of the thread running the method annotated with @Test. 164 | Feel free to contribute to QuickPerf by adding a feature allowing to measure the allocation level aggregated across all the threads! With `mvn validate`, we have checked that Maven code is not multithreaded during this validate phase by profiling the JVM with the help of [@ProfileJvm](https://github.com/quick-perf/doc/wiki/JVM-annotations#ProfileJvm). 165 | 166 | Please read [General setup](#General-setup) to get some of the setup requirements. 167 | 168 | You also have to give a value for the following properties contained in the [maven-bench.properties](src/test/resources/maven-bench.properties) file: 169 | * `maven.version.from` 170 | * `maven.version.to` 171 | * `warmup.number` 172 | * `measures.number-by-maven-version` 173 | 174 | The meaning of these properties is given in the [maven-bench.properties](src/test/resources/maven-bench.properties) file. 175 | 176 | Measures can be launched with this command line: ```mvn -Dtest=org.quickperf.maven.bench.MvnValidateAllocationByMaven3VersionTest test```. 177 | Before doing it, you can close your IDE, web browser or other applications to free memory. 178 | 179 | The benchmark results are exported into a `maven-memory-allocation-{date-time}.csv` file. The execution context (processor, OS, ...) is reported in an `execution-context-{date-time}.txt` file. 180 | 181 | For several Maven versions, the following graph gives the average of ten heap allocations caused by the application of `mvn validate` on Apache Camel: 182 |

183 | 184 |

185 | 186 | For this graph, you can consult: 187 | * [the measures](maven-perf/measures/maven-memory-allocation-2019-09-01-18-48-41.csv) 188 | * [the execution context](maven-perf/measures/execution-context-2019-09-01-18-48-41.txt) 189 | 190 | Measures took around one hour and a quarter. 191 | 192 | From Maven versions 3.2.5 to 3.6.2, heap allocation level is the highest with Maven 3.2.5 and the smallest with Maven 3.6.2. *The heap allocation decreases from ~7 Gb with Maven 3.6.1 to ~3 Gb with Maven 3.6.2*. 193 | 194 | Control and reduce heap allocation is an important matter for Maven project. Indeed, a part of the heap allocation is going to be garbage collected and the garbage collection activity is succeptible to slow down your build. In addition, less heap allocation means that you may execute Maven with a smaller heap size. 195 | 196 | But where the allocation comes from? In the following part we will see how to spot the Java methods allocating a lot. 197 | 198 | # Investigate where heap allocation comes from 199 | 200 | You can use `org.quickperf.maven.bench.MvnValidateProfilingTest` to understand the origin of heap allocation. 201 | Some of the set up requirements can be found in [General setup](#General-setup) part. 202 | 203 | The Maven version under test can be set with the `MAVEN_3_VERSION` constant: 204 | ``` java 205 | public static org.quickperf.maven.bench.projects.Maven3Version MAVEN_3_VERSION = org.quickperf.maven.bench.projects.Maven3Version.V_3_6_2; 206 | ``` 207 | 208 | A test method is annotated with [@ProfileJvm](https://github.com/quick-perf/doc/wiki/JVM-annotations#Profile-or-check-your-JVM) to profile the test method with Java Flight Recorder (JFR). 209 | 210 | The JFR file location is going to be displayed in the console: 211 | ``` 212 | [QUICK PERF] JVM was profiled with Java File Recorder (JFR). 213 | The recording file can be found here: C:\Users\JEANBI~1\AppData\Local\Temp\QuickPerf-46868616\jvm-profiling.jfr 214 | You can open it with Java Mission Control (JMC). 215 | ``` 216 | 217 | You can open it with Java Mission Control (JMC) to discover the methods contributing the most to heap allocation. 218 | 219 | Below a JFR file for Maven 3.2.5 and opened with JMC 5.5: 220 |

221 | 222 |

223 | 224 | 225 | By the way, you can also benefit from an automatic performance analysis with [@ExpectNoJvmIssue](https://github.com/quick-perf/doc/wiki/JVM-annotations#ExpectNoJvmIssue). 226 | For example, the following warning is reported with Maven 3.2.5: 227 | ``` 228 | Rule: Thrown Exceptions 229 | Severity: WARNING 230 | Score: 97 231 | Message: The program generated 20 482 exceptions per second during 26,722 s starting at 232 | 03/09/19 17:08:31. 233 | ``` 234 | 235 | # Perspectives 236 | We have developed a test bench that is able to compare the heap allocation level between several Maven versions. We also have given a method to understand the origin of heap allocation. 237 | 238 | Feel free to play with this bench and [QuickPerf](https://github.com/quick-perf/doc/wiki/QuickPerf), to perform measures (heap allocation, execution time, ...) with different plugins/goals, use different JDK or garbage collectors, ..., suggest new ideas, create new features or share your measures with PR! 239 | Some issues are also available [here](https://github.com/quick-perf/maven-test-bench/issues)! 240 | 241 | You also have [QuickPerf issues](https://github.com/quick-perf/quickperf/issues) to build new performance tools! 242 | 243 | # Contributors 244 | Many thanks to all our contributors! 245 | 246 | 247 | 248 | 260 | 270 | 279 | 288 | 289 |
249 | 250 | Jean Bisutti 251 |
252 | Jean Bisutti 253 |
254 |
255 | 🤔 256 | 💻 257 | 📖 258 | 👀 259 |
261 | 262 | Hervé Boutemy 263 |
264 | Hervé Boutemy 265 |
266 |
267 | 🤔 268 | 📖 269 |
271 | 272 | Alberto Martinelli 273 |
274 | Alberto Martinelli 275 |
276 |
277 | 💻 278 |
280 | 281 | Patrice Cavezzan 282 |
283 | Patrice Cavezzan 284 |
285 |
286 | 💻 287 |
290 | emoji key 291 | 292 | # License 293 | [Apache License 2.0](/LICENSE.txt) 294 | -------------------------------------------------------------------------------- /bench-tools-maven/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 16 | 17 | maven-test-bench 18 | org.quickperf 19 | 1.0-SNAPSHOT 20 | 21 | 4.0.0 22 | 23 | bench-tools-maven 24 | 25 | 26 | 27 | org.quickperf 28 | bench-tools 29 | 1.0-SNAPSHOT 30 | 31 | 32 | org.apache.commons 33 | commons-csv 34 | 1.7 35 | 36 | 37 | org.apache.maven 38 | maven-model-builder 39 | 3.6.3 40 | 41 | 42 | com.github.oshi 43 | oshi-core 44 | 4.0.0 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /bench-tools-maven/src/main/java/org/quickperf/maven/bench/AllocationCsvExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench; 13 | 14 | import org.apache.commons.csv.CSVFormat; 15 | import org.apache.commons.csv.CSVPrinter; 16 | import org.quickperf.maven.bench.projects.Maven3Version; 17 | 18 | import java.io.File; 19 | import java.io.FileWriter; 20 | import java.io.IOException; 21 | import java.util.ArrayList; 22 | import java.util.Arrays; 23 | import java.util.List; 24 | import java.util.LongSummaryStatistics; 25 | import java.util.stream.Collectors; 26 | 27 | public class AllocationCsvExporter { 28 | 29 | public static final AllocationCsvExporter INSTANCE = new AllocationCsvExporter(); 30 | 31 | private AllocationCsvExporter() {} 32 | 33 | public void writeAllocationsToCsv(Maven3Version maven3Version, AllocationTimePair[] allocations, String resultFilePath) throws IOException { 34 | 35 | int numberOfAllocations = allocations.length; 36 | CSVFormat csvFormat = buildCsvFormat(resultFilePath, numberOfAllocations); 37 | 38 | FileWriter fileWriter = new FileWriter(resultFilePath, true); 39 | try (CSVPrinter csvPrinter = new CSVPrinter(fileWriter, csvFormat)) { 40 | List csvRecord = buildCsvRecord(maven3Version, allocations); 41 | csvPrinter.printRecord(csvRecord); 42 | } 43 | 44 | } 45 | 46 | private CSVFormat buildCsvFormat(String resultFilePath, int numberOfAllocations) { 47 | if (new File(resultFilePath).exists()) { 48 | return CSVFormat.DEFAULT; 49 | } 50 | String[] csvHeaders = buildCsvHeaders(numberOfAllocations); 51 | return CSVFormat.DEFAULT.withHeader(csvHeaders); 52 | } 53 | 54 | private String[] buildCsvHeaders(int numberOfAllocations) { 55 | String[] csvHeaders = new String[(3 * numberOfAllocations) +8]; 56 | csvHeaders[0] = "Maven version"; 57 | csvHeaders[1] = "Average (bytes)"; 58 | csvHeaders[2] = "Average (Gb)"; 59 | csvHeaders[3] = "Min (bytes)"; 60 | csvHeaders[4] = "Max (bytes)"; 61 | csvHeaders[5] = "Average length(seconds)"; 62 | csvHeaders[6] = "Min length (seconds)"; 63 | csvHeaders[7] = "Max length (seconds)"; 64 | 65 | for (int i = 1; i < numberOfAllocations + 1; i++) { 66 | csvHeaders[i + 7] = "Allocation" + " " + i + " "+ "(bytes)"; 67 | } 68 | 69 | for (int i = 1; i < numberOfAllocations + 1; i++) { 70 | csvHeaders[i + 7+ numberOfAllocations] = "Length" + " " + i + " "+ "(seconds)"; 71 | } 72 | 73 | for (int i = 1; i < numberOfAllocations + 1; i++) { 74 | csvHeaders[i + 7 + numberOfAllocations*2] = "Allocation" + " " + i + " "+ "(Gb)"; 75 | } 76 | return csvHeaders; 77 | } 78 | 79 | private List buildCsvRecord(Maven3Version maven3Version, AllocationTimePair[] input) { 80 | 81 | List csvRecord = new ArrayList<>((2 * input.length) + 5); 82 | 83 | csvRecord.add(maven3Version); 84 | 85 | LongSummaryStatistics allocationStatistics = Arrays.stream(input).collect(Collectors.summarizingLong(AllocationTimePair::getAllocationInBytes)); 86 | double averageAllocationInBytes = allocationStatistics.getAverage(); 87 | csvRecord.add(averageAllocationInBytes); 88 | csvRecord.add(averageAllocationInBytes / Math.pow(1024, 3)); 89 | csvRecord.add(allocationStatistics.getMin()); 90 | csvRecord.add(allocationStatistics.getMax()); 91 | 92 | LongSummaryStatistics lengthStatistics = Arrays.stream(input).collect(Collectors.summarizingLong(AllocationTimePair::getLengthInSeconds)); 93 | double averageAllocationInSeconds = lengthStatistics.getAverage(); 94 | csvRecord.add(averageAllocationInSeconds); 95 | csvRecord.add(lengthStatistics.getMin()); 96 | csvRecord.add(lengthStatistics.getMax()); 97 | 98 | for (int i = 0; i < input.length; i++) { 99 | csvRecord.add(input[i].getAllocationInBytes()); 100 | } 101 | 102 | for (int i = 0; i < input.length; i++) { 103 | csvRecord.add(input[i].getLengthInSeconds()); 104 | } 105 | 106 | for (int i = 0; i < input.length; i++) { 107 | csvRecord.add(input[i].getAllocationInBytes() / Math.pow(1024, 3)); 108 | } 109 | 110 | 111 | 112 | return csvRecord; 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /bench-tools-maven/src/main/java/org/quickperf/maven/bench/AllocationTimePair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench; 13 | 14 | public class AllocationTimePair { 15 | 16 | private final Long allocationInBytes; 17 | private final Long lengthInSeconds; 18 | 19 | public AllocationTimePair(Long allocationInBytes, Long lengthInSeconds) { 20 | this.allocationInBytes = allocationInBytes; 21 | this.lengthInSeconds = lengthInSeconds; 22 | } 23 | 24 | public Long getAllocationInBytes() { 25 | return allocationInBytes; 26 | } 27 | 28 | public Long getLengthInSeconds() { 29 | return lengthInSeconds; 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /bench-tools-maven/src/main/java/org/quickperf/maven/bench/ExecutionContextTextExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench; 13 | 14 | import org.quickperf.maven.bench.config.BenchConfiguration; 15 | import oshi.SystemInfo; 16 | import oshi.hardware.CentralProcessor; 17 | import oshi.hardware.HardwareAbstractionLayer; 18 | import oshi.software.os.OperatingSystem; 19 | 20 | import java.io.BufferedWriter; 21 | import java.io.File; 22 | import java.io.FileWriter; 23 | import java.io.IOException; 24 | 25 | class ExecutionContextTextExporter { 26 | 27 | private ExecutionContextTextExporter() {} 28 | 29 | static ExecutionContextTextExporter INSTANCE = new ExecutionContextTextExporter(); 30 | 31 | public void writeExecutionContextToTextFile(String dateTimeAsString) { 32 | 33 | String filePath = BenchConfiguration.INSTANCE.getExportPathOfMeasures() 34 | + File.separator 35 | + "execution-context-" +dateTimeAsString + ".txt"; 36 | 37 | try (FileWriter writer = new FileWriter(filePath); 38 | BufferedWriter bw = new BufferedWriter(writer)) { 39 | 40 | int numberOfWarms = BenchConfiguration.INSTANCE.getNumberOfWarms(); 41 | bw.write("Warm up: " + numberOfWarms); 42 | 43 | bw.newLine(); 44 | bw.newLine(); 45 | 46 | String javaVersion = System.getProperty("java.version"); 47 | bw.write("Java version: " + javaVersion); 48 | 49 | bw.newLine(); 50 | 51 | String javaVendor = System.getProperty("java.vendor"); 52 | bw.write("Java vendor: " + javaVendor); 53 | 54 | bw.newLine(); 55 | 56 | String javaVmName = System.getProperty("java.vm.name"); 57 | bw.write("Java VM name: " + javaVmName); 58 | 59 | bw.newLine(); 60 | bw.newLine(); 61 | 62 | SystemInfo systemInfo = new SystemInfo(); 63 | 64 | HardwareAbstractionLayer hardware = systemInfo.getHardware(); 65 | 66 | CentralProcessor processor = hardware.getProcessor(); 67 | bw.write("Processor: " + processor); 68 | 69 | bw.newLine(); 70 | 71 | int logicalProcessorCount = processor.getLogicalProcessorCount(); 72 | bw.write("Logical processor count: " + logicalProcessorCount); 73 | 74 | bw.newLine(); 75 | bw.newLine(); 76 | 77 | long totalMemoryInBytes = hardware.getMemory().getTotal(); 78 | 79 | long totalMemoryInGigaBytes = (long) (totalMemoryInBytes / Math.pow(1024, 3)); 80 | 81 | bw.write("Total memory (giga bytes): " + totalMemoryInGigaBytes); 82 | 83 | bw.newLine(); 84 | 85 | long availableMemoryInBytes = systemInfo.getHardware().getMemory().getAvailable(); 86 | 87 | double availableMemoryInGigaBytes = availableMemoryInBytes / Math.pow(1024, 3); 88 | bw.write("Available memory (giga bytes): " + availableMemoryInGigaBytes); 89 | 90 | bw.newLine(); 91 | bw.newLine(); 92 | 93 | OperatingSystem os = systemInfo.getOperatingSystem(); 94 | bw.write("OS: " + os); 95 | 96 | bw.flush(); 97 | 98 | } catch (IOException e) { 99 | throw new IllegalStateException("Can't create execution context file", e); 100 | } 101 | 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /bench-tools-maven/src/main/java/org/quickperf/maven/bench/commands/InstallMavenVersionIfNotExists.java: -------------------------------------------------------------------------------- 1 | package org.quickperf.maven.bench.commands; 2 | 3 | import org.quickperf.maven.bench.Command; 4 | import org.quickperf.maven.bench.projects.Maven3Version; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.File; 9 | /* 10 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 15 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 16 | * 17 | * Copyright 2019-2020 the original author or authors. 18 | */ 19 | 20 | public class InstallMavenVersionIfNotExists implements Command { 21 | 22 | private static final Logger LOGGER = LoggerFactory.getLogger(InstallMavenVersionIfNotExists.class); 23 | 24 | private final Maven3Version maven3Version; 25 | 26 | public InstallMavenVersionIfNotExists(Maven3Version maven3Version) { 27 | this.maven3Version = maven3Version; 28 | } 29 | 30 | @Override 31 | public String execute() { 32 | LOGGER.info("Installing Maven {} if it has not been already installed", maven3Version); 33 | Command install = null; 34 | switch (maven3Version.getInstallProcess()) { 35 | case HTTP: 36 | install = new InstallWithHttpGet(maven3Version.getUrlAsString(), maven3Version.getMavenPath()); 37 | break; 38 | case GIT: 39 | install = new MavenBuildFromGitSourceInstall(maven3Version.getUrlAsString(), maven3Version.getMavenPath(), maven3Version.getNumVersion()); 40 | break; 41 | } 42 | 43 | String mavenPath = maven3Version.getMavenPath(); 44 | if (alreadyDownloaded(mavenPath)) { 45 | LOGGER.debug("Maven version has been already downloaded"); 46 | } else { 47 | LOGGER.debug("Maven version is absent, installing maven {}", maven3Version); 48 | mavenPath = install.execute(); 49 | } 50 | 51 | return mavenPath; 52 | } 53 | 54 | private boolean alreadyDownloaded(final String mavenFilePath) { 55 | File mavenFile = new File(mavenFilePath); 56 | return mavenFile.exists(); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /bench-tools-maven/src/main/java/org/quickperf/maven/bench/commands/MavenBuildFromGitSourceInstall.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench.commands; 13 | 14 | import org.apache.maven.model.Model; 15 | import org.apache.maven.model.io.xpp3.MavenXpp3Reader; 16 | import org.codehaus.plexus.util.xml.pull.XmlPullParserException; 17 | import org.quickperf.maven.bench.Command; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.io.*; 22 | import java.nio.file.Files; 23 | import java.nio.file.Path; 24 | 25 | /** 26 | * Command to run for building Maven from Source code. 27 | * 28 | *

29 | * This command execute the following step: 30 | *

    31 | *
  • git clone sourceUrl@head
  • 32 | *
  • mvn clean package -DskipTest
  • 33 | *
  • unzip APACHE_MAVEN_DIR/target/apache-maven-version-bin.zip targetPath
  • 34 | *
35 | *

36 | */ 37 | public class MavenBuildFromGitSourceInstall implements Command { 38 | private static final Logger LOGGER = LoggerFactory.getLogger(MavenBuildFromGitSourceInstall.class); 39 | 40 | private final String sourceUrl; 41 | private final String targetPath; 42 | private final String head; 43 | 44 | public MavenBuildFromGitSourceInstall(String sourceUrl, String targetPath, String head) { 45 | this.sourceUrl = sourceUrl; 46 | this.targetPath = targetPath; 47 | this.head = head; 48 | } 49 | 50 | @Override 51 | public String execute() { 52 | LOGGER.info("Install Apache Maven project from GIT source code {} into {}", sourceUrl, targetPath); 53 | final String targetDirectoryPath; 54 | try { 55 | final Path tempDirectory = Files.createTempDirectory("maven-test-bench"); 56 | targetDirectoryPath = new GitClone(sourceUrl, tempDirectory.toString(), head).execute(); 57 | } catch (IOException e) { 58 | throw new IllegalStateException("Could not clone project " + sourceUrl + " into temporary directory", e); 59 | } 60 | 61 | try { 62 | LOGGER.debug("Running 'mvn clean package -DskipTest' for building Apache Maven project"); 63 | final Process process = Runtime.getRuntime().exec("mvn clean package -DskipTests -f " + targetDirectoryPath + "/pom.xml"); 64 | BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); 65 | String line; 66 | while ((line = input.readLine()) != null) { 67 | LOGGER.trace(line); 68 | } 69 | input.close(); 70 | 71 | final int exitValue = process.waitFor(); 72 | if (exitValue != 0) { 73 | throw new IllegalStateException("mvn clean package -DskipTests has failed for maven project directory: " + targetDirectoryPath + ". Exit code: " + exitValue); 74 | } 75 | 76 | } catch (IOException | InterruptedException e) { 77 | throw new IllegalStateException("Could not build with Maven from project directory " + targetDirectoryPath, e); 78 | } 79 | 80 | final String pomXmlFile = targetDirectoryPath + "/pom.xml"; 81 | final String apacheMavenBinDir; 82 | LOGGER.trace("Getting project version from pom project."); 83 | try (final Reader reader = new FileReader(pomXmlFile)){ 84 | final MavenXpp3Reader xpp3Reader = new MavenXpp3Reader(); 85 | final Model model = xpp3Reader.read(reader); 86 | final String apacheMavenVersion = model.getVersion(); 87 | apacheMavenBinDir = targetDirectoryPath + "/apache-maven/target/apache-maven-" + apacheMavenVersion + "-bin.zip"; 88 | } catch (final IOException | XmlPullParserException e) { 89 | throw new IllegalStateException("Cannot read pom version.", e); 90 | } 91 | return new ZipExtractor(apacheMavenBinDir, targetPath).execute(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /bench-tools-maven/src/main/java/org/quickperf/maven/bench/config/BenchConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench.config; 13 | 14 | import org.quickperf.maven.bench.projects.Maven3Version; 15 | import org.quickperf.maven.bench.projects.TestingProject; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Collections; 19 | import java.util.List; 20 | 21 | /** 22 | * Benchmark configuration needed to run all bench tests on Apache Maven. 23 | * 24 | *

25 | * The configuration are loaded using differents {@link BenchConfigurationResolver} configured uppon 26 | * {@link DefaultBenchConfigurationResolver}. 27 | *

28 | */ 29 | public class BenchConfiguration { 30 | 31 | public static final BenchConfiguration INSTANCE = new BenchConfiguration(); 32 | 33 | private BenchConfiguration() { 34 | initialize(); 35 | } 36 | 37 | private int numberOfMeasuresByMavenVersion; 38 | 39 | private String exportPathOfMeasures; 40 | 41 | private int numberOfWarns; 42 | 43 | private String mavenBinariesPath; 44 | 45 | private TestingProject testingProject; 46 | 47 | private List maven3VersionsToMeasure; 48 | 49 | private String mavenGitVersion; 50 | 51 | private void initialize() { 52 | BenchConfigurationResolver properties = new DefaultBenchConfigurationResolver(); 53 | String numberOfMeasuresByMavenVersionAsString = properties.resolve("measures.number-by-maven-version"); 54 | this.numberOfMeasuresByMavenVersion = Integer.parseInt(numberOfMeasuresByMavenVersionAsString); 55 | String numberOfWarnsAsString = properties.resolve("warmup.number"); 56 | this.numberOfWarns = Integer.parseInt(numberOfWarnsAsString); 57 | this.mavenBinariesPath = properties.resolve("maven.binaries.path"); 58 | this.exportPathOfMeasures = properties.resolve("measures.export.path"); 59 | this.maven3VersionsToMeasure = findMaven3VersionsToMeasure(properties); 60 | this.mavenGitVersion = properties.resolve("maven.git.version"); 61 | this.testingProject = new TestingProject( 62 | properties.resolve("testing.project.name"), 63 | properties.resolve("testing.project.repository"), 64 | properties.resolve("testing.project.version"), 65 | properties.resolve("testing.project.path")); 66 | 67 | } 68 | 69 | private List findMaven3VersionsToMeasure(BenchConfigurationResolver properties) { 70 | 71 | List maven3VersionsToMeasure = new ArrayList<>(); 72 | 73 | boolean mavenVersionStartFound = false; 74 | boolean mavenVersionToAlreadyFound = false; 75 | 76 | for (Maven3Version maven3Version : Maven3Version.values()) { 77 | 78 | if(isMaven3VersionFrom(maven3Version, properties)) { 79 | mavenVersionStartFound = true; 80 | } 81 | 82 | if(mavenVersionStartFound && !mavenVersionToAlreadyFound) { 83 | maven3VersionsToMeasure.add(maven3Version); 84 | } 85 | 86 | if(isMaven3VersionTo(maven3Version, properties)) { 87 | mavenVersionToAlreadyFound = true; 88 | } 89 | 90 | } 91 | 92 | return Collections.unmodifiableList(maven3VersionsToMeasure); 93 | 94 | } 95 | 96 | private boolean isMaven3VersionFrom(Maven3Version maven3Version, BenchConfigurationResolver properties) { 97 | return properties.resolve("maven.version.from").equals(maven3Version.getNumVersion()); 98 | } 99 | 100 | private boolean isMaven3VersionTo(Maven3Version maven3Version, BenchConfigurationResolver properties) { 101 | return properties.resolve("maven.version.to").equals(maven3Version.getNumVersion()); 102 | } 103 | 104 | public int getNumberOfMeasuresByMavenVersion() { 105 | return numberOfMeasuresByMavenVersion; 106 | } 107 | 108 | public String getExportPathOfMeasures() { 109 | return exportPathOfMeasures; 110 | } 111 | 112 | public int getNumberOfWarms() { 113 | return numberOfWarns; 114 | } 115 | 116 | public String getMavenBinariesPath() { 117 | return mavenBinariesPath; 118 | } 119 | 120 | public TestingProject getTestingProject() { 121 | return testingProject; 122 | } 123 | 124 | public List getMaven3VersionsToMeasure() { 125 | return maven3VersionsToMeasure; 126 | } 127 | 128 | public String getMavenGitVersion() { 129 | return mavenGitVersion; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /bench-tools-maven/src/main/java/org/quickperf/maven/bench/config/BenchConfigurationFileBasedResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench.config; 13 | 14 | import java.io.FileInputStream; 15 | import java.io.IOException; 16 | import java.net.URL; 17 | import java.net.URLDecoder; 18 | import java.nio.charset.StandardCharsets; 19 | import java.util.Properties; 20 | 21 | /** 22 | * Strategy to resolve all configuration from a properties file. 23 | */ 24 | class BenchConfigurationFileBasedResolver implements BenchConfigurationResolver { 25 | private Properties props; 26 | 27 | private BenchConfigurationFileBasedResolver(String fileName) throws IOException { 28 | this.props = this.loadProperties(fileName); 29 | } 30 | 31 | static BenchConfigurationFileBasedResolver createBenchPropertiesFileBasedResolver(String fileName) 32 | throws IOException { 33 | return new BenchConfigurationFileBasedResolver(fileName); 34 | } 35 | 36 | private Properties loadProperties(String fileName) throws IOException { 37 | Properties properties = new Properties(); 38 | URL resource = getClass().getClassLoader().getResource(fileName); 39 | if (resource == null) { 40 | throw new IOException("file (" + fileName + ") not found."); 41 | } 42 | 43 | String propertiesFilePath = URLDecoder.decode(resource.getPath(), StandardCharsets.UTF_8.toString()); 44 | try (final FileInputStream fileInputStream = new FileInputStream(propertiesFilePath)) { 45 | properties.load(fileInputStream); 46 | } 47 | return properties; 48 | } 49 | 50 | @Override 51 | public String resolve(String parameter) { 52 | return props.getProperty(parameter); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /bench-tools-maven/src/main/java/org/quickperf/maven/bench/config/DefaultBenchConfigurationResolver.java: -------------------------------------------------------------------------------- 1 | package org.quickperf.maven.bench.config; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.Objects; 7 | 8 | /** 9 | * Default strategy to resolve all configuration parameters for maven benchmark in the following order: 10 | * 11 | *
    12 | *
  1. from Environment Variable
  2. 13 | *
  3. from System properties
  4. 14 | *
  5. from a local configuration file named
    local-maven-bench.properties
  6. 15 | *
  7. from the default configuration file named
    maven-bench.properties
  8. 16 | *
17 | */ 18 | class DefaultBenchConfigurationResolver implements BenchConfigurationResolver { 19 | 20 | private static final String CONFIG_FILENAME = "maven-bench.properties"; 21 | 22 | private final List resolvers = new ArrayList<>(); 23 | 24 | DefaultBenchConfigurationResolver() { 25 | resolvers.add(key -> { 26 | final String name = key.toUpperCase() 27 | .replace('.', '_') 28 | .replace('-', '_'); 29 | return System.getenv(name); 30 | }); 31 | resolvers.add(System::getProperty); 32 | addBenchPropertiesFromFile(resolvers, "local." + CONFIG_FILENAME); 33 | addBenchPropertiesFromFile(resolvers, CONFIG_FILENAME); 34 | } 35 | 36 | private void addBenchPropertiesFromFile(List resolvers, String fileName) { 37 | try { 38 | resolvers.add(BenchConfigurationFileBasedResolver.createBenchPropertiesFileBasedResolver(fileName)); 39 | } catch (final IOException e) { 40 | // Ok we accept that a file config may not exist. 41 | } 42 | } 43 | 44 | @Override 45 | public String resolve(String parameter) { 46 | return resolvers.stream() 47 | .map(benchConfigurationResolver -> benchConfigurationResolver.resolve(parameter)) 48 | .filter(Objects::nonNull) 49 | .findFirst().orElse(null); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /bench-tools-maven/src/main/java/org/quickperf/maven/bench/projects/Maven3Version.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench.projects; 13 | 14 | import org.quickperf.maven.bench.config.BenchConfiguration; 15 | 16 | import java.io.File; 17 | import java.util.Arrays; 18 | 19 | public enum Maven3Version { 20 | V_3_0_4("3.0.4", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 21 | V_3_0_5("3.0.5", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 22 | V_3_1_0("3.1.0", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 23 | V_3_1_1("3.1.1", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 24 | V_3_2_1("3.2.1", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 25 | V_3_2_2("3.2.2", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 26 | V_3_2_3("3.2.3", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 27 | V_3_2_5("3.2.5", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 28 | V_3_3_1("3.3.1", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 29 | V_3_3_3("3.3.3", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 30 | V_3_3_9("3.3.9", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 31 | V_3_5_0("3.5.0", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 32 | V_3_5_2("3.5.2", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 33 | V_3_5_3("3.5.3", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 34 | V_3_5_4("3.5.4", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 35 | V_3_6_0("3.6.0", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 36 | V_3_6_1("3.6.1", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 37 | V_3_6_2("3.6.2", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 38 | V_3_6_3("3.6.3", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 39 | V_3_8_1("3.8.1", UrlPatterns.HTTP_RELEASE_DOWNLOAD), 40 | BRANCH_V_3_8("origin/maven-3.8.x", UrlPatterns.HTTP_GIT_REPO, "3.8.x"), 41 | HEAD("master", UrlPatterns.HTTP_GIT_REPO, "head"); 42 | 43 | private final String numVersion; 44 | private final String urlAsString; 45 | private final String version; 46 | private final InstallProcess installProcess; 47 | 48 | Maven3Version(String numVersion, String urlPattern, String configVersion) { 49 | this.numVersion = numVersion; 50 | this.version = configVersion; 51 | this.urlAsString = String.format(urlPattern, numVersion, numVersion); 52 | this.installProcess = InstallProcess.parse(urlPattern); 53 | } 54 | 55 | Maven3Version(String numVersion, String urlPattern) { 56 | this(numVersion, urlPattern, numVersion); 57 | } 58 | 59 | public String getMavenPath() { 60 | String mavenBinariesPath = BenchConfiguration.INSTANCE.getMavenBinariesPath(); 61 | return mavenBinariesPath + File.separator + "apache-maven-" + numVersion; 62 | } 63 | 64 | public String getUrlAsString() { 65 | return urlAsString; 66 | } 67 | 68 | public String getNumVersion() { 69 | return numVersion; 70 | } 71 | 72 | public InstallProcess getInstallProcess() { 73 | return installProcess; 74 | } 75 | 76 | @Override 77 | public String toString() { 78 | return "Maven" + " " + numVersion; 79 | } 80 | 81 | public static Maven3Version parse(String version) { 82 | return Arrays.stream(Maven3Version.values()) 83 | .filter(maven3Version -> maven3Version.version.equalsIgnoreCase(version)) 84 | .findFirst() 85 | .orElse(Maven3Version.HEAD); 86 | } 87 | 88 | public enum InstallProcess { 89 | GIT, 90 | HTTP; 91 | 92 | public static InstallProcess parse(String urlPattern) { 93 | final InstallProcess installProcess; 94 | switch (urlPattern) { 95 | case UrlPatterns.HTTP_GIT_REPO: 96 | installProcess = GIT; 97 | break; 98 | case UrlPatterns.HTTP_RELEASE_DOWNLOAD: 99 | default: 100 | installProcess = HTTP; 101 | break; 102 | } 103 | return installProcess; 104 | } 105 | } 106 | 107 | private static class UrlPatterns { 108 | private static final String HTTP_RELEASE_DOWNLOAD = "https://archive.apache.org/dist/maven/maven-3/%s/binaries/apache-maven-%s-bin.zip"; 109 | private static final String HTTP_GIT_REPO = "https://gitbox.apache.org/repos/asf/maven.git"; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /bench-tools-maven/src/main/java/org/quickperf/maven/bench/projects/TestingProject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench.projects; 13 | 14 | import org.quickperf.maven.bench.Command; 15 | import org.quickperf.maven.bench.commands.GitClone; 16 | 17 | import java.nio.file.Files; 18 | import java.nio.file.Paths; 19 | 20 | public class TestingProject { 21 | 22 | private final String repository; 23 | private final String version; 24 | private final String targetPath; 25 | 26 | public TestingProject(String name, String repository, String version, String targetPath) { 27 | this.repository = repository; 28 | this.version = version; 29 | this.targetPath = targetPath; 30 | } 31 | 32 | public boolean isNotAlreadyInstalled() { 33 | return Files.notExists(Paths.get(this.targetPath)); 34 | } 35 | 36 | public String getPath() { 37 | return targetPath; 38 | } 39 | 40 | public void installProject() { 41 | final Command install = new GitClone(this.repository, this.targetPath, this.version); 42 | install.execute(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /bench-tools-maven/src/test/java/org/quickperf/maven/bench/config/BenchConfigurationFileBasedResolverTestCase.java: -------------------------------------------------------------------------------- 1 | package org.quickperf.maven.bench.config; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.io.IOException; 7 | 8 | public class BenchConfigurationFileBasedResolverTestCase { 9 | 10 | @Test 11 | public void createBenchPropertiesFileBasedResolverShouldReturnResolverWhenFileExists() throws IOException { 12 | Assert.assertNotNull(BenchConfigurationFileBasedResolver.createBenchPropertiesFileBasedResolver("org/quickperf/maven/bench/config/test.properties")); 13 | } 14 | 15 | @Test(expected = IOException.class) 16 | public void createBenchPropertiesFileBasedResolverShouldReturnThrowIOExceptionWhenFileDoesNotExist() throws IOException { 17 | BenchConfigurationFileBasedResolver.createBenchPropertiesFileBasedResolver("org/quickperf/maven/bench/config/fileDoesNotExists.properties"); 18 | } 19 | 20 | @Test 21 | public void resolve() throws IOException { 22 | BenchConfigurationFileBasedResolver props = BenchConfigurationFileBasedResolver.createBenchPropertiesFileBasedResolver("org/quickperf/maven/bench/config/test.properties"); 23 | Assert.assertNull(props.resolve("doesNotExist")); 24 | Assert.assertEquals("Hello World!", props.resolve("person.say")); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /bench-tools-maven/src/test/java/org/quickperf/maven/bench/config/DefaultBenchConfigurationResolverTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench.config; 13 | 14 | import org.junit.Assert; 15 | import org.junit.Test; 16 | 17 | import static org.junit.Assert.assertEquals; 18 | 19 | public class DefaultBenchConfigurationResolverTest { 20 | 21 | private static final String ENV_TEST_KEY = "PATH"; 22 | 23 | private static final String MAVEN_VERSION_FROM = "maven.version.from"; 24 | private static final String SYSTEM_PROPERTIES_KEY = "hello.world"; 25 | 26 | private final DefaultBenchConfigurationResolver resolver = new DefaultBenchConfigurationResolver(); 27 | 28 | @Test 29 | public void getPropertyShouldReadFromDefaultMavenBenchProperties() { 30 | assertEquals("3.2.5", resolver.resolve(MAVEN_VERSION_FROM)); 31 | } 32 | 33 | @Test 34 | public void getPropertyShouldReadFromOsEnv() { 35 | Assert.assertNotNull(resolver.resolve(ENV_TEST_KEY)); 36 | } 37 | 38 | @Test 39 | public void getPropertyShouldReadFromSystemProperties() { 40 | final String expectedValue = "Foo Bar"; 41 | System.setProperty(SYSTEM_PROPERTIES_KEY, expectedValue); 42 | 43 | final String resolve = resolver.resolve(SYSTEM_PROPERTIES_KEY); 44 | 45 | assertEquals(expectedValue, resolve); 46 | } 47 | 48 | 49 | } -------------------------------------------------------------------------------- /bench-tools-maven/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootCategory=warn,console 2 | log4j.logger=info,console 3 | log4j.logger.org.quickperf.maven.bench=debug 4 | log4j.logger.org.eclipse.jgit=info 5 | 6 | log4j.appender.console=org.apache.log4j.ConsoleAppender 7 | log4j.appender.console.target=System.out 8 | log4j.appender.console.immediateFlush=true 9 | log4j.appender.console.encoding=UTF-8 10 | 11 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 12 | log4j.appender.console.layout.conversionPattern=%d [%t] %-5p %c - %m%n -------------------------------------------------------------------------------- /bench-tools-maven/src/test/resources/maven-bench.properties: -------------------------------------------------------------------------------- 1 | maven.version.from = 3.2.5 -------------------------------------------------------------------------------- /bench-tools-maven/src/test/resources/org/quickperf/maven/bench/config/test.properties: -------------------------------------------------------------------------------- 1 | person.say=Hello World! -------------------------------------------------------------------------------- /bench-tools/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 16 | 17 | maven-test-bench 18 | org.quickperf 19 | 1.0-SNAPSHOT 20 | 21 | 4.0.0 22 | 23 | bench-tools 24 | 25 | 26 | 27 | net.lingala.zip4j 28 | zip4j 29 | 2.9.1 30 | 31 | 32 | org.eclipse.jgit 33 | org.eclipse.jgit 34 | 5.7.0.202003110725-r 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /bench-tools/src/main/java/org/quickperf/maven/bench/Command.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench; 13 | 14 | /** 15 | * Define a command to perform in order to make a bench test for a project. 16 | */ 17 | public interface Command { 18 | 19 | /** 20 | * Execute a command. 21 | * 22 | * @return the output result. 23 | */ 24 | String execute(); 25 | } 26 | -------------------------------------------------------------------------------- /bench-tools/src/main/java/org/quickperf/maven/bench/commands/GitClone.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench.commands; 13 | 14 | import org.eclipse.jgit.api.Git; 15 | import org.eclipse.jgit.api.errors.GitAPIException; 16 | import org.quickperf.maven.bench.Command; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | import java.nio.file.Paths; 21 | 22 | public class GitClone implements Command { 23 | private static final Logger LOGGER = LoggerFactory.getLogger(GitClone.class); 24 | 25 | private final String sourceCloneUri; 26 | private final String targetPath; 27 | private final String checkoutBranch; 28 | 29 | public GitClone(String sourceCloneUri, String targetPath, String checkoutBranch) { 30 | this.sourceCloneUri = sourceCloneUri; 31 | this.targetPath = targetPath; 32 | this.checkoutBranch = checkoutBranch; 33 | } 34 | 35 | @Override 36 | public String execute() { 37 | try { 38 | LOGGER.info("Cloning {} into {}", sourceCloneUri, targetPath); 39 | final Git gitRepository = Git.cloneRepository() 40 | .setURI(sourceCloneUri) 41 | .setDirectory(Paths.get(targetPath).toFile()) 42 | .call(); 43 | LOGGER.info("Checking out {} commit", checkoutBranch); 44 | gitRepository.checkout().setName(checkoutBranch).call(); 45 | } catch (GitAPIException e) { 46 | throw new IllegalStateException("Could not clone " + sourceCloneUri + " repository.", e); 47 | } 48 | return targetPath; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /bench-tools/src/main/java/org/quickperf/maven/bench/commands/HttpGet.java: -------------------------------------------------------------------------------- 1 | package org.quickperf.maven.bench.commands; 2 | 3 | import org.quickperf.maven.bench.Command; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.io.File; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.net.MalformedURLException; 11 | import java.net.URL; 12 | import java.nio.channels.Channels; 13 | import java.nio.channels.FileChannel; 14 | import java.nio.channels.ReadableByteChannel; 15 | /* 16 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 17 | * 18 | * http://www.apache.org/licenses/LICENSE-2.0 19 | * 20 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 21 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 22 | * 23 | * Copyright 2019-2020 the original author or authors. 24 | */ 25 | 26 | public class HttpGet implements Command { 27 | 28 | private static final Logger LOGGER = LoggerFactory.getLogger(HttpGet.class); 29 | 30 | private final String sourceUrl; 31 | private final String targetPath; 32 | 33 | public HttpGet(String sourceUrl, String targetPath) { 34 | this.sourceUrl = sourceUrl; 35 | this.targetPath = targetPath; 36 | } 37 | 38 | @Override 39 | public String execute() { 40 | LOGGER.info("Downloading to {} from HTTP GET {}", targetPath, sourceUrl); 41 | File downloadDir = new File(targetPath); 42 | if(!downloadDir.exists()) { 43 | downloadDir.mkdir(); 44 | } 45 | 46 | URL url = buildURL(sourceUrl); 47 | String fileName = getDirectoryNameFromUrl(url); 48 | final String downloadedFilePath = String.format("%s/%s", targetPath, fileName); 49 | try ( 50 | final FileOutputStream fileOutputStream = new FileOutputStream(downloadedFilePath); 51 | final FileChannel fileChannel = fileOutputStream.getChannel() 52 | ) { 53 | ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream()); 54 | fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE); 55 | } catch (final IOException downloadEx) { 56 | throw new IllegalStateException("Could not download project under test.", downloadEx); 57 | } 58 | 59 | return downloadedFilePath; 60 | } 61 | 62 | private URL buildURL(String sourceUrlAsString) { 63 | try { 64 | return new URL(sourceUrlAsString); 65 | } catch (MalformedURLException malformedUrlEx) { 66 | throw new IllegalArgumentException("source url is not well formatted.", malformedUrlEx); 67 | } 68 | } 69 | 70 | private String getDirectoryNameFromUrl(URL url) { 71 | return url.getFile().substring(url.getFile().lastIndexOf("/") + 1); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /bench-tools/src/main/java/org/quickperf/maven/bench/commands/InstallWithHttpGet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench.commands; 13 | 14 | import org.quickperf.maven.bench.Command; 15 | 16 | public class InstallWithHttpGet implements Command { 17 | 18 | private final String sourceUrl; 19 | 20 | private final String targetPath; 21 | 22 | public InstallWithHttpGet(String sourceUrl, String targetPath) { 23 | this.sourceUrl = sourceUrl; 24 | this.targetPath = targetPath; 25 | } 26 | 27 | @Override 28 | public String execute() { 29 | final String targetFilePath = new HttpGet(sourceUrl, targetPath).execute(); 30 | ZipExtractor zipExtractor = new ZipExtractor(targetFilePath, targetPath); 31 | return zipExtractor.execute(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /bench-tools/src/main/java/org/quickperf/maven/bench/commands/ZipExtractor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench.commands; 13 | 14 | import net.lingala.zip4j.ZipFile; 15 | import net.lingala.zip4j.model.FileHeader; 16 | import org.quickperf.maven.bench.Command; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | import java.io.File; 21 | import java.io.IOException; 22 | import java.nio.file.Files; 23 | import java.nio.file.Path; 24 | import java.nio.file.Paths; 25 | 26 | public class ZipExtractor implements Command { 27 | private final static Logger LOGGER = LoggerFactory.getLogger(ZipExtractor.class); 28 | private final String sourceZipFilePath; 29 | private final String targetDirectoryPath; 30 | 31 | public ZipExtractor(String sourceZipFilePath, String targetDirectoryPath){ 32 | this.sourceZipFilePath = sourceZipFilePath; 33 | this.targetDirectoryPath = targetDirectoryPath; 34 | } 35 | 36 | @Override 37 | public String execute() { 38 | LOGGER.info("Extracting {} into {}", sourceZipFilePath, targetDirectoryPath); 39 | final ZipFile zipFile = new ZipFile(sourceZipFilePath); 40 | try { 41 | final FileHeader rootFileHeader = zipFile.getFileHeaders().get(0); 42 | if (rootFileHeader.isDirectory()) { 43 | final Path currentProjectPath = Paths.get(targetDirectoryPath); 44 | System.out.println(targetDirectoryPath); 45 | System.out.println(currentProjectPath); 46 | final String parentDirectoryPath = currentProjectPath.getParent().toString(); 47 | zipFile.extractAll(parentDirectoryPath); 48 | final Path extractProjectDirPath = Paths.get(parentDirectoryPath + File.separator + rootFileHeader.getFileName()); 49 | Files.move(extractProjectDirPath, Paths.get(targetDirectoryPath)); 50 | } else { 51 | zipFile.extractAll(targetDirectoryPath); 52 | } 53 | } catch (final IOException unableExtractingEx) { 54 | throw new IllegalStateException( 55 | "Unable to extract zip file " + sourceZipFilePath + " to directory " + targetDirectoryPath, 56 | unableExtractingEx); 57 | } 58 | return targetDirectoryPath; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /bench-tools/src/main/java/org/quickperf/maven/bench/config/BenchConfigurationResolver.java: -------------------------------------------------------------------------------- 1 | package org.quickperf.maven.bench.config; 2 | 3 | /** 4 | * Define the way to resolve the value of a configuration parameter. 5 | */ 6 | @FunctionalInterface 7 | interface BenchConfigurationResolver { 8 | String resolve(String parameter); 9 | } 10 | -------------------------------------------------------------------------------- /bench-tools/src/test/java/org.quickperf.maven.bench.commands/GitCloneTest.java: -------------------------------------------------------------------------------- 1 | package org.quickperf.maven.bench.commands; 2 | 3 | import org.eclipse.jgit.api.Git; 4 | import org.eclipse.jgit.api.errors.GitAPIException; 5 | import org.eclipse.jgit.revwalk.RevCommit; 6 | import org.junit.AfterClass; 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.nio.charset.StandardCharsets; 13 | import java.nio.file.Files; 14 | import java.nio.file.Path; 15 | import java.nio.file.Paths; 16 | import java.util.Comparator; 17 | import java.util.List; 18 | import java.util.Properties; 19 | import java.util.stream.Collectors; 20 | import java.util.stream.Stream; 21 | 22 | import static java.util.Collections.singletonList; 23 | import static org.assertj.core.api.Assertions.assertThat; 24 | import static org.assertj.core.util.Arrays.asList; 25 | import static org.quickperf.maven.bench.commands.PropertiesUtils.loadBenchToolsProperties; 26 | 27 | public class GitCloneTest { 28 | private static Path GIT_CLONE_WORKING_DIR_PATH; 29 | public static Path FAKE_ORIGINAL_GIT_REPO_PATH; 30 | 31 | @BeforeClass 32 | public static void setUpBeforeClass() throws IOException, GitAPIException { 33 | GIT_CLONE_WORKING_DIR_PATH = Files.createTempDirectory("org-quickperf-maven-bench-commands-gitclone"); 34 | FAKE_ORIGINAL_GIT_REPO_PATH = GIT_CLONE_WORKING_DIR_PATH.resolve("fakeOriginalGitRepo"); 35 | 36 | final File gitRepoDir = FAKE_ORIGINAL_GIT_REPO_PATH.toFile(); 37 | Git.init().setDirectory(gitRepoDir).call(); 38 | final Path fakeReadMePath = FAKE_ORIGINAL_GIT_REPO_PATH.resolve("README.md"); 39 | Files.write(fakeReadMePath, "# READE ME\n".getBytes(StandardCharsets.UTF_8)); 40 | Git.open(gitRepoDir).add().addFilepattern("README.md").call(); 41 | Git.open(gitRepoDir).commit().setAll(true).setMessage("Initial Commit").call(); 42 | } 43 | 44 | @AfterClass 45 | public static void tearDownAfterClass() throws IOException { 46 | Files.walk(GIT_CLONE_WORKING_DIR_PATH) 47 | .sorted(Comparator.reverseOrder()) 48 | .map(Path::toFile) 49 | .forEach(File::delete); 50 | } 51 | 52 | @Test 53 | public void execute() throws IOException { 54 | final Path outputDirPath = GIT_CLONE_WORKING_DIR_PATH.resolve("test"); 55 | final GitClone gitClone = new GitClone(FAKE_ORIGINAL_GIT_REPO_PATH.toUri().toString(), 56 | outputDirPath.toString(), 57 | "master"); 58 | 59 | final String result = gitClone.execute(); 60 | 61 | assertThat(result).isEqualTo(outputDirPath.toString()); 62 | final Path resultDirPath = Paths.get(result); 63 | final List files = Files.list(resultDirPath).collect(Collectors.toList()); 64 | assertThat(files).containsOnly( 65 | resultDirPath.resolve(".git"), 66 | resultDirPath.resolve("README.md") 67 | ); 68 | } 69 | } -------------------------------------------------------------------------------- /bench-tools/src/test/java/org.quickperf.maven.bench.commands/HttpGetTest.java: -------------------------------------------------------------------------------- 1 | package org.quickperf.maven.bench.commands; 2 | 3 | import org.junit.BeforeClass; 4 | import org.junit.Test; 5 | 6 | import java.io.IOException; 7 | import java.util.Properties; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 11 | import static org.quickperf.maven.bench.commands.PropertiesUtils.loadBenchToolsProperties; 12 | 13 | public class HttpGetTest { 14 | private static final String SOURCE_URL = "org.quickperf.maven.bench.commands.httpGet.sourceUrl"; 15 | private static final String TARGET_PATH = "org.quickperf.maven.bench.commands.httpGet.targetPath"; 16 | private static final String WRONG_SOURCE_URL = "org.quickperf.maven.bench.commands.httpGet.wrongSourceUrl"; 17 | private static final String NOT_EXISTS_SOURCE_URL = "org.quickperf.maven.bench.commands.httpGet.notExistsSourceUrl"; 18 | private static final Properties PROPERTIES = loadBenchToolsProperties(); 19 | 20 | @Test 21 | public void executeShouldReturnDownloadedFilePath() { 22 | final HttpGet command = new HttpGet(PROPERTIES.getProperty(SOURCE_URL), PROPERTIES.getProperty(TARGET_PATH)); 23 | 24 | final String result = command.execute(); 25 | 26 | assertThat(result).isNotNull(); 27 | assertThat(result).isEqualTo(PROPERTIES.getProperty(TARGET_PATH) + "/index.txt"); 28 | } 29 | 30 | @Test 31 | public void executeShouldThrowIllegalArgumentExWhenSourceUrlIsNotAnUrl() { 32 | final HttpGet command = new HttpGet(PROPERTIES.getProperty(WRONG_SOURCE_URL), PROPERTIES.getProperty(TARGET_PATH)); 33 | 34 | assertThatThrownBy(command::execute).isInstanceOf(IllegalArgumentException.class); 35 | } 36 | 37 | @Test 38 | public void executeShouldThrowIllegalStateExWhenSourceUrlCouldNotBeDownloaded() { 39 | final HttpGet command = new HttpGet(PROPERTIES.getProperty(NOT_EXISTS_SOURCE_URL), PROPERTIES.getProperty(TARGET_PATH)); 40 | 41 | assertThatThrownBy(command::execute).isInstanceOf(IllegalStateException.class); 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /bench-tools/src/test/java/org.quickperf.maven.bench.commands/PropertiesUtils.java: -------------------------------------------------------------------------------- 1 | package org.quickperf.maven.bench.commands; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.FileInputStream; 7 | import java.io.IOException; 8 | import java.io.UnsupportedEncodingException; 9 | import java.net.URL; 10 | import java.net.URLDecoder; 11 | import java.nio.charset.StandardCharsets; 12 | import java.util.Properties; 13 | 14 | public class PropertiesUtils { 15 | private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesUtils.class); 16 | 17 | static Properties loadBenchToolsProperties() { 18 | final Properties properties = new Properties(); 19 | 20 | URL resource = HttpGet.class.getClassLoader().getResource("bench-tools.properties"); 21 | if (resource == null) { 22 | LOGGER.error("bench-tools.properties does not exist."); 23 | } else { 24 | String propertiesFilePath; 25 | try { 26 | propertiesFilePath = URLDecoder.decode(resource.getPath(), StandardCharsets.UTF_8.toString()); 27 | try (final FileInputStream fileInputStream = new FileInputStream(propertiesFilePath)) { 28 | properties.load(fileInputStream); 29 | } catch (IOException ioException) { 30 | LOGGER.error("Access denied to bench-tools.properties."); 31 | } 32 | } catch (UnsupportedEncodingException e) { 33 | LOGGER.error("Path to bench-tools.properties contains unknown encoded characters"); 34 | } 35 | } 36 | 37 | return properties; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /bench-tools/src/test/java/org.quickperf.maven.bench.commands/PropertiesUtilsTest.java: -------------------------------------------------------------------------------- 1 | package org.quickperf.maven.bench.commands; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.IOException; 6 | import java.util.Properties; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | public class PropertiesUtilsTest { 11 | 12 | public static final String KEY_TEST = "org.quickperf.maven.bench.commands.propertiesUtils.test"; 13 | 14 | @Test 15 | public void loadBenchToolsProperties() { 16 | final Properties properties = PropertiesUtils.loadBenchToolsProperties(); 17 | 18 | assertThat(properties).isNotNull(); 19 | assertThat(properties.getProperty(KEY_TEST)).isEqualTo("Hello World"); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /bench-tools/src/test/resources/bench-tools.properties: -------------------------------------------------------------------------------- 1 | org.quickperf.maven.bench.commands.propertiesUtils.test=Hello World 2 | 3 | org.quickperf.maven.bench.commands.httpGet.sourceUrl=file://${project.build.testOutputDirectory}/data/index.txt 4 | org.quickperf.maven.bench.commands.httpGet.targetPath=${project.build.testOutputDirectory}/download 5 | org.quickperf.maven.bench.commands.httpGet.wrongSourceUrl=${project.build.testOutputDirectory}/data/index.txt 6 | org.quickperf.maven.bench.commands.httpGet.notExistsSourceUrl=file://${project.build.testOutputDirectory}/data/notExists.txt 7 | 8 | -------------------------------------------------------------------------------- /bench-tools/src/test/resources/data/index.txt: -------------------------------------------------------------------------------- 1 | This is Maven Test Bench from QuickPerf -------------------------------------------------------------------------------- /bench-tools/src/test/resources/download/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quick-perf/maven-test-bench/c90f141daf072bd020145343d4b5c77c48769bc8/bench-tools/src/test/resources/download/.gitkeep -------------------------------------------------------------------------------- /bench-tools/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootCategory=warn,console 2 | log4j.logger=info,console 3 | log4j.logger.org.quickperf.maven.bench=debug 4 | log4j.logger.org.eclipse.jgit=info 5 | 6 | log4j.appender.console=org.apache.log4j.ConsoleAppender 7 | log4j.appender.console.target=System.out 8 | log4j.appender.console.immediateFlush=true 9 | log4j.appender.console.encoding=UTF-8 10 | 11 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 12 | log4j.appender.console.layout.conversionPattern=%d [%t] %-5p %c - %m%n -------------------------------------------------------------------------------- /maven-perf/NEXT_STEP.md: -------------------------------------------------------------------------------- 1 | # Next steps 2 | 3 | ## Goals 4 | 5 | Have an measurement history for maven test bench 6 | 7 | ## Steps 8 | 9 | maven test bench side 10 | 1) Create a s3 bucket (done: bucketname: quickperf-maventestbench-measurements) 11 | 2) Push each measure file to s3 bucket thanks to a custom exporter (change AllocationExporter to push to s3) 12 | 1) Think to push a timestamped file 13 | 14 | maven plugin apache site 15 | 1) Get all s3 files 16 | 1) first all 17 | 2) second just take the last 10 days 18 | 2) Parse measurement file 19 | 1) ex: 3.31 Giga bytes (3 552 270 680 bytes) --> parse to get only 3552270680 20 | 3) Generate graph from measurements -------------------------------------------------------------------------------- /maven-perf/measures/Maven3.2.5-JMC.5.5JPG.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quick-perf/maven-test-bench/c90f141daf072bd020145343d4b5c77c48769bc8/maven-perf/measures/Maven3.2.5-JMC.5.5JPG.jpg -------------------------------------------------------------------------------- /maven-perf/measures/execution-context-2019-09-01-18-48-41.txt: -------------------------------------------------------------------------------- 1 | Warm up: 1 2 | 3 | Java version: 11.0.1 4 | Java vendor: Oracle Corporation 5 | Java VM name: Java HotSpot(TM) 64-Bit Server VM 6 | 7 | Processor: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz 8 | Logical processor count: 8 9 | 10 | Total memory (giga bytes): 15 11 | Available memory (giga bytes): 12.701236724853516 12 | 13 | OS: Microsoft Windows 10 build 17134 -------------------------------------------------------------------------------- /maven-perf/measures/maven-memory-allocation-2019-09-01-18-48-41.csv: -------------------------------------------------------------------------------- 1 | Maven version,Average (bytes),Average (Gb),Min (bytes),Max (bytes),Allocation 1 (bytes),Allocation 2 (bytes),Allocation 3 (bytes),Allocation 4 (bytes),Allocation 5 (bytes),Allocation 6 (bytes),Allocation 7 (bytes),Allocation 8 (bytes),Allocation 9 (bytes),Allocation 10 (bytes),Allocation 1 (Gb),Allocation 2 (Gb),Allocation 3 (Gb),Allocation 4 (Gb),Allocation 5 (Gb),Allocation 6 (Gb),Allocation 7 (Gb),Allocation 8 (Gb),Allocation 9 (Gb),Allocation 10 (Gb) 2 | Maven 3.2.5,1.9789881664E10,18.43076354265213,19726297408,19976266976,19767425352,19726297408,19816443264,19747273792,19777588072,19726663008,19976266976,19731830152,19866696088,19762332528,18.40984947234392,18.3715460896492,18.455500960350037,18.391081869602203,18.419314242899418,18.37188658118248,18.60434839129448,18.37669885903597,18.502302549779415,18.405106410384178 3 | Maven 3.3.1,1.63652819808E10,15.241356548666953,16230773864,16693424392,16262686712,16693424392,16334764760,16321124736,16471252752,16320766328,16246968320,16295583240,16475474704,16230773864,15.145807258784771,15.546962983906269,15.212935172021389,15.200231909751892,15.340049520134926,15.19989811629057,15.131168365478516,15.176444537937641,15.343981519341469,15.116086103022099 4 | Maven 3.3.3,1.63498950344E10,15.227026338130235,16217341776,16433631352,16394038256,16347943048,16334895464,16343550120,16217341776,16388924368,16347059936,16433631352,16301460552,16390105472,15.26813791692257,15.225208409130573,15.213056899607182,15.221117176115513,15.103576496243477,15.263375237584114,15.22438594698906,15.305011861026287,15.1819182112813,15.264475226402283 5 | Maven 3.3.9,1.64261345472E10,15.298029917478562,16332680160,16500938056,16447794464,16453595712,16406149696,16332680160,16422662512,16464767464,16362820600,16454565624,16500938056,16415371184,15.318202286958694,15.323605120182037,15.27941757440567,15.210993736982346,15.294796332716942,15.334009625017643,15.239064209163189,15.324508421123028,15.367696113884449,15.288005754351616 6 | Maven 3.5.0,9.0067345608E9,8.388175220042466,8940200944,9075800320,8960115616,8940200944,9033529568,9051340136,9068634592,8987055624,8977630160,9075800320,8950870232,9022168416,8.344757944345474,8.326210960745811,8.413130015134811,8.429717399179935,8.44582411646843,8.369847781956196,8.36106963455677,8.452497720718384,8.336147509515285,8.402549117803574 7 | Maven 3.5.2,9.0290809992E9,8.408986962586642,8964607952,9127326760,9035467704,9127326760,8996199712,8994889472,8964607952,9075934248,9027703368,9037162032,9028764376,9002754368,8.414935044944286,8.500485457479954,8.378363877534866,8.377143621444702,8.348941758275032,8.452622450888157,8.407703943550587,8.41651301085949,8.408692084252834,8.384468376636505 8 | Maven 3.5.3,9.1027149184E9,8.477563893795013,8988880912,9223481632,9215697584,9099222808,9045095824,9133152248,8988880912,9050947000,9223481632,9032652392,9075718872,9162299912,8.582787200808525,8.474311612546444,8.423901930451393,8.505910865962505,8.37154771387577,8.429351262748241,8.590036660432816,8.4123130813241,8.452421866357327,8.533056743443012 9 | Maven 3.5.4,9.3033531864E9,8.664422842115163,9249422072,9407891048,9251326096,9276245960,9249422072,9272522200,9298142992,9281981576,9281806088,9406696280,9307497552,9407891048,8.615968838334084,8.639177270233631,8.614195577800274,8.635709248483181,8.659570470452309,8.644518978893757,8.644355542957783,8.760668598115444,8.668282583355904,8.761781312525272 10 | Maven 3.6.0,9.5467233096E9,8.891078931838274,9460713560,9727374280,9517162512,9511551880,9460713560,9549597152,9517631656,9476896688,9727374280,9501802248,9686110464,9518392656,8.863548293709755,8.858322985470295,8.81097611039877,8.893755406141281,8.8639852181077,8.826047822833061,9.059323258697987,8.849242933094501,9.020893335342407,8.864693954586983 11 | Maven 3.6.1,7.7437195136E9,7.211900794506073,7644467376,7884269760,7745229056,7822170928,7884269760,7793330568,7706046232,7672915680,7644467376,7704195424,7759306328,7705263784,7.213306665420532,7.284964367747307,7.342798411846161,7.25810468941927,7.176814816892147,7.145959585905075,7.119465038180351,7.175091117620468,7.226417146623135,7.176086105406284 12 | Maven 3.6.2,3.3445866128E9,3.1148890152573587,3298792248,3445668176,3317396000,3330513160,3316534824,3422256552,3312832264,3298792248,3316562936,3310245744,3375064224,3445668176,3.08956578373909,3.101782090961933,3.088763751089573,3.1872247830033302,3.0853154733777046,3.072239689528942,3.0887899324297905,3.08290658891201,3.143273502588272,3.2090285569429398 13 | -------------------------------------------------------------------------------- /maven-perf/measures/mvn-validate-on-camel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quick-perf/maven-test-bench/c90f141daf072bd020145343d4b5c77c48769bc8/maven-perf/measures/mvn-validate-on-camel.png -------------------------------------------------------------------------------- /maven-perf/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 16 | 17 | maven-test-bench 18 | org.quickperf 19 | 1.0-SNAPSHOT 20 | 21 | 4.0.0 22 | 23 | maven-perf 24 | 25 | 26 | 27 | org.quickperf 28 | bench-tools-maven 29 | 1.0-SNAPSHOT 30 | test 31 | 32 | 33 | org.apache.maven.shared 34 | maven-verifier 35 | 1.6 36 | test 37 | 38 | 39 | commons-io 40 | commons-io 41 | 2.7 42 | test 43 | 44 | 45 | org.quickperf 46 | quick-perf-junit4 47 | 1.0.0 48 | test 49 | 50 | 51 | org.quickperf 52 | quick-perf-jfr-annotations 53 | 1.0.0 54 | test 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /maven-perf/src/test/java/org/quickperf/maven/bench/MvnValidateAllocationByMaven3VersionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench; 13 | 14 | import org.apache.commons.io.FileUtils; 15 | import org.apache.maven.it.VerificationException; 16 | import org.apache.maven.it.Verifier; 17 | import org.junit.Before; 18 | import org.junit.Test; 19 | import org.junit.experimental.results.PrintableResult; 20 | import org.junit.runner.RunWith; 21 | import org.quickperf.junit4.QuickPerfJUnitRunner; 22 | import org.quickperf.jvm.allocation.AllocationUnit; 23 | import org.quickperf.jvm.annotations.HeapSize; 24 | import org.quickperf.jvm.annotations.MeasureHeapAllocation; 25 | import org.quickperf.maven.bench.config.BenchConfiguration; 26 | import org.quickperf.maven.bench.commands.InstallMavenVersionIfNotExists; 27 | import org.quickperf.maven.bench.projects.Maven3Version; 28 | import org.quickperf.maven.bench.projects.TestingProject; 29 | import org.quickperf.repository.LongFileRepository; 30 | import org.quickperf.repository.ObjectFileRepository; 31 | import org.slf4j.Logger; 32 | import org.slf4j.LoggerFactory; 33 | 34 | import java.io.File; 35 | import java.io.FilenameFilter; 36 | import java.io.IOException; 37 | import java.nio.file.Files; 38 | import java.nio.file.Path; 39 | import java.nio.file.Paths; 40 | import java.text.DateFormat; 41 | import java.text.SimpleDateFormat; 42 | import java.util.Collections; 43 | import java.util.Date; 44 | import java.util.List; 45 | 46 | import static org.junit.experimental.results.PrintableResult.testResult; 47 | 48 | public class MvnValidateAllocationByMaven3VersionTest { 49 | 50 | private final Logger logger = LoggerFactory.getLogger(MvnValidateAllocationByMaven3VersionTest.class); 51 | 52 | @RunWith(QuickPerfJUnitRunner.class) 53 | public static class MvnValidate { 54 | 55 | private static final String TEMP_DIR_PATH = System.getProperty("java.io.tmpdir"); 56 | 57 | private static final Maven3Version MAVEN_3_VERSION = (Maven3Version) ObjectFileRepository.INSTANCE 58 | .find(TEMP_DIR_PATH, MvnValidateAllocationByMaven3VersionTest.MAVEN_3_VERSION_FILE_NAME); 59 | 60 | private final TestingProject projectUnderTest = BenchConfiguration.INSTANCE.getTestingProject(); 61 | 62 | private Verifier verifier; 63 | 64 | private final List validate = Collections.singletonList("validate"); 65 | 66 | @Before 67 | public void before() throws VerificationException { 68 | System.out.println(MAVEN_3_VERSION); 69 | 70 | String mavenPath = MAVEN_3_VERSION.getMavenPath(); 71 | 72 | System.setProperty("verifier.forkMode", "auto"); // embedded 73 | 74 | System.setProperty("maven.home", mavenPath); 75 | 76 | if (projectUnderTest.isNotAlreadyInstalled()) { 77 | try { 78 | projectUnderTest.installProject(); 79 | } catch (IllegalStateException mavenProjectUnderTestNotInstallEx) { 80 | throw new IllegalStateException(mavenProjectUnderTestNotInstallEx); 81 | } 82 | } 83 | 84 | final String projectDirectoryPath = projectUnderTest.getPath(); 85 | verifier = new Verifier(projectDirectoryPath); 86 | verifier.setSystemProperty("maven.multiModuleProjectDirectory", projectDirectoryPath); 87 | } 88 | 89 | @HeapSize(value = 6, unit = AllocationUnit.GIGA_BYTE) 90 | @MeasureHeapAllocation 91 | @Test 92 | public void execute_maven_validate() throws VerificationException { 93 | verifier.executeGoals(validate); 94 | } 95 | 96 | } 97 | 98 | private static final String MAVEN_3_VERSION_FILE_NAME = "org.quickperf.maven.bench.projects.Maven3Version"; 99 | 100 | private final String tempDirPath = System.getProperty("java.io.tmpdir"); 101 | 102 | private final FilenameFilter quickPerfDirFilter = (dir, name) -> name.contains("QuickPerf"); 103 | 104 | private final File tempDir = new File(tempDirPath); 105 | 106 | @Test 107 | public void measure() throws IOException { 108 | logger.debug("measure - start"); 109 | String dateTimeAsString = getDateTimeAsString(); 110 | String resultFilePath = buildAllocationCsvExportPath(dateTimeAsString); 111 | 112 | int numberOfMeasuresByVersion = BenchConfiguration.INSTANCE.getNumberOfMeasuresByMavenVersion(); 113 | 114 | Class testClass = MvnValidate.class; 115 | 116 | List maven3VersionsToMeasure = BenchConfiguration.INSTANCE.getMaven3VersionsToMeasure(); 117 | for (Maven3Version maven3Version : maven3VersionsToMeasure) { 118 | 119 | new InstallMavenVersionIfNotExists(maven3Version).execute(); 120 | 121 | saveMavenVersion(maven3Version); 122 | 123 | applyWarmMeasurements(maven3Version, testClass); 124 | 125 | AllocationTimePair[] allocations = measureAllocationSeveralTimes(testClass, numberOfMeasuresByVersion); 126 | 127 | AllocationCsvExporter.INSTANCE.writeAllocationsToCsv(maven3Version 128 | , allocations 129 | , resultFilePath); 130 | } 131 | 132 | 133 | 134 | String csvContent = readCsvContentFrom(resultFilePath); 135 | logger.info("Bench result" + System.lineSeparator() + csvContent); 136 | 137 | ExecutionContextTextExporter.INSTANCE.writeExecutionContextToTextFile(dateTimeAsString); 138 | logger.debug("measure - end"); 139 | } 140 | 141 | private String readCsvContentFrom(String resultFilePath) throws IOException { 142 | Path path = Paths.get(resultFilePath); 143 | return Files.readString(path); 144 | } 145 | 146 | private void saveMavenVersion(Maven3Version maven3Version) { 147 | FileUtils.deleteQuietly(new File(tempDirPath 148 | + File.separator 149 | + MAVEN_3_VERSION_FILE_NAME 150 | ) 151 | ); 152 | ObjectFileRepository.INSTANCE.save( tempDirPath 153 | , MAVEN_3_VERSION_FILE_NAME 154 | , maven3Version); 155 | } 156 | 157 | private void applyWarmMeasurements(Maven3Version maven3Version, Class testClass) throws IOException { 158 | int numberOfWarms = BenchConfiguration.INSTANCE.getNumberOfWarms(); 159 | if(numberOfWarms != 0) { 160 | System.out.println(maven3Version + " - Start " + numberOfWarms + " warm up"); 161 | System.out.println("-----------------------------"); 162 | measureAllocationSeveralTimes(testClass, numberOfWarms); 163 | System.out.println(maven3Version + " - End warm up"); 164 | System.out.println("----------------------------"); 165 | } 166 | } 167 | 168 | private String buildAllocationCsvExportPath(String dateTimeAsString) throws IOException { 169 | String measurementsExportPathName = BenchConfiguration.INSTANCE.getExportPathOfMeasures(); 170 | final Path measurementsExportPath = Paths.get(measurementsExportPathName); 171 | if (Files.notExists(measurementsExportPath)) { 172 | Files.createDirectories(measurementsExportPath); 173 | } 174 | String fileName = "maven-memory-allocation" + "-" + dateTimeAsString + ".csv"; 175 | return measurementsExportPathName + File.separator + fileName; 176 | } 177 | 178 | private String getDateTimeAsString() { 179 | DateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); 180 | return df.format(new Date()); 181 | } 182 | 183 | private AllocationTimePair[] measureAllocationSeveralTimes(Class testClass, int numberOfTimes) throws IOException { 184 | AllocationTimePair[] allocations = new AllocationTimePair[numberOfTimes]; 185 | for (int i = 0; i < numberOfTimes; i++) { 186 | allocations[i] =measureAllocation(testClass); 187 | } 188 | return allocations; 189 | } 190 | 191 | private AllocationTimePair measureAllocation(Class testClass) throws IOException { 192 | deleteQuickPerfFoldersInTemp(); 193 | long startTime = System.currentTimeMillis(); 194 | PrintableResult printableResult = testResult(testClass); 195 | long executionTimeInMilliseconds = System.currentTimeMillis() - startTime; 196 | if(printableResult.failureCount() != 0) { 197 | System.out.println("Allocation can't be measured. " + printableResult.toString()); 198 | } 199 | Long allocationInBytes = retrieveMeasuredAllocationInBytes(); 200 | Long lengthInSeconds = executionTimeInMilliseconds/1000L; 201 | System.out.println("Allocation in bytes: " + allocationInBytes); 202 | System.out.println("Length in seconds: " + lengthInSeconds); 203 | System.out.println("----------------"); 204 | return new AllocationTimePair(allocationInBytes, lengthInSeconds); 205 | } 206 | 207 | private void deleteQuickPerfFoldersInTemp() throws IOException { 208 | File[] quickPerfFoldersBeforeMeasure = tempDir.listFiles(quickPerfDirFilter); 209 | for (File quickPerfFolder : quickPerfFoldersBeforeMeasure) { 210 | FileUtils.deleteDirectory(quickPerfFolder); 211 | } 212 | } 213 | 214 | private Long retrieveMeasuredAllocationInBytes() { 215 | LongFileRepository longFileRepository = new LongFileRepository(); 216 | String[] quickPerfFolders = tempDir.list(quickPerfDirFilter); 217 | if (quickPerfFolders.length != 1) { 218 | throw new IllegalStateException("Several QuickPerf folders found in temp."); 219 | } 220 | String quickPerfFolderPath = tempDirPath 221 | + File.separator 222 | + quickPerfFolders[0]; 223 | return longFileRepository.find(quickPerfFolderPath, "allocation.ser"); 224 | } 225 | 226 | } 227 | -------------------------------------------------------------------------------- /maven-perf/src/test/java/org/quickperf/maven/bench/MvnValidateMaxAllocation.java: -------------------------------------------------------------------------------- 1 | package org.quickperf.maven.bench; 2 | 3 | import org.apache.maven.it.VerificationException; 4 | import org.apache.maven.it.Verifier; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | import org.junit.experimental.results.PrintableResult; 8 | import org.junit.runner.RunWith; 9 | import org.quickperf.junit4.QuickPerfJUnitRunner; 10 | import org.quickperf.jvm.allocation.AllocationUnit; 11 | import org.quickperf.jvm.annotations.ExpectMaxHeapAllocation; 12 | import org.quickperf.jvm.annotations.HeapSize; 13 | import org.quickperf.jvm.annotations.MeasureHeapAllocation; 14 | import org.quickperf.maven.bench.commands.InstallMavenVersionIfNotExists; 15 | import org.quickperf.maven.bench.config.BenchConfiguration; 16 | import org.quickperf.maven.bench.projects.Maven3Version; 17 | import org.quickperf.maven.bench.projects.TestingProject; 18 | import org.quickperf.writer.WriterFactory; 19 | 20 | import java.io.FileWriter; 21 | import java.io.IOException; 22 | import java.io.Writer; 23 | import java.util.Collections; 24 | import java.util.List; 25 | 26 | public class MvnValidateMaxAllocation { 27 | 28 | @RunWith(QuickPerfJUnitRunner.class) 29 | public static class MvnValidate { 30 | 31 | private final TestingProject apacheCamelProject = BenchConfiguration.INSTANCE.getTestingProject(); 32 | 33 | private Verifier verifier; 34 | private final List validate = Collections.singletonList("validate"); 35 | 36 | @Before 37 | public void before() throws VerificationException { 38 | final var mavenVersion = BenchConfiguration.INSTANCE.getMavenGitVersion(); 39 | final Maven3Version version = Maven3Version.parse(mavenVersion); 40 | new InstallMavenVersionIfNotExists(version).execute(); 41 | System.setProperty("verifier.forkMode", "auto"); // embedded 42 | System.setProperty("maven.home", version.getMavenPath()); 43 | if (apacheCamelProject.isNotAlreadyInstalled()) { 44 | try { 45 | apacheCamelProject.installProject(); 46 | } catch (IllegalStateException mavenProjectUnderTestNotInstallEx) { 47 | throw new IllegalStateException(mavenProjectUnderTestNotInstallEx); 48 | } 49 | } 50 | 51 | final String projectDirectoryPath = apacheCamelProject.getPath(); 52 | verifier = new Verifier(projectDirectoryPath); 53 | verifier.setSystemProperty("maven.multiModuleProjectDirectory", projectDirectoryPath); 54 | } 55 | 56 | @Test 57 | @HeapSize(value = 4, unit = AllocationUnit.GIGA_BYTE) 58 | @ExpectMaxHeapAllocation(value = 4.50, unit = AllocationUnit.GIGA_BYTE) 59 | @MeasureHeapAllocation(writerFactory = AllocationExporter.class, format = "%s") 60 | public void execute_maven_validate() throws VerificationException { 61 | verifier.executeGoals(validate); 62 | } 63 | 64 | public static class AllocationExporter implements WriterFactory { 65 | 66 | @Override 67 | public Writer buildWriter() throws IOException { 68 | return new FileWriter("./target/Allocation.txt"); 69 | } 70 | 71 | } 72 | 73 | 74 | } 75 | 76 | @Test 77 | public void verify_heap_allocation_of_mvn_validate() { 78 | 79 | // GIVEN 80 | Class testClass = MvnValidate.class; 81 | 82 | // WHEN 83 | PrintableResult printableResult = PrintableResult.testResult(testClass); 84 | 85 | // THEN 86 | if(testHasFailed(printableResult)) { 87 | String junit4ErrorReport = printableResult.toString(); 88 | String errorMessage = buildErrorMessage(junit4ErrorReport); 89 | throw new AssertionError(errorMessage 90 | + System.lineSeparator() 91 | + junit4ErrorReport); 92 | 93 | } 94 | 95 | } 96 | 97 | private String buildErrorMessage(String junit4ErrorReport) { 98 | if(isAllocationIssue(junit4ErrorReport)) { 99 | return "Allocation greater than expected."; 100 | } 101 | return "Unexpected failure."; 102 | } 103 | 104 | private boolean isAllocationIssue(String junit4ErrorReport) { 105 | return junit4ErrorReport.contains("Expected heap allocation"); 106 | } 107 | 108 | private boolean testHasFailed(PrintableResult printableResult) { 109 | return printableResult.failureCount() != 0; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /maven-perf/src/test/java/org/quickperf/maven/bench/MvnValidateProfilingTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 3 | * 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 7 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | * 9 | * Copyright 2019-2020 the original author or authors. 10 | */ 11 | 12 | package org.quickperf.maven.bench; 13 | 14 | import org.apache.maven.it.VerificationException; 15 | import org.apache.maven.it.Verifier; 16 | import org.junit.Before; 17 | import org.junit.Test; 18 | import org.junit.runner.RunWith; 19 | import org.quickperf.junit4.QuickPerfJUnitRunner; 20 | import org.quickperf.jvm.allocation.AllocationUnit; 21 | import org.quickperf.jvm.annotations.HeapSize; 22 | import org.quickperf.jvm.jfr.annotation.ProfileJvm; 23 | import org.quickperf.maven.bench.commands.InstallMavenVersionIfNotExists; 24 | import org.quickperf.maven.bench.config.BenchConfiguration; 25 | import org.quickperf.maven.bench.projects.Maven3Version; 26 | import org.quickperf.maven.bench.projects.TestingProject; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | import java.util.Collections; 31 | import java.util.List; 32 | 33 | @RunWith(QuickPerfJUnitRunner.class) 34 | public class MvnValidateProfilingTest { 35 | 36 | private Logger logger = LoggerFactory.getLogger(MvnValidateProfilingTest.class); 37 | 38 | public static Maven3Version MAVEN_3_VERSION = Maven3Version.V_3_2_5; 39 | 40 | private final TestingProject apacheCamelProject = BenchConfiguration.INSTANCE.getTestingProject(); 41 | 42 | private Verifier verifier; 43 | 44 | private final List validate = Collections.singletonList("validate"); 45 | 46 | @ProfileJvm 47 | @HeapSize(value = 6, unit = AllocationUnit.GIGA_BYTE) 48 | @Test 49 | public void execute_maven_validate() throws VerificationException { 50 | logger.debug("execute_maven_validate - start"); 51 | verifier.executeGoals(validate); 52 | logger.debug("execute_maven_validate - end"); 53 | } 54 | 55 | @Before 56 | public void before() throws VerificationException { 57 | if (apacheCamelProject.isNotAlreadyInstalled()) { 58 | try { 59 | apacheCamelProject.installProject(); 60 | } catch (IllegalStateException mavenProjectUnderTestNotInstallEx) { 61 | throw new IllegalStateException(mavenProjectUnderTestNotInstallEx); 62 | } 63 | } 64 | 65 | new InstallMavenVersionIfNotExists(MAVEN_3_VERSION).execute(); 66 | 67 | String mavenPath = MAVEN_3_VERSION.getMavenPath(); 68 | System.setProperty("verifier.forkMode", "auto"); // embedded 69 | System.setProperty("maven.home", mavenPath); 70 | 71 | verifier = new Verifier(apacheCamelProject.getPath()); 72 | verifier.setSystemProperty("maven.multiModuleProjectDirectory", apacheCamelProject.getPath()); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /maven-perf/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootCategory=warn,console 2 | log4j.logger=info,console 3 | log4j.logger.org.quickperf.maven.bench=debug 4 | log4j.logger.org.eclipse.jgit=info 5 | 6 | log4j.appender.console=org.apache.log4j.ConsoleAppender 7 | log4j.appender.console.target=System.out 8 | log4j.appender.console.immediateFlush=true 9 | log4j.appender.console.encoding=UTF-8 10 | 11 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 12 | log4j.appender.console.layout.conversionPattern=%d [%t] %-5p %c - %m%n -------------------------------------------------------------------------------- /maven-perf/src/test/resources/maven-bench.properties: -------------------------------------------------------------------------------- 1 | # Informations of the project on which a Maven command will be applied 2 | testing.project.name=camel 3 | testing.project.repository=https://github.com/apache/camel.git 4 | testing.project.version=ac11f88de75 5 | testing.project.path=${project.build.testOutputDirectory}/camel 6 | # Path of Maven distribution. The test bench will download Maven binaries to this path 7 | maven.binaries.path=${project.build.testOutputDirectory}/maven 8 | # On Windows, download is not possible in C:\\Program Files 9 | #--------------------------------------------------------------------------------- 10 | # THE PROPERTIES BELOW ARE ONLY USED BY org.quickperf.maven.bench.MvnValidateMaxAllocation 11 | maven.git.version=3.8.x 12 | #--------------------------------------------------------------------------------- 13 | # THE PROPERTIES BELOW ARE ONLY USED BY org.quickperf.maven.bench.MvnValidateAllocationByMaven3VersionTest 14 | # Maven version of the first measure 15 | maven.version.from=3.2.5 16 | # Maven version of the last measure 17 | maven.version.to=3.6.2 18 | # The available Maven versions are given by org.quickperf.maven.bench.projects.Maven3Version 19 | # Number of warm up before starting measures 20 | warmup.number=1 21 | 22 | # Number of measures for each Maven versions 23 | measures.number-by-maven-version = 10 24 | 25 | # Path where measures will be exported 26 | measures.export.path = ${project.build.testOutputDirectory}/maven/measures 27 | 28 | #--------------------------------------------------------------------------------- 29 | 30 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 16 | 4.0.0 17 | 18 | org.quickperf 19 | maven-test-bench 20 | pom 21 | 1.0-SNAPSHOT 22 | 23 | 24 | UTF-8 25 | 11 26 | 11 27 | 28 | 29 | 30 | 31 | 32 | src/test/resources 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | junit 41 | junit 42 | 4.13.1 43 | test 44 | 45 | 46 | org.assertj 47 | assertj-core 48 | 3.16.1 49 | test 50 | 51 | 52 | 55 | org.slf4j 56 | slf4j-log4j12 57 | 1.7.30 58 | test 59 | 60 | 61 | 62 | 63 | 64 | all 65 | 66 | true 67 | 68 | 69 | bench-tools 70 | bench-tools-maven 71 | maven-perf 72 | 73 | 74 | 75 | ci 76 | 77 | bench-tools 78 | bench-tools-maven 79 | 80 | 81 | 82 | 83 | --------------------------------------------------------------------------------