cchesser / java-perf-workshop Goto Github PK
View Code? Open in Web Editor NEWGuided walkthrough to understand the performance aspects of a Java web service
Home Page: https://jvmperf.net/
License: Apache License 2.0
Guided walkthrough to understand the performance aspects of a Java web service
Home Page: https://jvmperf.net/
License: Apache License 2.0
It is common where Java workloads are within a Linux container, and they aren't aware of all the sizing that can occur which feeds into the overall container size. Furthermore, using some of the available tooling requires making adaptations to use these and connect it to the container.
Play around with the RConsole from VisualVM and see what sort of reports we could build.
One of the things we might be able to try is replicating https://jvmperf.net/docs/memory/gc/#parsing-the-log - if the stringr pacakge is available.
Another option is maybe use R to create the same distribution report of items -> tags count.
Add some sort of navigation to the workshop that leads to the next page, the pages are sorted by weight already but that won't guarantee someone will know where to go next, something like this should work:
{{/*
Iterates over the set of pages in the current section, locating the current page and creating a link with the contents of the next page.
*/}}
{{ $scratch := newScratch }}
{{ range $index, $element := $.Page.CurrentSection.Pages.ByWeight }}
{{ if (eq $.Page.Params.weight .Params.weight) }}
{{ $scratch.Set "nextIndex" (add 1 $index)}}
{{ end }}
{{ end }}
{{ with index $.Page.CurrentSection.Pages.ByWeight ($scratch.Get "nextIndex") }}
<div class="card mb-3" style="width: 80%;">
<div class="card-header text-white border-info bg-info">
<i class="fas fa-arrow-alt-circle-right"></i> Up Next</div>
<div class="card-body">
<p class="card-text">{{ $.Inner }}</p>
<a href="{{ .Permalink }}">{{ .Params.title | humanize | title }}</a></i>
</div>
</div>
{{ end}}
Docker recently updated their subscription terms, which mostly affects large businesses. We could keep its reference (free for personal use0, but it would make sense to update it to some recently identified alternatives that may be applicable to others who will be exposed to this difference.
Needing to update the GitHub action configuration, which is dated on the Hugo / action configuration.
With the the ZGC in Java 11 preview, and now available in Java 13, we should get this updated to include this type of content.
The JMC profile we provide was created for Oracle JVMs:
When using an OpenJDK JVM , the Template Manager will be smart enough to not let us select the profile provided by the guide. You can import it and select apply, BUT the resulting dropdown doesn't let you end up choosing that profile, so at a quick glance it seems like things didn't import but that's just JMC filtering down the select to only profiles that are applicable.
We should rename the template to be OracleJDK (or something that mentions oracle) and provide a new one for OpenJDK if continous/whatever don't suit our needs.
java-perf-workshop-tester
module. However everything else in the instructions is from the java-perf-workshop
module (relative to it). The gatling tests should also run from that directory so there's no confusion on what needs to be ran from where.The gatling simulation attempts to create a sort of real world scenario (using search/
, ascii/
search/context
and conference/details
). However the race condition that should trigger the memory leak sometimes is not reached (dumb threads not doing what I want).
We should:
/search
95% of the time and 5% with the context parameter.Ideally we could be able to create a situation where we can get an OutOfMemory exception when the service's memory is lowered (not using the default size)
https://buggyapp.ycrash.io/ <- would be good to have a reference to this something.
We are wanting to have a contributors page to highlight those who contribute to the content. This would include a short bio, reference to their github account, and photo.
Consider making updates to the flow of the workshop:
The commands all have 1.0-SNAPSHOT.
I'll update all instances to say 1.1.0-SNAPSHOT.
There will be some implied knowledge about Java, but it may help share those expectations with references to good learning resources before going through this workshop.
This should include content from #27 on anything additional that might be needed for the inclusion of containers.
We are wanting to change the organization of this site to be hosted in as a website, vs just Markdown files within the folder structure. This will help in guiding the flow of the workshop, making a better user experience, and then can have references to the code they run in the project.
The SearcherTest#testSearch
suffers from intermittent failures, I've been able to reproduce it a bunch and have some symptoms:
When the test takes less than a second, things fail. When it doesn't, things pass. I'm guessing there's some synchronization / concurrency state involved in the failure.
I've been able to get a consistent exception in the console when this fails:
On thread:wkshp-conf-loader-1
Process finished with exit code -1
java.io.FileNotFoundException: text.png (Access is denied)
at java.io.RandomAccessFile.open0(Native Method)
at java.io.RandomAccessFile.open(RandomAccessFile.java:316)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:243)
at javax.imageio.stream.FileImageOutputStream.<init>(FileImageOutputStream.java:69)
at com.sun.imageio.spi.FileImageOutputStreamSpi.createOutputStreamInstance(FileImageOutputStreamSpi.java:55)
at javax.imageio.ImageIO.createImageOutputStream(ImageIO.java:419)
at javax.imageio.ImageIO.write(ImageIO.java:1530)
at cchesser.javaperf.workshop.data.AsciiArtConverter.convert(AsciiArtConverter.java:32)
at cchesser.javaperf.workshop.data.ConferenceSessionLoader$SessionLoadCallable.call(ConferenceSessionLoader.java:128)
at cchesser.javaperf.workshop.data.ConferenceSessionLoader$SessionLoadCallable.call(ConferenceSessionLoader.java:105)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.NullPointerException
at cchesser.javaperf.workshop.data.ConferenceSessionLoader.load(ConferenceSessionLoader.java:98)
at cchesser.javaperf.workshop.data.Searcher.search(Searcher.java:44)
at cchesser.javaperf.workshop.data.SearcherTest.testSearch(SearcherTest.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at com.github.tomakehurst.wiremock.junit.WireMockRule$1.evaluate(WireMockRule.java:72)
at org.junit.rules.RunRules.evaluate(RunRules.java:18)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.NullPointerException
at com.google.common.util.concurrent.AbstractFuture$Sync.getValue(AbstractFuture.java:299)
at com.google.common.util.concurrent.AbstractFuture$Sync.get(AbstractFuture.java:286)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:116)
at com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly(Uninterruptibles.java:137)
at com.google.common.cache.LocalCache$Segment.getAndRecordStats(LocalCache.java:2348)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2320)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2282)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2197)
at com.google.common.cache.LocalCache.get(LocalCache.java:3937)
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3941)
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4824)
at cchesser.javaperf.workshop.data.ConferenceSessionLoader.load(ConferenceSessionLoader.java:96)
... 26 more
Caused by: java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at cchesser.javaperf.workshop.data.ConferenceSessionLoader$1.load(ConferenceSessionLoader.java:58)
at cchesser.javaperf.workshop.data.ConferenceSessionLoader$1.load(ConferenceSessionLoader.java:49)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3527)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2319)
... 32 more
Caused by: java.lang.NullPointerException
at javax.imageio.ImageIO.write(ImageIO.java:1538)
at cchesser.javaperf.workshop.data.AsciiArtConverter.convert(AsciiArtConverter.java:32)
at cchesser.javaperf.workshop.data.ConferenceSessionLoader$SessionLoadCallable.call(ConferenceSessionLoader.java:128)
at cchesser.javaperf.workshop.data.ConferenceSessionLoader$SessionLoadCallable.call(ConferenceSessionLoader.java:105)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
I thought it had to do with where the threads are launched from (and somehow not having access to write, so I added some naive prints for the thread name:
On thread:wkshp-conf-loader-0
java.io.FileNotFoundException: text.png (Access is denied)
at java.io.RandomAccessFile.open0(Native Method)
at java.io.RandomAccessFile.open(RandomAccessFile.java:316)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:243)
at javax.imageio.stream.FileImageOutputStream.<init>(FileImageOutputStream.java:69)
at com.sun.imageio.spi.FileImageOutputStreamSpi.createOutputStreamInstance(FileImageOutputStreamSpi.java:55)
at javax.imageio.ImageIO.createImageOutputStream(ImageIO.java:419)
at javax.imageio.ImageIO.write(ImageIO.java:1530)
at cchesser.javaperf.workshop.data.AsciiArtConverter.convert(AsciiArtConverter.java:32)
at cchesser.javaperf.workshop.data.ConferenceSessionLoader$SessionLoadCallable.call(ConferenceSessionLoader.java:128)
at cchesser.javaperf.workshop.data.ConferenceSessionLoader$SessionLoadCallable.call(ConferenceSessionLoader.java:105)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
On thread:wkshp-conf-loader-0
However, this also happens with wkshp-conf-loader-1 , so no dice there :(
I've found a way to fix it (if the issue is not being able to create a file at a certain spot, concurrency problems are always tough).
Path tempFilePath = Files.createTempFile("text", "png");
File tempFile = tempFilePath.toFile();
tempFile.deleteOnExit();
ImageIO.write(image, "png", tempFile);
Was the intermittent failure an intended behavior for the purpose of the workshop? If so, we can keep the failures!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.