<div dir="ltr">Hi Ken,<div><br></div><div>Of course it is :-)<div>If you haven't done it yet, I highly recommend you go through all the <a href="https://github.com/openjdk/jmh/tree/master/jmh-samples">JMH samples</a>.</div><div>This one in your case: <a href="https://github.com/openjdk/jmh/blob/master/jmh-samples/src/main/java/org/openjdk/jmh/samples/JMHSample_03_States.java">https://github.com/openjdk/jmh/blob/master/jmh-samples/src/main/java/org/openjdk/jmh/samples/JMHSample_03_States.java</a></div><div>They are really useful to understand how it works.</div><div><br></div><div>That said, you can have a state with scope = Benchmark (@State(Scope.Benchmark))</div><div>It will be executed only one time at the beginning.</div><div><br></div><div>You also have @Setup that you can put on a method.</div><div>However, it will be minimally called for every trial.</div><div><br></div></div><div>I see something like this:</div><div><div style="background-color:rgb(30,31,34);color:rgb(188,190,196)"><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><span style="color:rgb(102,166,255)">@Fork</span>(<span style="color:rgb(102,166,255)">2</span>)<br><span style="color:rgb(102,166,255)">@Warmup</span>(<span style="color:rgb(102,166,255);font-weight:bold">iterations </span>= <span style="color:rgb(102,166,255)">10</span>, <span style="color:rgb(102,166,255);font-weight:bold">time </span>= <span style="color:rgb(102,166,255)">1</span>)<br><span style="color:rgb(102,166,255)">@Measurement</span>(<span style="color:rgb(102,166,255);font-weight:bold">iterations </span>= <span style="color:rgb(102,166,255)">4</span>, <span style="color:rgb(102,166,255);font-weight:bold">time </span>= <span style="color:rgb(102,166,255)">1</span>)<br><span style="color:rgb(102,166,255)">@BenchmarkMode</span>(Mode.<span style="color:rgb(130,142,186);font-weight:bold">AverageTime</span>)<br><span style="color:rgb(102,166,255)">@OutputTimeUnit</span>(TimeUnit.<span style="color:rgb(130,142,186);font-weight:bold">NANOSECONDS</span>)<br><span style="color:rgb(102,166,255)">@State</span>(Scope.<span style="color:rgb(130,142,186);font-weight:bold">Thread</span>)<br><span style="color:rgb(89,124,194)">public class </span>KenBenchmark {<br><br>    <span style="color:rgb(89,124,194)">private static final int </span><span style="color:rgb(130,142,186);font-weight:bold">A_NUMBER_BIG_ENOUGH_TO_PREVENT_RESIZE </span>= <span style="color:rgb(102,166,255)">1_000_000</span>;<br>    <span style="color:rgb(89,124,194)">private static </span>List<String> <span style="color:rgb(130,142,186);font-weight:bold">dataArray </span>= Arrays.<span style="font-style:italic">asList</span>(<span style="color:rgb(148,144,127);font-weight:bold">"a"</span>, <span style="color:rgb(148,144,127);font-weight:bold">"b"</span>, <span style="color:rgb(148,144,127);font-weight:bold">"..."</span>);<br>    <span style="color:rgb(89,124,194)">private </span>ArrayDeque<String> <span style="color:rgb(130,142,186);font-weight:bold">arrayDeque</span>;<br><br>    <span style="color:rgb(102,166,255)">@Setup</span>(Level.<span style="color:rgb(130,142,186);font-weight:bold">Iteration</span>)<br>    <span style="color:rgb(89,124,194)">public void </span><span style="color:rgb(217,175,108)">init</span>() {<br>        <span style="color:rgb(130,142,186);font-weight:bold">arrayDeque </span>= <span style="color:rgb(89,124,194)">new </span>ArrayDeque<>(<span style="color:rgb(130,142,186);font-weight:bold">dataArray</span>.size() + <span style="color:rgb(130,142,186);font-weight:bold">A_NUMBER_BIG_ENOUGH_TO_PREVENT_RESIZE</span>);<br>        <span style="color:rgb(130,142,186);font-weight:bold">arrayDeque</span>.addAll(<span style="color:rgb(130,142,186);font-weight:bold">dataArray</span>);<br>    }<br><br>    <span style="color:rgb(102,166,255)">@Benchmark<br></span><span style="color:rgb(102,166,255)">    </span><span style="color:rgb(89,124,194)">public void </span><span style="color:rgb(217,175,108)">addFirst</span>() {<br>        <span style="color:rgb(130,142,186);font-weight:bold">arrayDeque</span>.addFirst(<span style="color:rgb(148,144,127);font-weight:bold">"Dawson College"</span>);<br>    }<br><br>}</pre></div></div><div>Regards,</div><div>Henri</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 24 Jul 2024 at 23:01, Kenneth Fogel <<a href="mailto:kfogel@dawsoncollege.qc.ca">kfogel@dawsoncollege.qc.ca</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="msg1300453022548937439">





<div lang="EN-CA" style="overflow-wrap: break-word;">
<div class="m_1300453022548937439WordSection1">
<p class="MsoNormal"><span lang="EN-US">Hi everyone,<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">Thank you for allowing me to join this mailing list.<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">My name is Ken Fogel and I was a Computer Science instructor at Dawson College in Montreal for 31 years, having retired 3 years ago. I was chairperson for 25 of those years and led the change from COBOL to Java in 2000.
 I am a Java Champion and organize, with fellow JCs, the JChampions Conference. I also sit on the JCP Executive Committee. Like all retired academics I wrote a book entitle Transitioning to Java from Packt for devs who need to move to Java from any other language.
 Finally, I still get to present at conferences, and it is work I am doing with the JMH for JavaLand that has led me to this mailing list.<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">Some years ago, I wrote a program that demonstrated the relative differences between the various collection in Java. The program worked as required, made for a good lecture, and proved why no one should use a LinkedList
 (this remark is meant to be funny and true). A little over a year ago I discovered the jmh and created a version of my program using it. Unfortunately, I could not run the benchmarks as I did in my version as the results were presented in a Swing table but
 that is not the issue I am having. Here is the measurement code for adding an element at the end of an ArrayList from my pre-jmh code:<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">for (int y = 0; y < REPETITIONS; ++y) {<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">         arrayDeque = new ArrayDeque<>();<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">         for (int x = 0; x < SIZE; ++x) {<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">                arrayDeque.add(dataArray[x]);<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">         }<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">         startTime = System.nanoTime();<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">         arrayDeque.addFirst("Dawson College");<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">         endTime = System.nanoTime() - startTime;<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">         runningTotal += endTime;<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">  }<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">The dataArray is a simple array of 10000 strings. I use the same set of words for every test. This worked well enough. The actual time to insert was calculated after a new ArrayList was created and populated for every
 repetition. This was necessary because had I created a new copy with :<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">arrayDeque = new ArrayDeque<>(Arrays.asList(dataArray));<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">I end up with an ArrayDeques that is the same size as the Array I am initializing it with. The problem is that this ArrayDeque has no slack space so it must immediately grow, As I am interested in the performance when
 there is slack space, I create the ArrayDeque in a loop. This results in the ArrayDeque having slack space.<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">When I moved to the jmh I could not find a way to create and initialize the ArrayList as @Benchmark timed the entire method’s code.  I thought I figured it out by using an inner static class annotated with @State. It
 did not work. I discovered that the ArrayList was being initialized for each iteration but, and this was a very big but, I discovered after reading numerous StackOverflows and then looking at the jmh source code that iterations that were not set to  “Mode.SingleShotTime”
 executed the @Benchmark method a random number of times per iteration. This would be fine except that the @State class/method was only invoked once per iteration and not every time the method was executed as I required.
<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">If you have read this far you can probably guess my question. Is it possible to execute code that is part of a @Benchmark method but that is not included in the timing. Is there or could there be an annotation for this
 rather than use SingleShotTime and then have a large value for measurementIterations . Something like:<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">@Benchmark<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">public void do10InsertLastElementArrayList(Blackhole blackhole) {<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><b><span lang="EN-US">       @IgnoreOn<u></u><u></u></span></b></p>
<p class="MsoNormal"><b><span lang="EN-US">         Deque <String> arrayDeque = new ArrayDeque<>();<u></u><u></u></span></b></p>
<p class="MsoNormal"><b><span lang="EN-US">         for (int x = 0; x < SIZE; ++x) {<u></u><u></u></span></b></p>
<p class="MsoNormal"><b><span lang="EN-US">                arrayDeque.add(dataArray[x]);<u></u><u></u></span></b></p>
<p class="MsoNormal"><b><span lang="EN-US">         }<u></u><u></u></span></b></p>
<p class="MsoNormal"><b><span lang="EN-US">        @IgnoreOff<u></u><u></u></span></b></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">      arrayDeque.add("Dawson College");<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">      blackhole.consume(arrayDeque); // Not certain I need this<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">        <u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">    }<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">If the operation does not mutate anything then there is no issue. It is when I mutate something that I need to restore the state of variables to before the mutation every time and not have this included in the timing
 measurement.<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">Thank you for your patience in reading this and for any assistance you can provide.
<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
<p class="MsoNormal"><span lang="EN-US">Ken<u></u><u></u></span></p>
<p class="MsoNormal"><span lang="EN-US"><u></u> <u></u></span></p>
</div>
</div>

</div></blockquote></div>