├── .gitignore ├── README.md ├── benchmark.sh ├── create-charts.py ├── pom.xml └── src └── main └── java └── com └── github └── chrishantha └── microbenchmark └── objectpool ├── AbstractStormpotObjectPoolBenchmark.java ├── CommonsPool2GenericObjectPoolBenchmark.java ├── CommonsPool2SoftReferenceObjectPoolBenchmark.java ├── CommonsPoolGenericObjectPoolBenchmark.java ├── CommonsPoolSoftReferenceObjectPoolBenchmark.java ├── FastObjectPoolBenchmark.java ├── FuriousObjectPoolBenchmark.java ├── ObjectPoolBenchmark.java ├── StackObjectPoolBenchmark.java ├── StormpotBlazePoolBenchmark.java ├── StormpotQueuePoolBenchmark.java ├── TestObjectBenchmark.java ├── ViburObjectPoolBenchmark.java └── object └── TestObject.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | 14 | #Maven Target 15 | target/ 16 | 17 | #Eclipse files 18 | .project 19 | .classpath 20 | .settings 21 | 22 | #Idea Files 23 | .idea 24 | *.iml 25 | 26 | #Generated POM file 27 | dependency-reduced-pom.xml 28 | 29 | #Benchmark Results 30 | results/ 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Object Pool Benchmarks 2 | 3 | This repository has [JMH](http://openjdk.java.net/projects/code-tools/jmh/) benchmarks for different object pool 4 | implementations. 5 | 6 | Following are the object pools used in this project. 7 | 8 | * [Commons Pool Generic Object Pool](https://commons.apache.org/proper/commons-pool/api-1.6/org/apache/commons/pool/impl/GenericObjectPool.html) 9 | * [Commons Pool Soft Reference Object Pool](https://commons.apache.org/proper/commons-pool/api-1.6/org/apache/commons/pool/impl/SoftReferenceObjectPool.html) 10 | * [Commons Pool Stack Object Pool](http://commons.apache.org/proper/commons-pool/api-1.6/org/apache/commons/pool/impl/StackObjectPool.html) 11 | * [Commons Pool 2 Generic Object Pool](https://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool2/impl/GenericObjectPool.html) 12 | * [Commons Pool 2 Soft Reference Object Pool](https://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool2/impl/SoftReferenceObjectPool.html) 13 | * [Fast Object Pool](https://github.com/DanielYWoo/fast-object-pool) 14 | * [Furious Object Pool](https://code.google.com/archive/p/furious-objectpool/) 15 | * [Stormpot Blaze Pool](http://chrisvest.github.io/stormpot/) 16 | * [Stormpot Queue Pool](http://chrisvest.github.io/stormpot/performance.html) 17 | * [Vibur Object Pool](http://www.vibur.org/vibur-object-pool/) 18 | 19 | ## Building the project 20 | 21 | Build the benchmarks using Apache Maven 22 | 23 | mvn clean package 24 | 25 | ## Running the benchmarks 26 | 27 | Run the benchmarks using the `benchmark.sh` script. I recommend following command. 28 | 29 | time ./benchmark.sh 2>&1 | tee benchmark.log 30 | 31 | This script will run the benchmarks for different number of threads and different number of object pool sizes. 32 | 33 | All parameters are defined using variables in the script. You can change the parameters by editing the script. 34 | 35 | The results of the all benchmarks will be saved in `results` directory. 36 | 37 | ## Plotting Charts from the results 38 | 39 | The results from all benchmarks can be visualized using the `create-charts.py` Python script. 40 | 41 | The script is tested only with Python 3.6. Please make sure to install seaborn module, which will also install other 42 | dependencies 43 | 44 | python3.6 -m pip install seaborn 45 | 46 | The script must be run inside the `results` directory. 47 | 48 | cd results 49 | ../create-charts.py 50 | 51 | ## License 52 | 53 | Copyright 2016 M. Isuru Tharanga Chrishantha Perera 54 | 55 | Licensed under the Apache License, Version 2.0 56 | -------------------------------------------------------------------------------- /benchmark.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # ---------------------------------------------------------------------------- 17 | # Run Benchmarks 18 | # ---------------------------------------------------------------------------- 19 | 20 | ROOT_DIR=$(dirname "$0") 21 | # Benchmark using Throughput and Sample Modes 22 | BM_MODE="thrpt,sample" 23 | # Results will be in milliseconds 24 | TIME_UNIT="ms" 25 | 26 | if [[ ! -f $ROOT_DIR/target/benchmarks.jar ]]; then 27 | echo "Please build the benchmark project" 28 | exit 1 29 | fi 30 | 31 | RESULTS_DIR=$ROOT_DIR/results 32 | mkdir -p $RESULTS_DIR 33 | 34 | forks=2 35 | warmup_iterations=5 36 | warmup_time=1 37 | iterations=5 38 | measurement_time=1 39 | # Threads are in descending order to identify issues quickly 40 | threads=(100 50 10) 41 | # "poolSize" parameter to benchmarks 42 | poolSizes="150,100,50,10" 43 | 44 | objectpools_benchmark() { 45 | echo "# Running object pool benchmark. Benchmark Mode: $BM_MODE Time Unit: $TIME_UNIT Threads: $1 Pool Sizes: $poolSizes" 46 | java -Xms2g -Xmx2g -jar $ROOT_DIR/target/benchmarks.jar -jvmArgs "-Xms4g -Xmx4g" -bm $BM_MODE -tu $TIME_UNIT \ 47 | -f $forks -wi $warmup_iterations -i $iterations -t $1 -p poolSize=$poolSizes \ 48 | -w $warmup_time -r $measurement_time -v EXTRA -prof gc \ 49 | -rff "$RESULTS_DIR/results-$1-threads.csv" -rf csv -e simple -e SoftReference 50 | } 51 | 52 | benchmark_iteration=0 53 | # Running benchmarks 54 | total=${#threads[@]} 55 | 56 | for t in ${threads[@]} 57 | do 58 | objectpools_benchmark $t 59 | benchmark_iteration=$(($benchmark_iteration + 1)) 60 | awk -v i="$benchmark_iteration" -v t="$total" \ 61 | 'BEGIN{printf "# Object Pools Benchmark Progress: %.2f%s complete\n", i/t * 100, "%"}' 62 | done 63 | -------------------------------------------------------------------------------- /create-charts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3.6 2 | # Copyright 2017 M. Isuru Tharanga Chrishantha Perera 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # ---------------------------------------------------------------------------- 17 | # Create charts from the benchmark results 18 | # ---------------------------------------------------------------------------- 19 | import glob 20 | 21 | import matplotlib.pyplot as plt 22 | import matplotlib.ticker as tkr 23 | import numpy as np 24 | import pandas as pd 25 | import seaborn as sns 26 | 27 | # This script should be run inside the results directory. 28 | 29 | sns.set_style("darkgrid") 30 | # Selected from https://matplotlib.org/users/colormaps.html#qualitative 31 | sns.set_palette(sns.color_palette("tab20", n_colors=11)) 32 | 33 | # Name for Pool Size Parameter in results 34 | param_pool_size = "Object Pool Size" 35 | 36 | # Adjust left for single plot 37 | left_adjust_single = 0.2 38 | # Adjust left for multiple plots 39 | left_adjust_multiple = 0.12 40 | 41 | 42 | def print_dataframe(df): 43 | with pd.option_context('display.max_rows', None, 'display.max_columns', None): 44 | print(df) 45 | 46 | 47 | def save_plot(df, title, filename, x="Threads", hue="Benchmark", col=param_pool_size, col_wrap=2, print_data=False, 48 | formatter=tkr.FuncFormatter(lambda y, p: "{:,}".format(y)), left=left_adjust_multiple): 49 | unit = df['Unit'].unique()[0] 50 | print("Creating chart: " + title + ", filename: " + filename + ".") 51 | if print_data: 52 | print_dataframe(df) 53 | fig, ax = plt.subplots() 54 | g = sns.factorplot(x=x, y="Score", hue=hue, col=col, data=df, kind='bar', 55 | size=5, aspect=1, col_wrap=col_wrap, legend=False) 56 | for ax in g.axes.flatten(): 57 | ax.yaxis.set_major_formatter(formatter) 58 | g.set_axis_labels(y_var="Score (" + unit + ")") 59 | plt.subplots_adjust(top=0.9, left=left) 60 | g.fig.suptitle(title) 61 | plt.legend(loc='best', title=hue, frameon=True) 62 | plt.savefig(filename) 63 | plt.clf() 64 | plt.close(fig) 65 | 66 | 67 | # Plot bar charts with error bars 68 | # Some links helped: 69 | # https://stackoverflow.com/a/42033734/1955702 70 | # https://stackoverflow.com/a/30428808/1955702 71 | # https://matplotlib.org/devdocs/gallery/api/barchart.html#sphx-glr-gallery-api-barchart-py 72 | def barplot_with_errorbars(x, y, yerr, x_values, hue_values, label, **kwargs): 73 | # x_values and benchmarks must be sorted 74 | data = kwargs.pop("data") 75 | x_values_length = len(x_values) 76 | n = np.arange(x_values_length) 77 | offsets = (np.arange(len(hue_values)) - np.arange(len(hue_values)).mean()) / (len(hue_values) + 1.) 78 | width = np.diff(offsets).mean() 79 | # Make sure x axis data is sorted 80 | data = data.sort_values(x) 81 | data_length = len(data) 82 | if data_length < x_values_length: 83 | print('WARN: Not enough data points for %s. Expected %d, Found %d' % (label, x_values_length, data_length)) 84 | for i, benchmark in enumerate(hue_values): 85 | if label == benchmark: 86 | plt.bar(n[:data_length] + offsets[i], data[y], width=width, label=label, yerr=data[yerr], capsize=2) 87 | plt.xticks(n, x_values) 88 | 89 | 90 | def save_plot_with_error_bars(df, title, filename, x="Threads", hue="Benchmark", col=param_pool_size, col_wrap=2, 91 | print_data=False, 92 | formatter=tkr.FuncFormatter(lambda y, p: "{:,}".format(y)), left=left_adjust_multiple): 93 | unit = df['Unit'].unique()[0] 94 | print("Creating chart: " + title + ", filename: " + filename + ".") 95 | if print_data: 96 | print_dataframe(df) 97 | fig, ax = plt.subplots() 98 | 99 | x_values = sorted(df[x].unique()) 100 | hue_values = sorted(df[hue].unique()) 101 | 102 | g = sns.FacetGrid(df, hue=hue, col=col, size=5, aspect=1, col_wrap=col_wrap) 103 | g = g.map_dataframe(barplot_with_errorbars, x, "Score", "Score Error (99.9%)", x_values, hue_values) 104 | for ax in g.axes.flatten(): 105 | ax.yaxis.set_major_formatter(formatter) 106 | g.set_axis_labels(y_var="Score (" + unit + ")") 107 | plt.subplots_adjust(top=0.9, left=left) 108 | g.fig.suptitle(title) 109 | plt.legend(loc='best', title=hue, frameon=True) 110 | plt.savefig(filename) 111 | plt.clf() 112 | plt.close(fig) 113 | 114 | 115 | def save_plots(df, title, filename_prefix, x="Threads", hue="Benchmark", col=param_pool_size, col_wrap=2, 116 | print_data=False, formatter=tkr.FuncFormatter(lambda y, p: "{:,}".format(y)), left=left_adjust_multiple): 117 | # Save two plots with and without error bars 118 | # Plotting errorbars with dataframe data in factorplot is not directly supported. 119 | # First plot is important and must be used to verify the accuracy of the plot with error bars. 120 | save_plot(df, title, filename_prefix + '.png', x=x, hue=hue, col=col, col_wrap=col_wrap, print_data=print_data, 121 | formatter=formatter, left=left) 122 | save_plot_with_error_bars(df, title, filename_prefix + '-with-error-bars.png', x=x, hue=hue, col=col, 123 | col_wrap=col_wrap, print_data=print_data, formatter=formatter, left=left) 124 | 125 | 126 | def save_lmplot(df, x, title, filename, print_data=False, formatter=tkr.FuncFormatter(lambda y, p: "{:,}".format(y)), 127 | left=left_adjust_single): 128 | unit = df['Unit'].unique()[0] 129 | print("Creating chart: " + title + ", filename: " + filename + ".") 130 | if print_data: 131 | print_dataframe(df) 132 | fig, ax = plt.subplots() 133 | markers_length = len(df["Benchmark"].unique()) 134 | g = sns.lmplot(data=df, x=x, y="Score", hue="Benchmark", size=6, legend=False, x_jitter=0.2, y_jitter=0.5, 135 | markers=['o', 'v', '^', '<', '>', '+', 's', 'p', '*', 'x', 'D'][:markers_length]) 136 | for ax in g.axes.flatten(): 137 | ax.yaxis.set_major_formatter(formatter) 138 | plt.subplots_adjust(top=0.9, left=left) 139 | g.set_axis_labels(y_var="Score (" + unit + ")") 140 | plt.legend(loc='upper left', frameon=True) 141 | g.fig.suptitle(title) 142 | plt.savefig(filename) 143 | plt.clf() 144 | plt.cla() 145 | plt.close(fig) 146 | 147 | 148 | def replace_benchmark_names(df): 149 | df = df.replace(r'^com\.github\.chrishantha\.microbenchmark\.objectpool\.(.*)Benchmark.useObject$', r'\1', 150 | regex=True) 151 | df = df.replace([r'^com\.github\.chrishantha\.microbenchmark\.objectpool\.(.*)Benchmark.useObject:useObject(.*)$'], 152 | [r'\1\2'], regex=True) 153 | # Profiler Details 154 | df = df.replace([r'^com\.github\.chrishantha\.microbenchmark\.objectpool\.(.*)Benchmark.useObject:(.*)$'], 155 | [r'\1\2'], regex=True) 156 | df = df.replace('com.github.chrishantha.microbenchmark.objectpool.TestObjectBenchmark.expensiveObjectCreate', 157 | 'OnDemandExpensiveObject', regex=False) 158 | df = df.replace( 159 | r'^com\.github\.chrishantha\.microbenchmark\.objectpool\.TestObjectBenchmark\.expensiveObjectCreate' + 160 | r':expensiveObjectCreate(.*)$', r'OnDemandExpensiveObject\1', regex=True) 161 | # Profiler Details 162 | df = df.replace( 163 | r'^com\.github\.chrishantha\.microbenchmark\.objectpool\.TestObjectBenchmark\.expensiveObjectCreate' + 164 | r':(.*)$', r'OnDemandExpensiveObject\1', regex=True) 165 | return df 166 | 167 | 168 | def save_percentile_plot(df, title_percentile, percentile): 169 | df_sample_percentile = df.loc[df['Benchmark'].str.endswith(percentile)] 170 | save_plot(df_sample_percentile, "Sample Time " + title_percentile + "th Percentile Comparison", 171 | "sample-time-" + percentile + "th-percentile.png", formatter=tkr.FormatStrFormatter('%.2e')) 172 | 173 | 174 | def main(): 175 | all_results = glob.glob("results-*-threads.csv") 176 | print("Creating charts using data in following files:") 177 | for file in all_results: 178 | print(file) 179 | 180 | print("\nCreating charts...\n") 181 | df = pd.concat(map(pd.read_csv, all_results), ignore_index=True) 182 | df = replace_benchmark_names(df) 183 | df.rename(columns={"Param: poolSize": param_pool_size}, inplace=True) 184 | 185 | df.to_csv('all_results.csv') 186 | 187 | # df = df[df['Benchmark'].isin(['FastObjectPool', 'StackObjectPool', 'StormpotBlazePool'])] 188 | 189 | thrpt_unit = 'ops/ms' 190 | sample_unit = 'ms/op' 191 | alloc_rate_unit = 'MB/sec' 192 | 193 | df_thrpt = df.loc[(df['Mode'] == "thrpt") & (df['Unit'] == thrpt_unit)] 194 | 195 | thrpt_mask = df_thrpt['Benchmark'].isin(['OnDemandExpensiveObject']) 196 | save_plots(df_thrpt[~thrpt_mask], "Throughput vs Threads Comparison", "thrpt-vs-threads") 197 | save_plots(df_thrpt[~thrpt_mask], "Throughput vs Pool Sizes Comparison", "thrpt-vs-pool-sizes", col="Threads", 198 | x=param_pool_size) 199 | 200 | save_lmplot(df_thrpt, "Threads", "Throughput vs Threads", "lmplot-thrpt-vs-threads.png") 201 | save_lmplot(df_thrpt[~pd.isnull(df_thrpt[param_pool_size])], param_pool_size, "Throughput vs Pool Sizes", 202 | "lmplot-thrpt-vs-pool-sizes.png") 203 | 204 | for benchmark in df_thrpt[~thrpt_mask]['Benchmark'].unique(): 205 | df_benchmark_thrpt = df_thrpt[df_thrpt['Benchmark'] == benchmark] 206 | save_plots(df_benchmark_thrpt, "Throughput vs Threads", "thrpt-" + benchmark, col="Benchmark", 207 | hue=param_pool_size, col_wrap=1, left=left_adjust_single) 208 | 209 | df_sample = df.loc[(df['Mode'] == "sample") & (df['Unit'] == sample_unit)] 210 | # Score Error (99.9%) is NaN for percentiles 211 | df_sample_without_percentiles = df_sample[~pd.isnull(df_sample['Score Error (99.9%)'])] 212 | df_sample_pools_without_percentiles = df_sample_without_percentiles[ 213 | ~pd.isnull(df_sample_without_percentiles[param_pool_size])] 214 | 215 | time_formatter = tkr.FuncFormatter(lambda y, p: "{:.2e}".format(y)) 216 | 217 | sample_mask = df_sample_without_percentiles['Benchmark'].isin(['OnDemandExpensiveObject']) 218 | save_plots(df_sample_without_percentiles[~sample_mask], "Sample Time vs Threads Comparison", 219 | "sample-time-vs-threads", formatter=time_formatter) 220 | save_plots(df_sample_pools_without_percentiles, "Sample Time vs Pool Sizes Comparison", 221 | "sample-time-vs-pool-sizes", col="Threads", x=param_pool_size, formatter=time_formatter) 222 | 223 | save_lmplot(df_sample_without_percentiles, "Threads", "Sample Time vs Threads", "lmplot-sample-vs-threads.png", 224 | formatter=time_formatter, left=left_adjust_single) 225 | save_lmplot(df_sample_pools_without_percentiles, param_pool_size, "Sample Time vs Pool Sizes", 226 | "lmplot-sample-vs-pool-sizes.png", formatter=time_formatter, left=left_adjust_single) 227 | 228 | for benchmark in df_sample_pools_without_percentiles['Benchmark'].unique(): 229 | df_benchmark_sample = df_sample_pools_without_percentiles[ 230 | df_sample_pools_without_percentiles['Benchmark'] == benchmark] 231 | save_plots(df_benchmark_sample, "Sample Time vs Threads", "sample-time-" + benchmark, col="Benchmark", 232 | hue=param_pool_size, col_wrap=1, formatter=time_formatter, left=left_adjust_single) 233 | 234 | # Filter OnDemandExpensiveObject 235 | df_sample_pools = df_sample[~df_sample['Benchmark'].str.contains('OnDemandExpensiveObject.*')] 236 | 237 | save_percentile_plot(df_sample_pools, '50', 'p0.50') 238 | save_percentile_plot(df_sample_pools, '90', 'p0.90') 239 | save_percentile_plot(df_sample_pools, '95', 'p0.95') 240 | save_percentile_plot(df_sample_pools, '99', 'p0.99') 241 | save_percentile_plot(df_sample_pools, '99.9', 'p0.999') 242 | save_percentile_plot(df_sample_pools, '99.99', 'p0.9999') 243 | save_percentile_plot(df_sample_pools, '100', 'p1.00') 244 | 245 | df_sample_percentiles = df_sample_pools.copy() 246 | df_sample_percentiles = df_sample_percentiles.loc[pd.isnull(df_sample_percentiles['Score Error (99.9%)'])] 247 | df_sample_percentiles['Pool'] = df_sample_percentiles['Benchmark'].str.extract('(?P\w+Pool)', expand=True) 248 | 249 | df_sample_pool_percentiles = df_sample_percentiles.loc[~pd.isnull(df_sample_percentiles['Pool'])] 250 | unique_pools = df_sample_pool_percentiles['Pool'].unique() 251 | for pool in unique_pools: 252 | save_plot(df_sample_percentiles.loc[df_sample_percentiles['Pool'] == pool], 253 | "Sample Time Percentiles for " + pool, "sample-time-percentiles-" + pool + ".png", 254 | formatter=time_formatter) 255 | 256 | # Save gc.alloc.rate plots 257 | df_alloc = df.loc[(df['Unit'] == alloc_rate_unit) & (df['Benchmark'].str.endswith('gc.alloc.rate'))] 258 | df_alloc = df_alloc.replace([r'^(.*)·gc.alloc.rate$'], [r'\1'], regex=True) 259 | df_thrpt_alloc = df_alloc[df_alloc['Mode'] == "thrpt"] 260 | df_thrpt_alloc_mask = df_thrpt_alloc['Benchmark'].isin(['OnDemandExpensiveObject']) 261 | save_plots(df_thrpt_alloc[~df_thrpt_alloc_mask], "GC Allocation Rate vs Threads Comparison", 262 | "gc-alloc-rate-vs-threads") 263 | save_plots(df_thrpt_alloc[~df_thrpt_alloc_mask], "GC Allocation Rate vs Pool Sizes Comparison", 264 | "gc-alloc-rate-vs-pool-sizes", col="Threads", x=param_pool_size) 265 | 266 | save_lmplot(df_thrpt_alloc, "Threads", "GC Allocation Rate vs Threads", "lmplot-gc-alloc-rate-vs-threads.png") 267 | save_lmplot(df_thrpt_alloc[~pd.isnull(df_thrpt_alloc[param_pool_size])], param_pool_size, 268 | "GC Allocation Rate vs Pool Sizes", "lmplot-gc-alloc-rate-vs-pool-sizes.png") 269 | 270 | for benchmark in df_thrpt_alloc[~df_thrpt_alloc_mask]['Benchmark'].unique(): 271 | df_benchmark_thrpt_alloc = df_thrpt_alloc[df_thrpt_alloc['Benchmark'] == benchmark] 272 | save_plots(df_benchmark_thrpt_alloc, "GC Allocation Rate vs Threads", "gc-alloc-rate-" + benchmark, 273 | col="Benchmark", hue=param_pool_size, col_wrap=1, formatter=time_formatter, left=left_adjust_single) 274 | 275 | print("Done") 276 | 277 | 278 | if __name__ == '__main__': 279 | main() 280 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 4.0.0 19 | 20 | com.github.chrishantha.microbenchmark 21 | object-pool-benchmarks 22 | 1.1.1-SNAPSHOT 23 | jar 24 | 25 | JMH benchmark: Object Pools 26 | Benchmarking Object Pool implementations in Java 27 | 2016 28 | 29 | 30 | 31 | The Apache Software License, Version 2.0 32 | http://www.apache.org/licenses/LICENSE-2.0.txt 33 | repo 34 | 35 | 36 | 37 | 38 | https://github.com/chrishantha/object-pool-benchmarks.git 39 | scm:git:https://github.com/chrishantha/object-pool-benchmarks.git 40 | scm:git:https://github.com/chrishantha/object-pool-benchmarks.git 41 | HEAD 42 | 43 | 44 | 45 | 46 | org.openjdk.jmh 47 | jmh-core 48 | ${jmh.version} 49 | 50 | 51 | org.openjdk.jmh 52 | jmh-generator-annprocess 53 | ${jmh.version} 54 | provided 55 | 56 | 57 | commons-pool 58 | commons-pool 59 | ${commons.pool.version} 60 | 61 | 62 | org.apache.commons 63 | commons-pool2 64 | ${commons.pool2.version} 65 | 66 | 67 | nf.fr.eraasoft 68 | objectpool 69 | ${eraasoft.objectpool.version} 70 | 71 | 72 | cn.danielw 73 | fast-object-pool 74 | ${fast.object.pool.version} 75 | 76 | 77 | org.vibur 78 | vibur-object-pool 79 | ${vibur.object.pool.version} 80 | 81 | 82 | com.github.chrisvest 83 | stormpot 84 | ${stormpot.version} 85 | 86 | 87 | 88 | 89 | 90 | 91 | org.apache.maven.plugins 92 | maven-compiler-plugin 93 | 3.7.0 94 | 95 | ${javac.target} 96 | ${javac.target} 97 | ${javac.target} 98 | 99 | 100 | 101 | org.apache.maven.plugins 102 | maven-shade-plugin 103 | 3.1.0 104 | 105 | 106 | package 107 | 108 | shade 109 | 110 | 111 | ${uberjar.name} 112 | 113 | 114 | org.openjdk.jmh.Main 115 | 116 | 117 | 118 | 119 | 123 | *:* 124 | 125 | META-INF/*.SF 126 | META-INF/*.DSA 127 | META-INF/*.RSA 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | maven-clean-plugin 140 | 3.0.0 141 | 142 | 143 | maven-deploy-plugin 144 | 2.8.2 145 | 146 | 147 | maven-install-plugin 148 | 2.5.2 149 | 150 | 151 | maven-jar-plugin 152 | 3.0.2 153 | 154 | 155 | maven-javadoc-plugin 156 | 2.10.4 157 | 158 | 159 | maven-resources-plugin 160 | 3.0.2 161 | 162 | 163 | maven-site-plugin 164 | 3.6 165 | 166 | 167 | maven-source-plugin 168 | 3.0.1 169 | 170 | 171 | maven-surefire-plugin 172 | 2.20.1 173 | 174 | 175 | 176 | 177 | 178 | 179 | UTF-8 180 | 1.20 181 | 1.8 182 | benchmarks 183 | 184 | 1.6 185 | 2.5.0 186 | 1.1.2 187 | 2.1.0 188 | 22.0 189 | 2.4.1 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/AbstractStormpotObjectPoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import com.github.chrishantha.microbenchmark.objectpool.object.TestObject; 19 | import org.openjdk.jmh.infra.Blackhole; 20 | import stormpot.Allocator; 21 | import stormpot.Config; 22 | import stormpot.LifecycledPool; 23 | import stormpot.Poolable; 24 | import stormpot.Slot; 25 | import stormpot.Timeout; 26 | 27 | import java.util.concurrent.TimeUnit; 28 | 29 | /** 30 | * Benchmark for Stormpot. Code is at https://github.com/chrisvest/stormpot 31 | */ 32 | public abstract class AbstractStormpotObjectPoolBenchmark extends ObjectPoolBenchmark { 33 | 34 | private LifecycledPool objectPool; 35 | 36 | private final Timeout timeout = new Timeout(2, TimeUnit.MINUTES); 37 | 38 | public static class PoolableTestObject extends TestObject implements Poolable { 39 | 40 | private final Slot slot; 41 | 42 | public PoolableTestObject(Slot slot) { 43 | super(true); 44 | this.slot = slot; 45 | } 46 | 47 | @Override 48 | public void release() { 49 | slot.release(this); 50 | } 51 | } 52 | 53 | @Override 54 | public void setupObjectPool() { 55 | Allocator allocator = new Allocator() { 56 | 57 | @Override 58 | public PoolableTestObject allocate(Slot slot) throws Exception { 59 | return new PoolableTestObject(slot); 60 | } 61 | 62 | @Override 63 | public void deallocate(PoolableTestObject poolable) throws Exception { 64 | 65 | } 66 | }; 67 | 68 | Config config = new Config().setAllocator(allocator); 69 | config.setSize(poolSize); 70 | objectPool = buildPool(config); 71 | } 72 | 73 | protected abstract LifecycledPool buildPool(Config config); 74 | 75 | @Override 76 | public void tearDownObjectPool() throws Exception { 77 | objectPool.shutdown().await(timeout); 78 | } 79 | 80 | @Override 81 | public PoolableTestObject borrowObject() throws Exception { 82 | return objectPool.claim(timeout); 83 | } 84 | 85 | @Override 86 | public void releaseObject(PoolableTestObject object) throws Exception { 87 | object.release(); 88 | } 89 | 90 | @Override 91 | public void useObject(PoolableTestObject object, Blackhole blackhole) { 92 | blackhole.consume(object.getData()); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/CommonsPool2GenericObjectPoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import com.github.chrishantha.microbenchmark.objectpool.object.TestObject; 19 | import org.apache.commons.pool2.BasePooledObjectFactory; 20 | import org.apache.commons.pool2.PooledObject; 21 | import org.apache.commons.pool2.impl.DefaultPooledObject; 22 | import org.apache.commons.pool2.impl.GenericObjectPool; 23 | import org.apache.commons.pool2.impl.GenericObjectPoolConfig; 24 | import org.openjdk.jmh.infra.Blackhole; 25 | 26 | /** 27 | * Benchmark for {@link GenericObjectPool} in Apache Commons Pool2 28 | */ 29 | public class CommonsPool2GenericObjectPoolBenchmark extends ObjectPoolBenchmark { 30 | 31 | private GenericObjectPool objectPool; 32 | 33 | @Override 34 | public void setupObjectPool() { 35 | GenericObjectPoolConfig config = new GenericObjectPoolConfig(); 36 | config.setMaxTotal(poolSize); 37 | 38 | objectPool = new GenericObjectPool<>(new BasePooledObjectFactory() { 39 | @Override 40 | public TestObject create() throws Exception { 41 | return new TestObject(true); 42 | } 43 | 44 | @Override 45 | public PooledObject wrap(TestObject testObject) { 46 | return new DefaultPooledObject<>(testObject); 47 | } 48 | }, config); 49 | } 50 | 51 | @Override 52 | public void tearDownObjectPool() throws Exception { 53 | objectPool.close(); 54 | } 55 | 56 | @Override 57 | public TestObject borrowObject() throws Exception { 58 | return objectPool.borrowObject(); 59 | } 60 | 61 | @Override 62 | public void releaseObject(TestObject object) throws Exception { 63 | objectPool.returnObject(object); 64 | } 65 | 66 | @Override 67 | public void useObject(TestObject object, Blackhole blackhole) { 68 | blackhole.consume(object.getData()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/CommonsPool2SoftReferenceObjectPoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import com.github.chrishantha.microbenchmark.objectpool.object.TestObject; 19 | import org.apache.commons.pool2.BasePooledObjectFactory; 20 | import org.apache.commons.pool2.PooledObject; 21 | import org.apache.commons.pool2.impl.DefaultPooledObject; 22 | import org.apache.commons.pool2.impl.SoftReferenceObjectPool; 23 | import org.openjdk.jmh.infra.Blackhole; 24 | 25 | /** 26 | * Benchmark for {@link SoftReferenceObjectPool} in Apache Commons Pool2 27 | */ 28 | public class CommonsPool2SoftReferenceObjectPoolBenchmark extends ObjectPoolBenchmark { 29 | 30 | private SoftReferenceObjectPool objectPool; 31 | 32 | @Override 33 | public void setupObjectPool() { 34 | objectPool = new SoftReferenceObjectPool<>(new BasePooledObjectFactory() { 35 | @Override 36 | public TestObject create() throws Exception { 37 | return new TestObject(true); 38 | } 39 | 40 | @Override 41 | public PooledObject wrap(TestObject testObject) { 42 | return new DefaultPooledObject<>(testObject); 43 | } 44 | }); 45 | } 46 | 47 | @Override 48 | public void tearDownObjectPool() throws Exception { 49 | objectPool.close(); 50 | } 51 | 52 | @Override 53 | public TestObject borrowObject() throws Exception { 54 | return objectPool.borrowObject(); 55 | } 56 | 57 | @Override 58 | public void releaseObject(TestObject object) throws Exception { 59 | objectPool.returnObject(object); 60 | } 61 | 62 | @Override 63 | public void useObject(TestObject object, Blackhole blackhole) { 64 | blackhole.consume(object.getData()); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/CommonsPoolGenericObjectPoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import com.github.chrishantha.microbenchmark.objectpool.object.TestObject; 19 | import org.apache.commons.pool.BasePoolableObjectFactory; 20 | import org.apache.commons.pool.impl.GenericObjectPool; 21 | import org.openjdk.jmh.infra.Blackhole; 22 | 23 | /** 24 | * Benchmark for {@link GenericObjectPool} in Apache Commons Pool1 25 | */ 26 | public class CommonsPoolGenericObjectPoolBenchmark extends ObjectPoolBenchmark { 27 | 28 | private GenericObjectPool objectPool; 29 | 30 | @Override 31 | public void setupObjectPool() { 32 | objectPool = new GenericObjectPool<>(new BasePoolableObjectFactory() { 33 | @Override 34 | public TestObject makeObject() throws Exception { 35 | return new TestObject(true); 36 | } 37 | }, poolSize); 38 | } 39 | 40 | @Override 41 | public void tearDownObjectPool() throws Exception { 42 | objectPool.close(); 43 | } 44 | 45 | @Override 46 | public TestObject borrowObject() throws Exception { 47 | return objectPool.borrowObject(); 48 | } 49 | 50 | @Override 51 | public void releaseObject(TestObject object) throws Exception { 52 | objectPool.returnObject(object); 53 | } 54 | 55 | @Override 56 | public void useObject(TestObject object, Blackhole blackhole) { 57 | blackhole.consume(object.getData()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/CommonsPoolSoftReferenceObjectPoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import com.github.chrishantha.microbenchmark.objectpool.object.TestObject; 19 | import org.apache.commons.pool.BasePoolableObjectFactory; 20 | import org.apache.commons.pool.impl.SoftReferenceObjectPool; 21 | import org.openjdk.jmh.infra.Blackhole; 22 | 23 | /** 24 | * Benchmark for {@link SoftReferenceObjectPool} in Apache Commons Pool1 25 | */ 26 | public class CommonsPoolSoftReferenceObjectPoolBenchmark extends ObjectPoolBenchmark { 27 | 28 | private SoftReferenceObjectPool objectPool; 29 | 30 | @Override 31 | public void setupObjectPool() { 32 | objectPool = new SoftReferenceObjectPool<>(new BasePoolableObjectFactory() { 33 | @Override 34 | public TestObject makeObject() throws Exception { 35 | return new TestObject(true); 36 | } 37 | }); 38 | } 39 | 40 | @Override 41 | public void tearDownObjectPool() throws Exception { 42 | objectPool.close(); 43 | } 44 | 45 | @Override 46 | public TestObject borrowObject() throws Exception { 47 | return objectPool.borrowObject(); 48 | } 49 | 50 | @Override 51 | public void releaseObject(TestObject object) throws Exception { 52 | objectPool.returnObject(object); 53 | } 54 | 55 | @Override 56 | public void useObject(TestObject object, Blackhole blackhole) { 57 | blackhole.consume(object.getData()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/FastObjectPoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import cn.danielw.fop.ObjectFactory; 19 | import cn.danielw.fop.ObjectPool; 20 | import cn.danielw.fop.PoolConfig; 21 | import cn.danielw.fop.Poolable; 22 | import com.github.chrishantha.microbenchmark.objectpool.object.TestObject; 23 | import org.openjdk.jmh.infra.Blackhole; 24 | 25 | /** 26 | * Benchmark for Fast-Object-Pool. Code is at https://github.com/DanielYWoo/fast-object-pool 27 | */ 28 | public class FastObjectPoolBenchmark extends ObjectPoolBenchmark> { 29 | 30 | private ObjectPool objectPool; 31 | 32 | @Override 33 | public void setupObjectPool() { 34 | PoolConfig config = new PoolConfig(); 35 | config.setMaxSize(poolSize); 36 | objectPool = new ObjectPool<>(config, new ObjectFactory() { 37 | @Override 38 | public TestObject create() { 39 | return new TestObject(true); 40 | } 41 | 42 | @Override 43 | public void destroy(TestObject o) { 44 | } 45 | 46 | @Override 47 | public boolean validate(TestObject o) { 48 | return true; 49 | } 50 | }); 51 | } 52 | 53 | @Override 54 | public void tearDownObjectPool() throws Exception { 55 | objectPool.shutdown(); 56 | } 57 | 58 | @Override 59 | public Poolable borrowObject() throws Exception { 60 | return objectPool.borrowObject(); 61 | } 62 | 63 | @Override 64 | public void releaseObject(Poolable object) throws Exception { 65 | objectPool.returnObject(object); 66 | } 67 | 68 | @Override 69 | public void useObject(Poolable object, Blackhole blackhole) { 70 | blackhole.consume(object.getObject().getData()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/FuriousObjectPoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | 19 | import com.github.chrishantha.microbenchmark.objectpool.object.TestObject; 20 | import nf.fr.eraasoft.pool.ObjectPool; 21 | import nf.fr.eraasoft.pool.PoolException; 22 | import nf.fr.eraasoft.pool.PoolSettings; 23 | import nf.fr.eraasoft.pool.PoolableObjectBase; 24 | import nf.fr.eraasoft.pool.impl.PoolControler; 25 | import org.openjdk.jmh.infra.Blackhole; 26 | 27 | /** 28 | * Benchmark for Furious-Object-Pool. Code is at https://code.google.com/archive/p/furious-objectpool/ 29 | */ 30 | public class FuriousObjectPoolBenchmark extends ObjectPoolBenchmark { 31 | 32 | private ObjectPool objectPool; 33 | 34 | @Override 35 | public void setupObjectPool() { 36 | PoolSettings settings = new PoolSettings<>(new PoolableObjectBase() { 37 | @Override 38 | public TestObject make() throws PoolException { 39 | return new TestObject(true); 40 | } 41 | 42 | @Override 43 | public void activate(TestObject testObject) throws PoolException { 44 | 45 | } 46 | }); 47 | settings.min(0).max(poolSize); 48 | objectPool = settings.pool(); 49 | } 50 | 51 | @Override 52 | public void tearDownObjectPool() throws Exception { 53 | PoolControler.shutdown(); 54 | } 55 | 56 | @Override 57 | public TestObject borrowObject() throws Exception { 58 | return objectPool.getObj(); 59 | } 60 | 61 | @Override 62 | public void releaseObject(TestObject object) throws Exception { 63 | objectPool.returnObj(object); 64 | } 65 | 66 | @Override 67 | public void useObject(TestObject object, Blackhole blackhole) { 68 | blackhole.consume(object.getData()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/ObjectPoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import org.openjdk.jmh.annotations.Benchmark; 19 | import org.openjdk.jmh.annotations.BenchmarkMode; 20 | import org.openjdk.jmh.annotations.CompilerControl; 21 | import org.openjdk.jmh.annotations.Fork; 22 | import org.openjdk.jmh.annotations.Measurement; 23 | import org.openjdk.jmh.annotations.Mode; 24 | import org.openjdk.jmh.annotations.Param; 25 | import org.openjdk.jmh.annotations.Scope; 26 | import org.openjdk.jmh.annotations.Setup; 27 | import org.openjdk.jmh.annotations.State; 28 | import org.openjdk.jmh.annotations.TearDown; 29 | import org.openjdk.jmh.annotations.Threads; 30 | import org.openjdk.jmh.annotations.Warmup; 31 | import org.openjdk.jmh.infra.Blackhole; 32 | 33 | @BenchmarkMode(Mode.Throughput) 34 | @Warmup(iterations = 5) 35 | @Measurement(iterations = 5) 36 | @Fork(1) 37 | @Threads(10) 38 | @State(Scope.Benchmark) 39 | public abstract class ObjectPoolBenchmark { 40 | 41 | @Param({"100"}) 42 | protected int poolSize; 43 | 44 | @Setup 45 | public abstract void setupObjectPool(); 46 | 47 | @TearDown 48 | public abstract void tearDownObjectPool() throws Exception; 49 | 50 | @CompilerControl(CompilerControl.Mode.INLINE) 51 | protected abstract T borrowObject() throws Exception; 52 | 53 | @CompilerControl(CompilerControl.Mode.INLINE) 54 | protected abstract void releaseObject(T object) throws Exception; 55 | 56 | @CompilerControl(CompilerControl.Mode.INLINE) 57 | protected abstract void useObject(T object, Blackhole blackhole); 58 | 59 | @Benchmark 60 | public void useObject(Blackhole blackhole) throws Exception { 61 | T object = borrowObject(); 62 | Blackhole.consumeCPU(1_000L); 63 | useObject(object, blackhole); 64 | releaseObject(object); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/StackObjectPoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import com.github.chrishantha.microbenchmark.objectpool.object.TestObject; 19 | import org.apache.commons.pool.BasePoolableObjectFactory; 20 | import org.apache.commons.pool.impl.StackObjectPool; 21 | import org.openjdk.jmh.infra.Blackhole; 22 | 23 | /** 24 | * Benchmark for {@link StackObjectPool} 25 | */ 26 | public class StackObjectPoolBenchmark extends ObjectPoolBenchmark { 27 | 28 | private StackObjectPool objectPool; 29 | 30 | @Override 31 | public void setupObjectPool() { 32 | objectPool = new StackObjectPool<>(new BasePoolableObjectFactory() { 33 | @Override 34 | public TestObject makeObject() throws Exception { 35 | return new TestObject(true); 36 | } 37 | }, poolSize, poolSize); 38 | } 39 | 40 | @Override 41 | public void tearDownObjectPool() throws Exception { 42 | objectPool.close(); 43 | } 44 | 45 | @Override 46 | public TestObject borrowObject() throws Exception { 47 | return objectPool.borrowObject(); 48 | } 49 | 50 | @Override 51 | public void releaseObject(TestObject object) throws Exception { 52 | objectPool.returnObject(object); 53 | } 54 | 55 | @Override 56 | public void useObject(TestObject object, Blackhole blackhole) { 57 | blackhole.consume(object.getData()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/StormpotBlazePoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import stormpot.BlazePool; 19 | import stormpot.Config; 20 | import stormpot.LifecycledPool; 21 | 22 | /** 23 | * Benchmark for {@link BlazePool} 24 | */ 25 | public class StormpotBlazePoolBenchmark extends AbstractStormpotObjectPoolBenchmark { 26 | 27 | @Override 28 | protected LifecycledPool buildPool(Config config) { 29 | return new BlazePool<>(config); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/StormpotQueuePoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import stormpot.Config; 19 | import stormpot.LifecycledPool; 20 | import stormpot.QueuePool; 21 | 22 | /** 23 | * Benchmark for {@link QueuePool} 24 | */ 25 | public class StormpotQueuePoolBenchmark extends AbstractStormpotObjectPoolBenchmark { 26 | 27 | @Override 28 | protected LifecycledPool buildPool(Config config) { 29 | return new QueuePool<>(config); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/TestObjectBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import com.github.chrishantha.microbenchmark.objectpool.object.TestObject; 19 | import org.openjdk.jmh.annotations.Benchmark; 20 | import org.openjdk.jmh.annotations.BenchmarkMode; 21 | import org.openjdk.jmh.annotations.Fork; 22 | import org.openjdk.jmh.annotations.Measurement; 23 | import org.openjdk.jmh.annotations.Mode; 24 | import org.openjdk.jmh.annotations.Threads; 25 | import org.openjdk.jmh.annotations.Warmup; 26 | import org.openjdk.jmh.infra.Blackhole; 27 | 28 | /** 29 | * Benchmark object creation 30 | */ 31 | @BenchmarkMode(Mode.Throughput) 32 | @Warmup(iterations = 5) 33 | @Measurement(iterations = 5) 34 | @Fork(1) 35 | @Threads(10) 36 | public class TestObjectBenchmark { 37 | 38 | @Benchmark 39 | public void simpleObjectCreate(Blackhole blackhole) { 40 | TestObject testObject = new TestObject(false); 41 | blackhole.consume(testObject.getData()); 42 | } 43 | 44 | @Benchmark 45 | public void expensiveObjectCreate(Blackhole blackhole) { 46 | TestObject testObject = new TestObject(true); 47 | // Consume the CPU for same number of tokens as in ObjectPoolBenchmark class 48 | Blackhole.consumeCPU(1_000L); 49 | blackhole.consume(testObject.getData()); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/ViburObjectPoolBenchmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 M. Isuru Tharanga Chrishantha Perera 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.github.chrishantha.microbenchmark.objectpool; 17 | 18 | import com.github.chrishantha.microbenchmark.objectpool.object.TestObject; 19 | import org.openjdk.jmh.infra.Blackhole; 20 | import org.vibur.objectpool.ConcurrentPool; 21 | import org.vibur.objectpool.PoolObjectFactory; 22 | import org.vibur.objectpool.util.ConcurrentLinkedQueueCollection; 23 | 24 | /** 25 | * Benchmark for Vibur Object Pool. Code is at https://github.com/vibur/vibur-object-pool/ 26 | */ 27 | public class ViburObjectPoolBenchmark extends ObjectPoolBenchmark { 28 | 29 | private ConcurrentPool objectPool; 30 | 31 | @Override 32 | public void setupObjectPool() { 33 | objectPool = new ConcurrentPool<>(new ConcurrentLinkedQueueCollection<>(), new PoolObjectFactory() { 34 | 35 | @Override 36 | public TestObject create() { 37 | return new TestObject(true); 38 | } 39 | 40 | @Override 41 | public boolean readyToTake(TestObject obj) { 42 | return true; 43 | } 44 | 45 | @Override 46 | public boolean readyToRestore(TestObject obj) { 47 | return true; 48 | } 49 | 50 | @Override 51 | public void destroy(TestObject obj) { 52 | 53 | } 54 | }, 1, poolSize, false); 55 | 56 | } 57 | 58 | @Override 59 | public void tearDownObjectPool() throws Exception { 60 | objectPool.close(); 61 | } 62 | 63 | @Override 64 | public TestObject borrowObject() throws Exception { 65 | return objectPool.take(); 66 | } 67 | 68 | @Override 69 | public void releaseObject(TestObject object) throws Exception { 70 | objectPool.restore(object); 71 | } 72 | 73 | @Override 74 | public void useObject(TestObject object, Blackhole blackhole) { 75 | blackhole.consume(object.getData()); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/github/chrishantha/microbenchmark/objectpool/object/TestObject.java: -------------------------------------------------------------------------------- 1 | package com.github.chrishantha.microbenchmark.objectpool.object; 2 | 3 | import org.openjdk.jmh.infra.Blackhole; 4 | 5 | /** 6 | * Test Object to be used in Object Pools 7 | */ 8 | public class TestObject { 9 | 10 | private String data = TestObject.class.getName(); 11 | 12 | public TestObject(boolean expensive) { 13 | if (expensive) { 14 | Blackhole.consumeCPU(10_000L); 15 | StringBuilder stringBuilder = new StringBuilder(); 16 | for (int i = 0; i < 10_000L; i++) { 17 | for (int j = '0'; j <= 'z'; j++) { 18 | stringBuilder.append((char) j); 19 | } 20 | } 21 | data = stringBuilder.toString(); 22 | } 23 | } 24 | 25 | 26 | public String getData() { 27 | return data; 28 | } 29 | 30 | } 31 | --------------------------------------------------------------------------------