tag:blogger.com,1999:blog-17298225193921750092024-03-23T10:14:07.222+00:00Vanilla JavaUnderstanding how Core Java really works can help you write simpler, faster applications.Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.comBlogger340125tag:blogger.com,1999:blog-1729822519392175009.post-70558306180424358422022-09-12T08:49:00.009+00:002022-09-15T04:10:20.903+00:00Java is Very Fast, If You Don’t Create Many Objects<p> </p><span id="docs-internal-guid-0f0bdfd8-7fff-ba4a-10ed-f4b6f8244f22"><h1 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 20pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-style: italic; white-space: pre-wrap;">You still have to watch how many objects you create.</span></h1><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">This article looks at a benchmark passing events over TCP/IP at 4 billion events per minute using the net.openhft.chronicle.wire.channel package in <a href="https://github.com/OpenHFT/Chronicle-Wire" target="_blank">Chronicle Wire</a> and why we still avoid object allocations.. </span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">One of the key optimisations is creating almost no garbage. Allocation is a very cheap operation and collection of very short-lived objects is also very cheap. Does this really make a difference? What difference does one small object per event (44 bytes) make to the performance in a throughput test where GC pauses are amortised?</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">While allocation is as efficient as possible, it doesn’t avoid the memory pressure on the L1/L2 caches of your CPUs and when many cores are busy, they are contending for memory in the shared L3 cache. </span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span face="Poppins, sans-serif" style="font-size: 16pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">Results</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Benchmark on a Ryzen 5950X with Ubuntu 22.10.</span></p><div align="center" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none;"><colgroup><col width="187"></col><col width="241"></col><col width="245"></col></colgroup><tbody><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">JVM Vendor, Version</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">No objects</span></p><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Throughput, Average Latency*</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">One object per event</span></p><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Throughput, Average Latency*</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Azul Zulu 1.8.0_322</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">60.6 M event/s, 528 ns</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">36.8 M event/s, 879 ns</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Azul Zulu 11.0.14.1</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">67.3 M event/s, 476 ns</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">45.7 M event/s, 700 ns</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Azul Zulu 17.0.4.1</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">68.6 M event/s, 467 ns</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">50.3 M event/s, 636 ns</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Azul Zulu 18.0.2.1</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">67.5 M event/s, 474 ns</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">49.8 M event/s, 642 ns</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Oracle OpenJDK 18.0.2.1</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">67.8 M event/s, 472 ns</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">50.1 M event/s, 638 ns</span></p></td></tr></tbody></table></div><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 9pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">* Across 16 clients, an event is sent in both directions. The Average Latency = 2 * 16 / throughput</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">One extra object for each event adds 166 ns or so. This doesn’t sound like much; however, in a high throughput context, this can reduce performance by 25%.</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">The default behaviour for reading events in Chronicle WIre is to reuse the same object for the same event type every time on deserialization. This provides a simple object pooling strategy to avoid allocations. If this data is retained across method calls, it must be copied.</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">NOTE: The total time spent in GC was about 170 milliseconds per minute or 0.3% of the time. It is the allocations rather than the time to clean up these very short-lived objects that takes time.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">A benchmark of creating short-lived TopOfBook objects across multiple CPUs, produces a similar result. This suggests that the rate new objects can be allocated is quickly saturated for even a small proportion of cores, increasing the average latency with more threads. This is for the same small 44-byte objects.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">On a Ryzen 5950X with Ubuntu 21.10, Java 17.0.4.1</span></p><div align="center" dir="ltr" style="margin-left: 0pt;"><table style="border-collapse: collapse; border: none;"><colgroup><col width="122"></col><col width="294"></col></colgroup><tbody><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: right;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Threads</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Allocation rate, average latency</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: right;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">2</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">126 M objs/sec, 15 ns</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: right;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">3</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">176 M objs/sec, 17 ns</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: right;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">4</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">211 M objs/sec, 18 ns</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: right;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">6</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">226 M objs/sec, 26 ns</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: right;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">8</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">219 M objs/sec, 36 ns</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: right;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">16</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">220 M objs/sec, 72 ns</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: right;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">32</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">211 M objs/sec, </span><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">150 ns</span></p></td></tr><tr style="height: 0pt;"><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt; text-align: right;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">32 (two JVMS)</span></p></td><td style="border-bottom: solid #000000 1pt; border-color: rgb(0, 0, 0); border-left: solid #000000 1pt; border-right: solid #000000 1pt; border-style: solid; border-top: solid #000000 1pt; border-width: 1pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;"><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">209 M objs/sec total</span></p></td></tr></tbody></table></div><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span face="Poppins, sans-serif" style="font-size: 16pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">The benchmarks</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">They are not directly comparable but confirm that it’s in the same ballpark. See PerfTopOfBookAllocationMain </span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="border: none; display: inline-block; height: 283px; overflow: hidden; width: 677px;"><img height="283" src="https://lh5.googleusercontent.com/Xv0Qa2eCzTir7VXvwrKG5gQCE_d4vcXIl6Vj_5yPgFz2NRd4rTDekfqJhKSKnvKkVqG-8lSemGfiPWxtLdfle3BHJmOGAN5snpbZtMhj6rBCvmbNEvZQHfHNHzrSCnSkACVjQ1rPvZkOB5TWNQsWnIUVtSQHqQ0vHmUCfg4sn6OpE_Zd66-zmP4gYg" style="margin-left: 0px; margin-top: 0px;" width="677" /></span></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">In this benchmark, sixteen clients connect to a simple microservice that takes each event and sends it back again. All events are (de)serialised POJOs with an event type. This translates to an asynchronous RPC call.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public class </span><span style="background-color: white; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">EchoTopOfBookHandler </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">implements </span><span style="background-color: white; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">ITopOfBookHandler </span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">private </span><span style="background-color: white; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">TopOfBookListener </span><span style="background-color: white; color: #871094; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">topOfBookListener</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #9e880d; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">@Override</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #9e880d; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public void </span><span style="background-color: white; color: #00627a; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">topOfBook</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="background-color: white; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">TopOfBook </span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">topOfBook) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">if </span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="background-color: white; color: #871094; font-family: Verdana; font-size: 12pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">ONE__NEW_OBJECT</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">)</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> topOfBook = topOfBook.deepCopy();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #871094; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">topOfBookListener</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">.topOfBook(topOfBook);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">In this case, deepCopy() creates a new TopOfBook and sets all the fields.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">The benchmark can be run in two modes, one where no objects are allocated and one where any object is allocated and initialised, allowing us to measure the difference this makes. Each event is modelled as an asynchronous RPC call to make testing, development and maintenance easier. </span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">public interface </span><span style="background-color: white; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">TopOfBookListener </span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">void </span><span style="background-color: white; color: #00627a; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">topOfBook</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="background-color: white; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">TopOfBook </span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">topOfBook);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Low latency software can be very fast but also difficult to work with, slowing development. Using events modelled in YAML we can support Behaviour Driven Development of the microservice.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">This is the </span><span face="Poppins, sans-serif" style="font-size: 11pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">in.yaml</span><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> and the </span><span face="Poppins, sans-serif" style="font-size: 11pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">out.yaml</span><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> for the microservice above.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #8c8c8c; font-family: Verdana; font-size: 12pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"># first top-of-book</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">---</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">topOfBook</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">sendingTimeNS</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: 2022-09-05T12:34:56.789012345,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">symbol</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: EUR/USD,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">ecn</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: EBS,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">bidPrice</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: 0.9913,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">askPrice</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: 0.9917,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">bidQuantity</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: 1000000,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">askQuantity</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: 2500000</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">...</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #8c8c8c; font-family: Verdana; font-size: 12pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"># second top-of-book</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">---</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">topOfBook</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">sendingTimeNS</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: 2022-09-05T12:34:56.789123456,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">symbol</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: EUR/USD,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">ecn</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: EBS,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">bidPrice</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: 0.9914,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">askPrice</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: 0.9918,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">bidQuantity</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: 1500000,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #0033b3; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">askQuantity</span><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">: 2000000</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #080808; font-family: Verdana; font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">...</span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span face="Poppins, sans-serif" style="font-size: 16pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">The code</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Is available here <a href="https://github.com/OpenHFT/Chronicle-Wire/tree/ea/src/test/java/net/openhft/chronicle/wire/channel/book">https://github.com/OpenHFT/Chronicle-Wire/tree/ea/src/test/java/net/openhft/chronicle/wire/channel/book</a></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">This library is used in <a href="https://chronicle.software/services-2/" target="_blank">Chronicle Services</a> </span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Hacker News comments on this article <a href="https://news.ycombinator.com/item?id=32807587#32809487">https://news.ycombinator.com/item?id=32807587#32809487</a></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Twitter post on this article <a href="https://twitter.com/PeterLawrey/status/1569247849074012160">https://twitter.com/PeterLawrey/status/1569247849074012160</a></span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span face="Poppins, sans-serif" style="font-size: 16pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">Conclusion</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Java can be very fast, however, it can be well worth avoiding object creation. </span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">The cost of object creation can be far higher than cleaning them up if they are very short-lived.</span></p><div><span face="Poppins, sans-serif" style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></div></span>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com2tag:blogger.com,1999:blog-1729822519392175009.post-76283852950440117442022-08-02T08:00:00.003+00:002022-08-03T10:53:07.119+00:00Comparing Approaches to Durability in Low Latency Messaging Queues<p> <span face="Poppins, sans-serif" style="background-color: white; color: #181f4c; font-size: 16px;">A significant feature of Chronicle Queue Enterprise is support for TCP replication across multiple servers to ensure the high availability of application infrastructure. I generally believe that replicating data to a secondary system is faster than syncing to disk, assuming the round trip network delay wasn’t high due to quality networks and co-located redundant servers. This is the first time I have benchmarked it with a realistic example.</span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Little’s Law and Why Latency Matters</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">In many cases, the assumption is that the latency won't be a problem as long as throughput is high enough. However, latency is often a key factor in why the throughput isn’t high enough.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word; text-align: center;"><span style="box-sizing: border-box;"><span id="docs-internal-guid-e66cf3bb-7fff-3a95-c2cf-a2f2939a331c"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="border: none; display: inline-block; height: 284px; overflow: hidden; width: 519px;"><img height="284" src="https://lh4.googleusercontent.com/3UTwosTuuwqZzGcZ1N6MMkVbR9rwmTwp2vFkakJjcH3rRZUkdHv8-wC2A97_FI4PCBj50dUr7mPvkEi0Lc15iu7hHr5HEn1VVBbrWcQluXHAMQ0JABYuOeEIjG8gL5LQ8hFG6mXAdWNL6ikezrt0CLA" style="margin-left: 0px; margin-top: 0px;" width="519" /></span></span></span></span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Little’s law states, “</span><span style="box-sizing: border-box;">the long-term average number </span><i style="box-sizing: border-box;">L</i><span style="box-sizing: border-box;"> of customers in a </span><a href="https://en.wikipedia.org/wiki/Stationary_process" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">stationary</span></a><span style="box-sizing: border-box;"> system is equal to the long-term average effective arrival rate </span><i style="box-sizing: border-box;">λ</i><span style="box-sizing: border-box;"> multiplied by the average time </span><i style="box-sizing: border-box;">W</i><span style="box-sizing: border-box;"> that a customer spends in the system”.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">In computer terminology, the level of concurrency or parallelism a system has to support must be at least the average throughput times the average latency.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">To achieve a given throughput, the level of concurrency increases with the latency. This generally also increases the level of complexity and risk in order to achieve this concurrency. Many systems have high inherent parallelism; however financial systems generally do not, limiting how much concurrency can be theoretically achieved. More moving parts increase the risk of failure as well.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-4094 lazyloaded" data-sizes="(max-width: 728px) 100vw, 728px" data-src="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.36.13-AM.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.36.13-AM.png 1396w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.36.13-AM-300x126.png 300w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.36.13-AM-1024x431.png 1024w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.36.13-AM-768x323.png 768w" height="307" sizes="(max-width: 728px) 100vw, 728px" src="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.36.13-AM.png" srcset="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.36.13-AM.png 1396w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.36.13-AM-300x126.png 300w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.36.13-AM-1024x431.png 1024w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.36.13-AM-768x323.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="728" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><i style="box-sizing: border-box;">Table 1. Level of concurrency/parallelism required to achieve a given throughput and latency.</i></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Best of Both Worlds</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">While sync-ing to disk is normally seen as a requirement for message durability, it carries a cost in terms of performance, directly increasing latency but indirectly reducing throughput. Acknowledged replication gives similar guarantees and (spoiler alert) is quicker.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">From time to time, however, you might get messages such as orders, trades or payments that are too large to risk losing.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">A trade-off would be to use acknowledged replication but sync to disk when some business risk threshold is reached, either in an individual message or an aggregation of messages. In this test, I explore the difference that sync-ing only 10 times per second could make.</span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Balancing Technical and Commercial Risks</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Many IT systems tend to treat technical risks separately from commercial ones. For example, Kafka has the option to periodically sync data to disk say every 100 ms. This is regardless of the content or value of those messages. Unfortunately, you have no idea of the </span><i style="box-sizing: border-box;">value </i><span style="box-sizing: border-box;">of the messages that could be lost in that time.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">However, you can achieve improved outcomes by aligning the technical solution with the commercial risks. For example, you can sync to disk based on the content with the Chronicle stack. A large order or payment individually or a large total cumulatively can trigger a sync. Instead of a 100 ms cap of unknown value, you can have a cap of $10m (you can also cap by time).</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Chronicle Queue has multiple ways of triggering a sync, however, the simplest is to call </span><em style="box-sizing: border-box;">sync()</em><span style="box-sizing: border-box;"> on the </span><em style="box-sizing: border-box;">ExcerptAppender</em><span style="box-sizing: border-box;"> to sync everything up to the last message written. In Chronicle Services, writing a<em style="box-sizing: border-box;"> sync()</em> event triggers a sync on the underlying queue, keeping a record of when it was performed. Downstream services can wait for this event if they need to know a sync was performed.</span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Low Latency vs Durability Requirements</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Low latency systems ‘need for speed’ usually trumps the need for reliability, so the fastest option available is usually chosen. Messages are usually kept as small as is reasonably possible. E.g. 40 – 256 bytes.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">However, many financial systems have higher durability but lower latency speed requirements. The message sizes are also typically larger e.g. 1 – 8 KB.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-4095 lazyloaded" data-sizes="(max-width: 587px) 100vw, 587px" data-src="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.38.48-AM.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.38.48-AM.png 1174w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.38.48-AM-300x165.png 300w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.38.48-AM-1024x563.png 1024w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.38.48-AM-768x423.png 768w" height="323" sizes="(max-width: 587px) 100vw, 587px" src="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.38.48-AM.png" srcset="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.38.48-AM.png 1174w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.38.48-AM-300x165.png 300w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.38.48-AM-1024x563.png 1024w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.38.48-AM-768x423.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="587" /></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Benchmarked Scenario</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Many systems support flushing or syncing to a disk periodically; however, this is not based on the content of the messages. With Chronicle, you can select the critical messages that have to be synced to disk. You can make several programmatic calls to trigger or wait for a sync based on message content. </span><span style="box-sizing: border-box;">Assuming our application has a small portion of messages that must be sync-ed to disk based on business requirements, we can sync only when those messages are written.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">In this benchmark, (1) a client publishes a 1 KB message to a server over TCP, (2) the server writes the data to a Chronicle Queue on disk, either using async as msync(MS_ASYNC), sync as msync(MS_SYNC), or sync-ing 10 times/s based on a simulated business risk, your use case will vary, (3) data is replicated to a second server over TCP, (4) data is acknowledged, (5) on the replica the data is also written to disk via async flush under the control of the OS, (6) after step 2 & 4, a commit message is sent back to the client.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Each case used fast machines (Ryzen 9 5950X) and a low latency network.. The OS was tuned for isolating CPUs (https://access.redhat.com/solutions/480473) to reduce latency, however, no additional optimisations were added. Slower machines, disk subsystems, and network latencies will add to the timings below. No tuning was made to optimise how sync performed.</span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Low Latency Options with Small Messages</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">A simple way to reduce latencies is to do less work. Low latency systems tend to use smaller messages around 256 bytes; what latency can we get if we don’t need strong resilience guarantees? In each case, the same configuration is used. The difference is which points are timed. This chart illustrates the performance you can get if you consider:</span></p><ul style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word;"><li aria-level="1" style="box-sizing: border-box;"><span style="box-sizing: border-box;">Time to publish only; this is the minimum you can do. All it does is write the data to a buffer so it can be written to the network asynchronously. The data doesn’t even reach step 1 in the diagram above.</span></li><li aria-level="1" style="box-sizing: border-box;"><span style="box-sizing: border-box;">Time to wait for a response from Server 1 without an acknowledgement from a second server. This does steps 1, 2 & 6.</span></li><li aria-level="1" style="box-sizing: border-box;"><span style="box-sizing: border-box;">Time to wait for a response from Server 1 after an acknowledgement; this does the same steps 1, 2, 3, 4, and 6 as before.</span></li></ul><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">The chart below shows data from the same run, and the different lines represent which points we measure time at, to show the difference it makes if you wait for different stages of persistence.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-4096 lazyloaded" data-sizes="(max-width: 713px) 100vw, 713px" data-src="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.40.24-AM.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.40.24-AM.png 1356w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.40.24-AM-300x162.png 300w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.40.24-AM-1024x551.png 1024w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.40.24-AM-768x413.png 768w" height="384" sizes="(max-width: 713px) 100vw, 713px" src="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.40.24-AM.png" srcset="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.40.24-AM.png 1356w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.40.24-AM-300x162.png 300w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.40.24-AM-1024x551.png 1024w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.40.24-AM-768x413.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="713" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><i style="box-sizing: border-box;">Figure 1. M.2 200K/s messages of 256 Bytes in timed at different stages</i></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">While these tests benefit from smaller messages (compare “M.2 Async&Ack” in the last chart below), the main speed improvement is not waiting for the same persistence stage.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">You can customise how your system behaves, either at the queue level, by message type or even based on the message’s contents, to align the technical risks to the commercial risks.</span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Waiting for either Replication Acknowledgement OR a Sync to Disk</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">For systems where a sync to disk is currently required, there could be a significant latency improvement if the alternative is to wait for acknowledged replication. In this case, the latency is the same as the “Async&Ack” options (plus network round trip time), falling back to the “Sync&Ack” latency when the replica isn’t available (or after failover to the secondary system)</span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">SATA Solid State Drives with Medium Sized Messages</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Above, we compared the same configuration timed at different stages. In this case, the end-to-end is timed, with different options for sync-ing to disk.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">In use cases requiring higher guarantees, the messages are often larger. In this test, 50K/s messages of 1 KB are timed from publishing on a client to receiving a committed message from “Server 1”. The “SYNC 10/s” assumes that on average, a SYNC is required ten times a second. This can be based on the content of the messages, e.g. a large order or payment, rather than just periodically.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-4097 lazyloaded" data-sizes="(max-width: 722px) 100vw, 722px" data-src="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.41.21-AM.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.41.21-AM.png 1350w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.41.21-AM-300x164.png 300w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.41.21-AM-1024x560.png 1024w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.41.21-AM-768x420.png 768w" height="395" sizes="(max-width: 722px) 100vw, 722px" src="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.41.21-AM.png" srcset="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.41.21-AM.png 1350w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.41.21-AM-300x164.png 300w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.41.21-AM-1024x560.png 1024w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.41.21-AM-768x420.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="722" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><i style="box-sizing: border-box;">Figure 2. 50K/s messages of 1KB timed from publishing on the client to receiving a committed message</i></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Note: the round trip time for an acknowledgement from a second machine is much faster than a sync to disk. The cost is about the round trip time for the network.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Solid State Drives are not unusual in enterprise-grade data storage systems. They perform much better than Hard Disk Drives; however, increasing the throughput can be a bottleneck.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">As you can see from the yellow line, this significantly reduces the typical latency while improving the whole latency distribution for this SSD.</span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">M.2 Solid State Drives with Medium Sized Messages</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">M.2 drives perform much better across the board, and for the drive tested, even at 200Kmsg/s outperformed the SSD. Nevertheless, selective sync-ing still significantly improves the typical latency and the high end latencies. This is the same test as above but with a higher throughput of 200K/s vs 50K/s</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-4098 lazyloaded" data-sizes="(max-width: 752px) 100vw, 752px" data-src="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.42.16-AM.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.42.16-AM.png 1352w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.42.16-AM-300x162.png 300w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.42.16-AM-1024x554.png 1024w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.42.16-AM-768x416.png 768w" height="407" sizes="(max-width: 752px) 100vw, 752px" src="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.42.16-AM.png" srcset="https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.42.16-AM.png 1352w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.42.16-AM-300x162.png 300w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.42.16-AM-1024x554.png 1024w, https://chronicle.software/wp-content/uploads/2022/08/Screen-Shot-2022-08-02-at-9.42.16-AM-768x416.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="752" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><i style="box-sizing: border-box;">Figure 3. 200K/s messages of 1KB timed from publishing on the client to receiving a committed message</i></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Again, you can see that the yellow line has significantly lower latencies with selective sync-ing compared to sync-ing every batch of messages.</span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Head Room</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">To put this in context, </span><a href="https://www.visa.co.uk/dam/VCOM/download/corporate/media/visanet-technology/aboutvisafactsheet.pdf" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">VISA has a capacity of 65,000 transaction messages per second</span></a><span style="box-sizing: border-box;"> (as of Aug 2017). This is a single pair of servers via a single TCP connection. Having greater headroom immediately available can increase reliability, reducing the risk of the system being overloaded in a burst of activity and reducing the time the system takes to return to normal operation.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Increased headroom reduces the risk of a cascading failure in the event of a burst of activity or an interruption. </span><a href="https://en.wikipedia.org/wiki/Cascading_failure" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">https://en.wikipedia.org/wiki/Cascading_failure</span></a><span style="box-sizing: border-box;"> </span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Conclusion</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Sync-ing to disk with SSDs, was under 25 milliseconds most of the time for even decent throughputs, up to 50K/s. However, using high-performance M.2 drives increases the throughput up to 200K/s and is still under 25 ms most of the time.</span><span style="box-sizing: border-box;"> </span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Typically latency can be reduced significantly if the application selectively syncs data based on the contents of those messages e.g. based on value. This can result in typical latencies close to just waiting for acknowledged replication.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">The fastest option tested was to async to disk and wait for acknowledged replication. The higher percentile latencies can be one-tenth or better using this strategy.</span></p>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-65038392701761574032022-06-22T11:48:00.007+00:002022-08-02T10:33:37.600+00:00Event-Driven Order Processing Program<p> <span style="background-color: white; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px;">Following the</span><span style="background-color: white; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px;"> </span><a href="https://chronicle.software/event-driven-hello-world-program/" style="box-sizing: border-box; color: #3155a5; font-family: Poppins, sans-serif; font-size: 16px; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;">Hello World example</a><span style="background-color: white; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px;"> </span><span style="background-color: white; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px;">of a simple, independently deployable real-time Event-Driven Microservice, this article looks at a more realistic example of an Order Processor with a New Order Single in and an Execution Report out. </span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">A </span><a href="https://fiximate.fixtrading.org/legacy/en/FIX.4.2/body_495268.html" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">New Order Single</span></a><span style="box-sizing: border-box;"> is a standard message type for the order of one asset in the FIX protocol used widely by financial institutions such as banks. The reply is typically one or more </span><a href="https://fiximate.fixtrading.org/legacy/en/FIX.4.2/body_495268.html" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">Execution </span><span style="box-sizing: border-box; font-weight: 400;">Report</span></a><span style="box-sizing: border-box;">s updating the status of that order.</span></p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Some Background on Fintech</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">In fintech, when one organisation wishes to purchase an asset or commodity from another, they send an order. </span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">The other organisation sends a message to notify if the order was successful; this message is called an execution report. You could think of it a bit like a trade receipt. These orders and execution reports are transmitted electronically, using a data format standardised by Financial Information eXchange (FIX). There are many different orders, but one of the most popular Orders offered by the FIX standard is the NewOrderSingle.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">We use the same terminology as the </span><a href="https://www.fixtrading.org/standards/" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">FIX protocol</span></a><span style="box-sizing: border-box;"> to simplify the translation from one to the other. This example is also </span><a href="https://github.com/OpenHFT/Chronicle-Queue-Demo/tree/master/order-processor" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">available on GitHub</span></a><span style="box-sizing: border-box;">.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Again, we model an input event in YAML. To start with, we will reject all new orders as this is simple to demonstrate. </span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3919 lazyloaded" data-sizes="(max-width: 616px) 100vw, 616px" data-src="https://chronicle.software/wp-content/uploads/2022/06/img1-2.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/06/img1-2.png 1446w, https://chronicle.software/wp-content/uploads/2022/06/img1-2-300x165.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img1-2-1024x564.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img1-2-768x423.png 768w" height="339" sizes="(max-width: 616px) 100vw, 616px" src="https://chronicle.software/wp-content/uploads/2022/06/img1-2.png" srcset="https://chronicle.software/wp-content/uploads/2022/06/img1-2.png 1446w, https://chronicle.software/wp-content/uploads/2022/06/img1-2-300x165.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img1-2-1024x564.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img1-2-768x423.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="616" /></p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Testing this Service</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">We can test this service with the captured data earlier with a YAML configuration. We override the system clock to produce the same results every time.</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">public static void </span><span style="box-sizing: border-box;">runTest</span><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">String </span><span style="box-sizing: border-box;">path) {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">try </span><span style="box-sizing: border-box;">{</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">SystemTimeProvider</span><span style="box-sizing: border-box;">.</span><i style="box-sizing: border-box;">CLOCK </i><span style="box-sizing: border-box;">= </span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">SetTimeProvider(</span><span style="box-sizing: border-box;">"2019-12-03T09:54:37.345678"</span><span style="box-sizing: border-box;">)</span>
<span style="box-sizing: border-box;"> .advanceMicros(</span><span style="box-sizing: border-box;">1</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">YamlTester yt </span><span style="box-sizing: border-box;">= </span><span style="box-sizing: border-box;">YamlTester</span><span style="box-sizing: border-box;">.</span><i style="box-sizing: border-box;">runTest</i><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">OMSImpl</span><span style="box-sizing: border-box;">.</span><span style="box-sizing: border-box;">class</span><span style="box-sizing: border-box;">, path);</span>
<span style="box-sizing: border-box;"> </span><i style="box-sizing: border-box;">assertEquals</i><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">yt</span><span style="box-sizing: border-box;">.expected(), </span><span style="box-sizing: border-box;">yt</span><span style="box-sizing: border-box;">.actual());</span>
<span style="box-sizing: border-box;"> } </span><span style="box-sizing: border-box;">finally </span><span style="box-sizing: border-box;">{</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">SystemTimeProvider</span><span style="box-sizing: border-box;">.</span><i style="box-sizing: border-box;">CLOCK </i><span style="box-sizing: border-box;">= </span><span style="box-sizing: border-box;">SystemTimeProvider</span><span style="box-sizing: border-box;">.</span><i style="box-sizing: border-box;">INSTANCE</i><span style="box-sizing: border-box;">;</span>
<span style="box-sizing: border-box;"> }</span>
<span style="box-sizing: border-box;">}</span>
<span style="box-sizing: border-box;">@Test</span>
<span style="box-sizing: border-box;">public void </span><span style="box-sizing: border-box;">newOrderSingle</span><span style="box-sizing: border-box;">() {</span>
<span style="box-sizing: border-box;"> </span><i style="box-sizing: border-box;">runTest</i><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">"newOrderSingle"</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;">}</span></pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">As in previous examples, if the output is incorrect, we can quickly see this in the data. </span></p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">What do we see when a test fails?</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Say we don’t override the time and use the wall clock instead. We might see something like this.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3921 lazyloaded" data-sizes="(max-width: 564px) 100vw, 564px" data-src="https://chronicle.software/wp-content/uploads/2022/06/img3-1.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/06/img3-1.png 1270w, https://chronicle.software/wp-content/uploads/2022/06/img3-1-300x64.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img3-1-1024x218.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img3-1-768x163.png 768w" height="120" sizes="(max-width: 564px) 100vw, 564px" src="https://chronicle.software/wp-content/uploads/2022/06/img3-1.png" srcset="https://chronicle.software/wp-content/uploads/2022/06/img3-1.png 1270w, https://chronicle.software/wp-content/uploads/2022/06/img3-1-300x64.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img3-1-1024x218.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img3-1-768x163.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="564" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">And if we “Click to see difference”, we can see the orderID, which contains a timestamp that has changed. There are many ways to handle this, but we override the system clock to ensure we also get the same time in this example.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3922 lazyloaded" data-sizes="(max-width: 705px) 100vw, 705px" data-src="https://chronicle.software/wp-content/uploads/2022/06/img4.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/06/img4.png 1340w, https://chronicle.software/wp-content/uploads/2022/06/img4-300x172.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img4-1024x588.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img4-768x441.png 768w" height="405" sizes="(max-width: 705px) 100vw, 705px" src="https://chronicle.software/wp-content/uploads/2022/06/img4.png" srcset="https://chronicle.software/wp-content/uploads/2022/06/img4.png 1340w, https://chronicle.software/wp-content/uploads/2022/06/img4-300x172.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img4-1024x588.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img4-768x441.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="705" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">The component doesn’t need to log anything as all results, including errors, are written to the output queue.</span></p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Performance Testing</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">In this benchmark, 100k orders/s are injected into one queue. These are then processed, and the result is written in a second queue and read to get an end-to-end latency. Each run is 30 seconds. This times two serializations, two writes, two reads, two deserializations and two hops between threads.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Running on a desktop with an AMD Ryzen 9 5950X and Ubuntu 21.10, gives very stable performance for in-memory messaging and consistent latencies for writing to the memory-mapped file synchronously. Using the queues in an asynchronous mode achieves similar latencies to in-memory writes while persisting to disk as fast as possible.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><i style="box-sizing: border-box;">Comparing using tmpfs as in-memory and ext4 on an M.2 NVMe drive.</i></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3923 lazyloaded" data-sizes="(max-width: 598px) 100vw, 598px" data-src="https://chronicle.software/wp-content/uploads/2022/06/img5.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/06/img5.png 1384w, https://chronicle.software/wp-content/uploads/2022/06/img5-300x189.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img5-1024x644.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img5-768x483.png 768w" height="376" sizes="(max-width: 598px) 100vw, 598px" src="https://chronicle.software/wp-content/uploads/2022/06/img5.png" srcset="https://chronicle.software/wp-content/uploads/2022/06/img5.png 1384w, https://chronicle.software/wp-content/uploads/2022/06/img5-300x189.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img5-1024x644.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img5-768x483.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="598" /></p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Chronicle Enterprise Extensions</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">You can test, develop and run microservices using our open-source software. Our commercial extensions support; state management e.g. idempotency, faster restarts of services, distributions of events and HA/DR, centralised monitoring of distributed systems, and configuration and testing of a services mesh.</span></p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Conclusion</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Combining high performance and ease of use can be challenging. However, if you keep it simple, microservices using event sources as input and outputs can have consistent, microsecond latency and support maintainable tests. </span></p>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-17398421372338496772022-06-13T11:48:00.001+00:002022-08-02T10:31:53.945+00:00Efficient Memory Mapping for Terabyte Sparse Files in Java<p> <span style="box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px;">On Linux, you can create </span><a href="https://en.wikipedia.org/wiki/Sparse_file" style="box-sizing: border-box; color: #3155a5; font-family: Poppins, sans-serif; font-size: 16px; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">sparse files</span></a><span style="box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px;">, where only the pages (of 4 KiB) that are touched utilise either memory or disk space. This allows you to memory map large virtual regions without worrying about wasted memory or disk</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">In this program, you can see it reserves 8 TiB (8,192 GiB)</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3890 lazyloaded" data-sizes="(max-width: 809px) 100vw, 809px" data-src="https://chronicle.software/wp-content/uploads/2022/06/img1-1.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/06/img1-1.png 1468w, https://chronicle.software/wp-content/uploads/2022/06/img1-1-300x141.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img1-1-1024x480.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img1-1-768x360.png 768w" height="379" sizes="(max-width: 809px) 100vw, 809px" src="https://chronicle.software/wp-content/uploads/2022/06/img1-1.png" srcset="https://chronicle.software/wp-content/uploads/2022/06/img1-1.png 1468w, https://chronicle.software/wp-content/uploads/2022/06/img1-1-300x141.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img1-1-1024x480.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img1-1-768x360.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="809" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><em style="box-sizing: border-box;">Figure 1. <span style="box-sizing: border-box;">Test 1: Sparse file</span></em></p><table style="background-color: white; border-collapse: collapse; border-spacing: 0px; color: #181f4c; display: block; font-family: Poppins, sans-serif; font-size: 16px; height: 202px; overflow-x: auto; white-space: nowrap; width: 811px;"><tbody style="box-sizing: border-box;"><tr style="box-sizing: border-box;"><td style="box-sizing: border-box; padding: 0px;"><span style="box-sizing: border-box;">Tip:</span><span style="box-sizing: border-box;"> x << y means x × 2</span><span style="box-sizing: border-box;">y</span><span style="box-sizing: border-box;"> therefore </span><p style="box-sizing: border-box; margin: 0px 0px 10px; overflow-wrap: break-word;"></p><p style="box-sizing: border-box; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">1L << 10 = 1 KiB (1024 bytes), </span></p><p style="box-sizing: border-box; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">1L << 20 = 1 MiB (1024</span><span style="box-sizing: border-box;">2</span><span style="box-sizing: border-box;"> bytes), </span></p><p style="box-sizing: border-box; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">1L << 30 = 1 GiB (1024</span><span style="box-sizing: border-box;">3</span><span style="box-sizing: border-box;"> bytes), </span></p><p style="box-sizing: border-box; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">1L << 40 = 1 TiB etc</span></p><p style="box-sizing: border-box; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Using multiples of 10 for the shift makes them easier to read. </span></p><p style="box-sizing: border-box; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">64L << 20 is 64 × 2</span><span style="box-sizing: border-box;">20</span><span style="box-sizing: border-box;"> = 64 × 1024</span><span style="box-sizing: border-box;">2</span><span style="box-sizing: border-box;"> = 64 MiB. </span></p></td></tr></tbody></table><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">The virtual memory size of the above process is just over 8192 GiB at 8200.7 GiB, but the RSS (Resident Set Size) is only 122,060 KB, or 122 MB.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3891 lazyloaded" data-sizes="(max-width: 801px) 100vw, 801px" data-src="https://chronicle.software/wp-content/uploads/2022/06/img2.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/06/img2.png 1464w, https://chronicle.software/wp-content/uploads/2022/06/img2-300x125.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img2-1024x427.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img2-768x320.png 768w" height="334" sizes="(max-width: 801px) 100vw, 801px" src="https://chronicle.software/wp-content/uploads/2022/06/img2.png" srcset="https://chronicle.software/wp-content/uploads/2022/06/img2.png 1464w, https://chronicle.software/wp-content/uploads/2022/06/img2-300x125.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img2-1024x427.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img2-768x320.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="801" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><em style="box-sizing: border-box;">Figure 2. RES for Test 1</em></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">On disk, the extents reported are 8 TiB, however the amount of disk (and memory) actually used is just 20 KiB.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3889 lazyloaded" data-sizes="(max-width: 804px) 100vw, 804px" data-src="https://chronicle.software/wp-content/uploads/2022/06/img3.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/06/img3.png 1472w, https://chronicle.software/wp-content/uploads/2022/06/img3-300x102.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img3-1024x349.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img3-768x262.png 768w" height="274" sizes="(max-width: 804px) 100vw, 804px" src="https://chronicle.software/wp-content/uploads/2022/06/img3.png" srcset="https://chronicle.software/wp-content/uploads/2022/06/img3.png 1472w, https://chronicle.software/wp-content/uploads/2022/06/img3-300x102.png 300w, https://chronicle.software/wp-content/uploads/2022/06/img3-1024x349.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/img3-768x262.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="804" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><em style="box-sizing: border-box;">Figure 3. Disk usage for Test 1</em></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">The following test displays the main point of this article more clearly. In the test the reserved virtual memory is 8 TiB again but data has been written sparsely; 1000 integers are written but there is 16L << 10 (16 KiB = four pages) skip after each write. </span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3900 lazyloaded" data-sizes="(max-width: 654px) 100vw, 654px" data-src="https://chronicle.software/wp-content/uploads/2022/06/figure4.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/06/figure4.png 1396w, https://chronicle.software/wp-content/uploads/2022/06/figure4-300x278.png 300w, https://chronicle.software/wp-content/uploads/2022/06/figure4-1024x949.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/figure4-768x712.png 768w" height="606" sizes="(max-width: 654px) 100vw, 654px" src="https://chronicle.software/wp-content/uploads/2022/06/figure4.png" srcset="https://chronicle.software/wp-content/uploads/2022/06/figure4.png 1396w, https://chronicle.software/wp-content/uploads/2022/06/figure4-300x278.png 300w, https://chronicle.software/wp-content/uploads/2022/06/figure4-1024x949.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/figure4-768x712.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="654" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><em style="box-sizing: border-box;">Figure 4. Test 2: Sparse file with skipped pages</em></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">The RSS (Resident Set Size) is only 129,272 KB or 122 MB, and the disk usage is only 4.0 MiB, indicating that only touched pages use memory. Although it seems the size of data is 16 KiB * 1000 = 16 MiB only 1 out of 4 pages have been touched so the actual disk usage is 4KiB * 1000 = 4.0 MiB</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3901 lazyloaded" data-sizes="(max-width: 670px) 100vw, 670px" data-src="https://chronicle.software/wp-content/uploads/2022/06/figure5.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/06/figure5.png 1402w, https://chronicle.software/wp-content/uploads/2022/06/figure5-300x125.png 300w, https://chronicle.software/wp-content/uploads/2022/06/figure5-1024x428.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/figure5-768x321.png 768w" height="280" sizes="(max-width: 670px) 100vw, 670px" src="https://chronicle.software/wp-content/uploads/2022/06/figure5.png" srcset="https://chronicle.software/wp-content/uploads/2022/06/figure5.png 1402w, https://chronicle.software/wp-content/uploads/2022/06/figure5-300x125.png 300w, https://chronicle.software/wp-content/uploads/2022/06/figure5-1024x428.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/figure5-768x321.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="670" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><em style="box-sizing: border-box;">Figure 5. RES for Test 2</em></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3902 lazyloaded" data-sizes="(max-width: 667px) 100vw, 667px" data-src="https://chronicle.software/wp-content/uploads/2022/06/figure6.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/06/figure6.png 1402w, https://chronicle.software/wp-content/uploads/2022/06/figure6-300x90.png 300w, https://chronicle.software/wp-content/uploads/2022/06/figure6-1024x308.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/figure6-768x231.png 768w" height="201" sizes="(max-width: 667px) 100vw, 667px" src="https://chronicle.software/wp-content/uploads/2022/06/figure6.png" srcset="https://chronicle.software/wp-content/uploads/2022/06/figure6.png 1402w, https://chronicle.software/wp-content/uploads/2022/06/figure6-300x90.png 300w, https://chronicle.software/wp-content/uploads/2022/06/figure6-1024x308.png 1024w, https://chronicle.software/wp-content/uploads/2022/06/figure6-768x231.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="667" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><em style="box-sizing: border-box;">Figure 6. Disk usage for Test 2</em></p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Conclusion</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Mapping large areas of memory avoids knowing in advance how much memory we need or resizing the memory mappings while in use while accessing the data as direct memory without the overhead of system calls. </span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">In short, using virtual instead of real memory gives greater flexibility to how we tune our systems. Files that can be pruned lazily make it clear the files won’t be extended.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">In memory mapped files, only the touched pages use disk space. On the system used for the tests in this article, each page can hold 4 KiB data space; hence writing data sparsely so that some pages were skipped did not increase disk usage; in other words, only the touched pages contributed to memory demand.</span></p>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-12532243868101416482022-05-27T11:48:00.003+00:002022-08-02T10:29:45.301+00:00Event Driven Hello World Program<p> <span style="box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; font-weight: 700;">Event-driven microservices</span><span style="box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px;"> can be straightforward to describe before they are implemented, tested and maintained. They are also highly responsive to new information in real-time, with latencies in Java of below 10 microseconds 99.99% of the time, depending on the functionality of the small, independently deployable microservice. </span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">In this introductory article, we use an example </span><a href="https://chronicle.software/how-to-develop-event-driven-architectures/" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">event-driven</span></a> <a href="https://en.wikipedia.org/wiki/%22Hello,_World!%22_program" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">Hello World</span></a><span style="box-sizing: border-box;"> program (</span><span style="box-sizing: border-box;">a programming paradigm where the program flow is determined by events)</span><span style="box-sizing: border-box;"> to step through</span><a href="https://chronicle.software/how-bdd-works-well-with-eda/" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"> <span style="box-sizing: border-box;">behaviour-driven</span> <span style="box-sizing: border-box;">development</span></a><span style="box-sizing: border-box;">, where we describe the behaviour the business needs first as test data and write a very simple </span><a href="https://en.wikipedia.org/wiki/Microservices" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">microservice </span></a><span style="box-sizing: border-box;">which turns input events like this.</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">say: Hello World</span></pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Into outputs like this, by adding an exclamation point</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">say: Hello World</span><span style="box-sizing: border-box; font-weight: 700;">! </span><i style="box-sizing: border-box;"> # <- adds an exclamation point</i></pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">All the code for this example is </span><a href="https://github.com/OpenHFT/Chronicle-Queue-Demo/tree/master/hello-world" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">available on GitHub</span></a><span style="box-sizing: border-box;">.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">When modelling Event-Driven systems, a useful pattern is to have event-driven core systems with gateways connecting to external systems that might not be event-driven. To keep a clear separation of concern, </span><a href="https://en.wikipedia.org/wiki/Business_logic" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">business logic</span></a><span style="box-sizing: border-box;"> such as making a decision based on market data, or processing an order, is placed in the event-driven microservices, as these are the easiest to test, with the </span><span style="box-sizing: border-box; font-weight: 700;">gateways </span><span style="box-sizing: border-box;">connecting to external clients and systems being as thin as possible, so they are only concerned with acting as adapters and avoid containing significant business logic. </span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box; font-weight: 700;">Domain-Driven Design</span><span style="box-sizing: border-box;"> is focused on determining the requirements of domain experts. Their requirements are further divided into event-driven microservices. Where the information is passed as a series of events between the microservices.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">The requirements for each internal microservices can be described in YAML for Behaviour-Driven Development.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3775 lazyloaded" data-sizes="(max-width: 789px) 100vw, 789px" data-src="https://chronicle.software/wp-content/uploads/2022/05/EventDriven.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/EventDriven.png 1642w, https://chronicle.software/wp-content/uploads/2022/05/EventDriven-300x83.png 300w, https://chronicle.software/wp-content/uploads/2022/05/EventDriven-1024x284.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/EventDriven-768x213.png 768w, https://chronicle.software/wp-content/uploads/2022/05/EventDriven-1536x427.png 1536w" height="219" sizes="(max-width: 789px) 100vw, 789px" src="https://chronicle.software/wp-content/uploads/2022/05/EventDriven.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/EventDriven.png 1642w, https://chronicle.software/wp-content/uploads/2022/05/EventDriven-300x83.png 300w, https://chronicle.software/wp-content/uploads/2022/05/EventDriven-1024x284.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/EventDriven-768x213.png 768w, https://chronicle.software/wp-content/uploads/2022/05/EventDriven-1536x427.png 1536w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="789" /><br style="box-sizing: border-box;" /><em style="box-sizing: border-box;"><span style="box-sizing: border-box;">Figure 1- </span><span style="box-sizing: border-box;">Gateways connect internal services to external systems</span></em></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">All examples are in the Chronicle-Queue-Demo/hello-world module.</span></p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">A Simple Event-Driven Contract</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">We model events as asynchronous method calls without arguments or one-to-many arguments e.g.</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">public interface </span><span style="box-sizing: border-box;">Says {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">void </span><span style="box-sizing: border-box;">say</span><span style="box-sizing: border-box;">(String words);</span>
<span style="box-sizing: border-box;">}</span></pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">This is the simplest Hello World example to get started. We can add to this interface other event types (methods) with multiple parameters. Parameters don’t have to be just primitives; they can also be complex data structures such as Data Transfer Objects.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">There is no assumption about how the events produced by the microservice will be processed. It might be recorded but otherwise ignored, for now, processed immediately by a single microservice or read by multiple downstream microservices sometime later. Thus, it doesn’t return a value. Any results will be emitted as events from the respective event handlers. In programming, an event handler is a callback routine that can operate asynchronously.</span></p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">External Event Producers and Consumers</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Often we need to integrate with the client’s external systems. As this is a simple “Hello World” example, let’s imagine that instead of external systems connected via gateways, we have a simple program that reads input from the console to provide upstream events and another simple program to write to the console, acting as a downstream gateway.</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">public class </span><span style="box-sizing: border-box;">SaysInput {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">public static void </span><span style="box-sizing: border-box;">input</span><span style="box-sizing: border-box;">(Says says) </span><span style="box-sizing: border-box;">throws </span><span style="box-sizing: border-box;">IOException {</span>
<span style="box-sizing: border-box;"> BufferedReader br = </span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">BufferedReader(</span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">InputStreamReader(System.</span><i style="box-sizing: border-box;">in</i><span style="box-sizing: border-box;">));</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">for </span><span style="box-sizing: border-box;">(String line; ((line = br.readLine()) != </span><span style="box-sizing: border-box;">null</span><span style="box-sizing: border-box;">); )</span>
<span style="box-sizing: border-box;"> says.say(line);</span>
<span style="box-sizing: border-box;"> }</span>
<span style="box-sizing: border-box;">}</span>
<span style="box-sizing: border-box;">public class </span><span style="box-sizing: border-box;">SaysOutput </span><span style="box-sizing: border-box;">implements </span><span style="box-sizing: border-box;">Says {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">public void </span><span style="box-sizing: border-box;">say</span><span style="box-sizing: border-box;">(String words) {</span>
<span style="box-sizing: border-box;"> System.</span><i style="box-sizing: border-box;">out</i><span style="box-sizing: border-box;">.println(words);</span>
<span style="box-sizing: border-box;"> }</span>
<span style="box-sizing: border-box;">}</span></pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">These can be integrated easily as the output of one is wired to the input of the other.</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">public class </span><span style="box-sizing: border-box;">RecordInputToConsoleMain {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">public static void </span><span style="box-sizing: border-box;">main</span><span style="box-sizing: border-box;">(String[] args) </span><span style="box-sizing: border-box;">throws </span><span style="box-sizing: border-box;">IOException {</span>
<span style="box-sizing: border-box;"> </span><i style="box-sizing: border-box;">// Writes text in each call to say(line) to the console</i>
<i style="box-sizing: border-box;"> </i><span style="box-sizing: border-box;">final </span><span style="box-sizing: border-box;">Says says = </span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">SaysOutput();</span>
<span style="box-sizing: border-box;"> </span><i style="box-sizing: border-box;">// Takes each line input and calls say(line) each time</i>
<i style="box-sizing: border-box;"> </i><span style="box-sizing: border-box;">SaysInput.</span><i style="box-sizing: border-box;">input</i><span style="box-sizing: border-box;">(says);</span>
<span style="box-sizing: border-box;"> }</span>
<span style="box-sizing: border-box;">}</span></pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">We can also record everything the producer performs to YAML to build tests later.</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">public class </span><span style="box-sizing: border-box;">RecordInputAsYamlMain {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">public static void </span><span style="box-sizing: border-box;">main</span><span style="box-sizing: border-box;">(String[] args) </span><span style="box-sizing: border-box;">throws </span><span style="box-sizing: border-box;">IOException {</span>
<span style="box-sizing: border-box;"> </span><i style="box-sizing: border-box;">// obtains a proxy that writes to the PrintStream the method calls and their arguments</i>
<i style="box-sizing: border-box;"> </i><span style="box-sizing: border-box;">final </span><span style="box-sizing: border-box;">Says says = Wires.</span><i style="box-sizing: border-box;">recordAsYaml</i><span style="box-sizing: border-box;">(Says.</span><span style="box-sizing: border-box;">class</span><span style="box-sizing: border-box;">, System.</span><i style="box-sizing: border-box;">out</i><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> </span><i style="box-sizing: border-box;">// Takes each line input and calls say(theLine) each time</i>
<i style="box-sizing: border-box;"> </i><span style="box-sizing: border-box;">SaysInput.</span><i style="box-sizing: border-box;">input</i><span style="box-sizing: border-box;">(says);</span>
<span style="box-sizing: border-box;"> }</span>
<span style="box-sizing: border-box;">}</span></pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3777 lazyloaded" data-sizes="(max-width: 595px) 100vw, 595px" data-src="https://chronicle.software/wp-content/uploads/2022/05/Img2-1.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/Img2-1.png 1100w, https://chronicle.software/wp-content/uploads/2022/05/Img2-1-300x118.png 300w, https://chronicle.software/wp-content/uploads/2022/05/Img2-1-1024x402.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/Img2-1-768x302.png 768w" height="234" sizes="(max-width: 595px) 100vw, 595px" src="https://chronicle.software/wp-content/uploads/2022/05/Img2-1.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/Img2-1.png 1100w, https://chronicle.software/wp-content/uploads/2022/05/Img2-1-300x118.png 300w, https://chronicle.software/wp-content/uploads/2022/05/Img2-1-1024x402.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/Img2-1-768x302.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="595" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Use the following to replay the output from a file.</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">public class </span><span style="box-sizing: border-box;">ReplayOutputMain {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">public static void </span><span style="box-sizing: border-box;">main</span><span style="box-sizing: border-box;">(String[] args) </span><span style="box-sizing: border-box;">throws </span><span style="box-sizing: border-box;">IOException {</span>
<span style="box-sizing: border-box;"> </span><i style="box-sizing: border-box;">// Reads the content of a Yaml file specified in args[0] and feeds it to SaysOutput.</i>
<i style="box-sizing: border-box;"> </i><span style="box-sizing: border-box;">Wires.</span><i style="box-sizing: border-box;">replay</i><span style="box-sizing: border-box;">(args[</span><span style="box-sizing: border-box;">0</span><span style="box-sizing: border-box;">], </span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">SaysOutput());</span>
<span style="box-sizing: border-box;"> }</span>
<span style="box-sizing: border-box;">}</span></pre><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Unit Tests for the RecordAsYaml and Replay Methods</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">The following unit tests were developed to test the functionality of recordAsYaml and replay methods in isolation and verify if they work as suggested above. Having lots of text in unit tests is cumbersome, and in the next section, you can see how this text can be taken from files.</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">public class </span><span style="box-sizing: border-box;">WiresTest </span><span style="box-sizing: border-box;">extends </span><span style="box-sizing: border-box;">WireTestCommon {</span>
<span style="box-sizing: border-box;">@Test</span>
<span style="box-sizing: border-box;">public void </span><span style="box-sizing: border-box;">recordAsYaml</span><span style="box-sizing: border-box;">() {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">ByteArrayOutputStream baos </span><span style="box-sizing: border-box;">= </span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">ByteArrayOutputStream();</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">PrintStream ps </span><span style="box-sizing: border-box;">= </span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">PrintStream(</span><span style="box-sizing: border-box;">baos</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">Says says </span><span style="box-sizing: border-box;">= </span><span style="box-sizing: border-box;">Wires</span><span style="box-sizing: border-box;">.</span><i style="box-sizing: border-box;">recordAsYaml</i><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">Says</span><span style="box-sizing: border-box;">.</span><span style="box-sizing: border-box;">class</span><span style="box-sizing: border-box;">, </span><span style="box-sizing: border-box;">ps</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">says</span><span style="box-sizing: border-box;">.say(</span><span style="box-sizing: border-box;">"One"</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">says</span><span style="box-sizing: border-box;">.say(</span><span style="box-sizing: border-box;">"Two"</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">says</span><span style="box-sizing: border-box;">.say(</span><span style="box-sizing: border-box;">"Three"</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> </span><i style="box-sizing: border-box;">assertEquals</i><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">"" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"---</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"say: One</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"...</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"---</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"say: Two</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"...</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"---</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"say: Three</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"...</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">"</span><span style="box-sizing: border-box;">,</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">String(</span><span style="box-sizing: border-box;">baos</span><span style="box-sizing: border-box;">.toByteArray(), </span><span style="box-sizing: border-box;">StandardCharsets</span><span style="box-sizing: border-box;">.</span><i style="box-sizing: border-box;">ISO_8859_1</i><span style="box-sizing: border-box;">));</span>
<span style="box-sizing: border-box;">}</span>
<span style="box-sizing: border-box;">@Test</span>
<span style="box-sizing: border-box;">public void </span><span style="box-sizing: border-box;">replay</span><span style="box-sizing: border-box;">() </span><span style="box-sizing: border-box;">throws </span><span style="box-sizing: border-box;">IOException </span><span style="box-sizing: border-box;">{</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">ByteArrayOutputStream baos </span><span style="box-sizing: border-box;">= </span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">ByteArrayOutputStream();</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">PrintStream ps </span><span style="box-sizing: border-box;">= </span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">PrintStream(</span><span style="box-sizing: border-box;">baos</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">Says says </span><span style="box-sizing: border-box;">= </span><span style="box-sizing: border-box;">Wires</span><span style="box-sizing: border-box;">.</span><i style="box-sizing: border-box;">recordAsYaml</i><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">Says</span><span style="box-sizing: border-box;">.</span><span style="box-sizing: border-box;">class</span><span style="box-sizing: border-box;">, </span><span style="box-sizing: border-box;">ps</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">says</span><span style="box-sizing: border-box;">.say(</span><span style="box-sizing: border-box;">"zero"</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">Wires</span><span style="box-sizing: border-box;">.</span><i style="box-sizing: border-box;">replay</i><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">"=" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"---</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"say: One</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"...</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"---</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"say: Two</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"...</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"---</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"say: Three</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"...</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">"</span><span style="box-sizing: border-box;">,</span><span style="box-sizing: border-box;">says</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> </span><i style="box-sizing: border-box;">assertEquals</i><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">"" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"---</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"say: zero</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"...</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"---</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"say: One</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"...</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"---</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"say: Two</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"...</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"---</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"say: Three</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">" </span><span style="box-sizing: border-box;">+</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">"...</span><span style="box-sizing: border-box;">\n</span><span style="box-sizing: border-box;">"</span><span style="box-sizing: border-box;">, </span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">String(</span><span style="box-sizing: border-box;">baos</span><span style="box-sizing: border-box;">.toByteArray(), </span><span style="box-sizing: border-box;">StandardCharsets</span><span style="box-sizing: border-box;">.</span><i style="box-sizing: border-box;">ISO_8859_1</i><span style="box-sizing: border-box;">));</span>
<span style="box-sizing: border-box;">}</span>
<span style="box-sizing: border-box;">interface </span><span style="box-sizing: border-box;">Says {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">void </span><span style="box-sizing: border-box;">say</span><span style="box-sizing: border-box;">(String word);</span>
<span style="box-sizing: border-box;">}</span>
<span style="box-sizing: border-box;">}</span>
</pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">By recording and replaying using YAML, our microservices are written, tested and debugged easily without any involvement of the messaging layer.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Let’s add a microservice as a data processor class that can have one or more event types. This microservice gets input events as text messages, adds an exclamation mark, and relays them to the output gateway.</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">public class </span><span style="box-sizing: border-box;">AddsExclamation </span><span style="box-sizing: border-box;">implements </span><span style="box-sizing: border-box;">Says {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">private final </span><span style="box-sizing: border-box;">Says </span><span style="box-sizing: border-box;">out</span><span style="box-sizing: border-box;">;</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">public </span><span style="box-sizing: border-box;">AddsExclamation</span><span style="box-sizing: border-box;">(Says out) {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">this</span><span style="box-sizing: border-box;">.</span><span style="box-sizing: border-box;">out </span><span style="box-sizing: border-box;">= out;</span>
<span style="box-sizing: border-box;"> }</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">public void </span><span style="box-sizing: border-box;">say</span><span style="box-sizing: border-box;">(String words) {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">this</span><span style="box-sizing: border-box;">.</span><span style="box-sizing: border-box;">out</span><span style="box-sizing: border-box;">.say(words + </span><span style="box-sizing: border-box;">"!"</span><span style="box-sizing: border-box;">);</span>
<span style="box-sizing: border-box;"> }</span>
<span style="box-sizing: border-box;">}</span></pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3779 lazyloaded" data-sizes="(max-width: 822px) 100vw, 822px" data-src="https://chronicle.software/wp-content/uploads/2022/05/Img3-1.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/Img3-1.png 1904w, https://chronicle.software/wp-content/uploads/2022/05/Img3-1-300x80.png 300w, https://chronicle.software/wp-content/uploads/2022/05/Img3-1-1024x274.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/Img3-1-768x206.png 768w, https://chronicle.software/wp-content/uploads/2022/05/Img3-1-1536x411.png 1536w" height="220" sizes="(max-width: 822px) 100vw, 822px" src="https://chronicle.software/wp-content/uploads/2022/05/Img3-1.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/Img3-1.png 1904w, https://chronicle.software/wp-content/uploads/2022/05/Img3-1-300x80.png 300w, https://chronicle.software/wp-content/uploads/2022/05/Img3-1-1024x274.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/Img3-1-768x206.png 768w, https://chronicle.software/wp-content/uploads/2022/05/Img3-1-1536x411.png 1536w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="822" /><br style="box-sizing: border-box;" /><em style="box-sizing: border-box;">Figure 2- A microservice that adds exclamation marks to input messages.</em></p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">A Single-Threaded Event-Driven Process</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">We can combine these all stages in one process, one thread. While this is unlikely to be useful in production, putting microservices into a single thread makes it easier to test and debug.</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">public class </span><span style="box-sizing: border-box;">DirectWithExclamationMain {</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">public static void </span><span style="box-sizing: border-box;">main</span><span style="box-sizing: border-box;">(String[] args) </span><span style="box-sizing: border-box;">throws </span><span style="box-sizing: border-box;">IOException {</span>
<span style="box-sizing: border-box;"> SaysInput.</span><i style="box-sizing: border-box;">input</i><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">AddsExclamation(</span><span style="box-sizing: border-box;">new </span><span style="box-sizing: border-box;">SaysOutput()));</span>
<span style="box-sizing: border-box;"> }</span>
<span style="box-sizing: border-box;">}</span></pre><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Testing a Single Event-Driven Service</span></h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Instead of embedding large amounts of text in a test, we can read resource files. This makes them easier to read and maintain.</span></p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">public class </span><span style="box-sizing: border-box;">AddsExclamationTest </span><span style="box-sizing: border-box;">{</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">@Test</span>
<span style="box-sizing: border-box;"> </span><span style="box-sizing: border-box;">public void </span><span style="box-sizing: border-box;">say</span><span style="box-sizing: border-box;">() </span><span style="box-sizing: border-box;">throws </span><span style="box-sizing: border-box;">IOException </span><span style="box-sizing: border-box;">{</span>
<span style="box-sizing: border-box;">YamlTester yt </span><span style="box-sizing: border-box;">= </span><span style="box-sizing: border-box;">YamlTester</span><span style="box-sizing: border-box;">.</span><i style="box-sizing: border-box;">runTest</i><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">AddsExclamation</span><span style="box-sizing: border-box;">.</span><span style="box-sizing: border-box;">class</span><span style="box-sizing: border-box;">, </span><span style="box-sizing: border-box;">"says"</span><span style="box-sizing: border-box;">);</span>
<i style="box-sizing: border-box;">assertEquals</i><span style="box-sizing: border-box;">(</span><span style="box-sizing: border-box;">yt</span><span style="box-sizing: border-box;">.expected(), </span><span style="box-sizing: border-box;">yt</span><span style="box-sizing: border-box;">.actual());</span>
<span style="box-sizing: border-box;"> }</span>
<span style="box-sizing: border-box;">}</span>
</pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3780 lazyloaded" data-sizes="(max-width: 671px) 100vw, 671px" data-src="https://chronicle.software/wp-content/uploads/2022/05/Img4.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/Img4.png 1230w, https://chronicle.software/wp-content/uploads/2022/05/Img4-300x106.png 300w, https://chronicle.software/wp-content/uploads/2022/05/Img4-1024x363.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/Img4-768x272.png 768w" height="238" sizes="(max-width: 671px) 100vw, 671px" src="https://chronicle.software/wp-content/uploads/2022/05/Img4.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/Img4.png 1230w, https://chronicle.software/wp-content/uploads/2022/05/Img4-300x106.png 300w, https://chronicle.software/wp-content/uploads/2022/05/Img4-1024x363.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/Img4-768x272.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="671" /><br style="box-sizing: border-box;" />Let’s update the input to see how easy it is to maintain this test. I will change the second input to Hello World and run the test again.</p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><span style="box-sizing: border-box;">src/test/resources/says/in.yaml</span>
<span style="box-sizing: border-box;">---</span>
<span style="box-sizing: border-box;">say</span><span style="box-sizing: border-box;">: One</span>
<span style="box-sizing: border-box;">...</span>
<span style="box-sizing: border-box;">---</span>
<span style="box-sizing: border-box;">say</span><span style="box-sizing: border-box;">: Hello World</span>
<span style="box-sizing: border-box;">...</span>
<span style="box-sizing: border-box;">---</span>
<span style="box-sizing: border-box;">say</span><span style="box-sizing: border-box;">: Three</span>
<span style="box-sizing: border-box;">...</span>
</pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3768 lazyloaded" data-sizes="(max-width: 610px) 100vw, 610px" data-src="https://chronicle.software/wp-content/uploads/2022/05/Img5.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/Img5.png 1292w, https://chronicle.software/wp-content/uploads/2022/05/Img5-300x109.png 300w, https://chronicle.software/wp-content/uploads/2022/05/Img5-1024x371.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/Img5-768x278.png 768w" height="221" sizes="(max-width: 610px) 100vw, 610px" src="https://chronicle.software/wp-content/uploads/2022/05/Img5.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/Img5.png 1292w, https://chronicle.software/wp-content/uploads/2022/05/Img5-300x109.png 300w, https://chronicle.software/wp-content/uploads/2022/05/Img5-1024x371.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/Img5-768x278.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="610" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Not only does the test fail, I can also click on the differences to see why.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3769 lazyloaded" data-sizes="(max-width: 468px) 100vw, 468px" data-src="https://chronicle.software/wp-content/uploads/2022/05/Img6.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/Img6.png 1058w, https://chronicle.software/wp-content/uploads/2022/05/Img6-300x168.png 300w, https://chronicle.software/wp-content/uploads/2022/05/Img6-1024x573.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/Img6-768x430.png 768w" height="262" sizes="(max-width: 468px) 100vw, 468px" src="https://chronicle.software/wp-content/uploads/2022/05/Img6.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/Img6.png 1058w, https://chronicle.software/wp-content/uploads/2022/05/Img6-300x168.png 300w, https://chronicle.software/wp-content/uploads/2022/05/Img6-1024x573.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/Img6-768x430.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="468" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">At this point, I can either fix the test or accept the change by copying and pasting the actual result over the expected result in the out.yaml file.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">In the next post, we will see how to implement more realistic example processing orders and automate many microservice tests from the configuration. This provides a basis for creating highly performant, deterministic, redundant microservices.</span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Conclusion</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">This article shows the outline of creating and testing a simple microservice, which provides the basis for microservices which are easy to deploy and maintain.</span></p>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-14086811075082920282022-05-19T11:48:00.000+00:002022-08-02T10:30:10.740+00:00How Behaviour Driven Development Works Well with Event Driven Architectures<p> <span style="background-color: white; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px;">Behaviour Driven Development (BDD) and Event-Driven Architecture (EDA) work well together as they complement each other’s strengths and weaknesses. Using both can result in a shorter time to market for new functionality and a more maintainable system.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box; font-weight: 700;">Behaviour Driven Development</span> encourages a common language between users and developers in describing requirements in a form the users can understand but can also automatically be checked as the application is developed and maintained. BDD increases the inclusion of users, focuses on requirements capture and maintains the development velocity as the application increases in complexity.</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="wp-image-3716 alignnone lazyloaded" data-sizes="(max-width: 779px) 100vw, 779px" data-src="https://chronicle.software/wp-content/uploads/2022/05/1-1.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/1-1.png 1380w, https://chronicle.software/wp-content/uploads/2022/05/1-1-300x157.png 300w, https://chronicle.software/wp-content/uploads/2022/05/1-1-1024x537.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/1-1-768x403.png 768w" height="409" sizes="(max-width: 779px) 100vw, 779px" src="https://chronicle.software/wp-content/uploads/2022/05/1-1.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/1-1.png 1380w, https://chronicle.software/wp-content/uploads/2022/05/1-1-300x157.png 300w, https://chronicle.software/wp-content/uploads/2022/05/1-1-1024x537.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/1-1-768x403.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="779" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><i style="box-sizing: border-box;">Figure 1. Behaviour Driven Development for the high level with Test Driven Development for the low level</i></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="wp-image-3717 alignnone lazyloaded" data-sizes="(max-width: 755px) 100vw, 755px" data-src="https://chronicle.software/wp-content/uploads/2022/05/2-1.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/2-1.png 1328w, https://chronicle.software/wp-content/uploads/2022/05/2-1-300x92.png 300w, https://chronicle.software/wp-content/uploads/2022/05/2-1-1024x313.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/2-1-768x235.png 768w" height="231" sizes="(max-width: 755px) 100vw, 755px" src="https://chronicle.software/wp-content/uploads/2022/05/2-1.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/2-1.png 1328w, https://chronicle.software/wp-content/uploads/2022/05/2-1-300x92.png 300w, https://chronicle.software/wp-content/uploads/2022/05/2-1-1024x313.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/2-1-768x235.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="755" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><i style="box-sizing: border-box;">Table 1. Pros and Cons of Behaviour-Driven Development</i></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box; font-weight: 700;">Event-Driven Architecture</span><span style="box-sizing: border-box;"> models interactions between services as events. Events are facts about something that happened to represent a state change, such as an order placed or a payment processed, without implying which action, if any must be taken, unlike request/response or actor patterns. EDA supports loosely coupled services, greater fault tolerance, and observable interactions between services can help minimise technical debt.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="wp-image-3718 alignnone lazyloaded" data-sizes="(max-width: 764px) 100vw, 764px" data-src="https://chronicle.software/wp-content/uploads/2022/05/3-1.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/3-1.png 1410w, https://chronicle.software/wp-content/uploads/2022/05/3-1-300x183.png 300w, https://chronicle.software/wp-content/uploads/2022/05/3-1-1024x626.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/3-1-768x470.png 768w" height="467" sizes="(max-width: 764px) 100vw, 764px" src="https://chronicle.software/wp-content/uploads/2022/05/3-1.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/3-1.png 1410w, https://chronicle.software/wp-content/uploads/2022/05/3-1-300x183.png 300w, https://chronicle.software/wp-content/uploads/2022/05/3-1-1024x626.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/3-1-768x470.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="764" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><i style="box-sizing: border-box;">Figure 2. Example of an Event Driven Kappa Architecture microservice with feedback</i></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="alignnone wp-image-3719 lazyloaded" data-sizes="(max-width: 762px) 100vw, 762px" data-src="https://chronicle.software/wp-content/uploads/2022/05/4-1.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/4-1.png 1304w, https://chronicle.software/wp-content/uploads/2022/05/4-1-300x115.png 300w, https://chronicle.software/wp-content/uploads/2022/05/4-1-1024x393.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/4-1-768x294.png 768w" height="292" sizes="(max-width: 762px) 100vw, 762px" src="https://chronicle.software/wp-content/uploads/2022/05/4-1.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/4-1.png 1304w, https://chronicle.software/wp-content/uploads/2022/05/4-1-300x115.png 300w, https://chronicle.software/wp-content/uploads/2022/05/4-1-1024x393.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/4-1-768x294.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="762" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><i style="box-sizing: border-box;">Table 2. Pros and Cons of Event-Driven Architectures</i></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box; font-weight: 700;">Regression Tests</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">When we came to design our kitchen recently, there were some things we knew we wanted but couldn’t imagine the details. However, once we could see an initial design based on what we knew we wanted, we were able to get down to the details.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Designing applications can be similar. There are things we know upfront, but there are other things we can only decide on once we see it come to life. EDA makes it natural to record what the application does do, in an easily observable way, and construct a test to ensure this behaviour doesn’t change. From the output of such a test, the user can see with each iteration, how they wish to customise the event processor or microservice, rather than having to specify all the details in advance.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="wp-image-3720 alignnone lazyloaded" data-sizes="(max-width: 627px) 100vw, 627px" data-src="https://chronicle.software/wp-content/uploads/2022/05/5.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/5.png 1106w, https://chronicle.software/wp-content/uploads/2022/05/5-300x185.png 300w, https://chronicle.software/wp-content/uploads/2022/05/5-1024x631.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/5-768x474.png 768w" height="386" sizes="(max-width: 627px) 100vw, 627px" src="https://chronicle.software/wp-content/uploads/2022/05/5.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/5.png 1106w, https://chronicle.software/wp-content/uploads/2022/05/5-300x185.png 300w, https://chronicle.software/wp-content/uploads/2022/05/5-1024x631.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/5-768x474.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="627" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><i style="box-sizing: border-box;">Figure 3. Using known inputs and designed output to iteratively specify a requirement</i></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box; font-weight: 700;">How BDD and EDA are More Effective in Combination</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">EDA naturally supports the recording and replaying of events produced by each microservice. EDA allows regression tests to be constructed and maintained easily with minimal input from end-users. While BDD benefits from responsive feedback from users, building regression tests can help in that process so users can see how they want to customise the behaviour. Utilising event-driven regression tests reduces the need for users to be always available to give feedback on incremental improvements.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">BDD naturally supports the development of a common language between all microservices when microservices could quickly diverge without someone who can authoritatively say how things should be named. The common language can be referred to in code and kept consistent by having a shared schema of events and data transfer objects.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="wp-image-3721 alignnone lazyloaded" data-sizes="(max-width: 887px) 100vw, 887px" data-src="https://chronicle.software/wp-content/uploads/2022/05/6.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/05/6.png 1414w, https://chronicle.software/wp-content/uploads/2022/05/6-300x118.png 300w, https://chronicle.software/wp-content/uploads/2022/05/6-1024x403.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/6-768x302.png 768w" height="349" sizes="(max-width: 887px) 100vw, 887px" src="https://chronicle.software/wp-content/uploads/2022/05/6.png" srcset="https://chronicle.software/wp-content/uploads/2022/05/6.png 1414w, https://chronicle.software/wp-content/uploads/2022/05/6-300x118.png 300w, https://chronicle.software/wp-content/uploads/2022/05/6-1024x403.png 1024w, https://chronicle.software/wp-content/uploads/2022/05/6-768x302.png 768w" style="border: 0px; box-sizing: border-box; height: auto; margin: 5px 20px 20px 0px; max-width: 100%; vertical-align: middle;" width="887" /></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><i style="box-sizing: border-box;">Figure 4. Simplified EDA used by a number of our customers</i></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Recording the outputs of EDA microservices makes it easy to create test input data for new services. In many cases, you can start by determining the output events you need to produce and then recording the events produced by existing systems for the inputs. BDD can determine functionality requirements to turn inputs into outputs. Breaking this functionality into stages, you can construct the events that should occur at the stages in between.</span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Microservices Framework</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><a href="http://chronicle.software/" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">Chronicle Software</span></a><span style="box-sizing: border-box;"> has a testing methodology and libraries for the behaviour-driven development of event-driven systems. This methodology will be introduced in the following article.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Our </span><a href="https://chronicle.software/services-2/" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">microservice framework</span></a><span style="box-sizing: border-box;"> supports low latency; it uses restartable, scalable, distributed, highly available processes that are </span><i style="box-sizing: border-box;">very </i><span style="box-sizing: border-box;">easy to test and debug.</span></p><h2 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Conclusion</span></h2><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">We have used Behaviour Driven Development to establish the application’s requirements from users, and Behaviour Driven Development to automate testing to ensure the application meets those requirements as it is developed and changes are made to add more functionality. We believe this is a very effective way to build and maintain back-end real-time software.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Event-Driven Architecture decomposes complex interactions into easily describable and testable components for real-time streaming data processing.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">Using both together provides a uniquely productive environment to deliver complex functionality.</span></p>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-91983327240657325782022-04-27T11:48:00.001+00:002022-08-02T10:24:55.786+00:00The More You Say, the Less People Remember The Fewer the Words, the Greater the Profit<p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">These wise words were written by François Fénelon, a writer and theologian living during the 17th century. This is an article summarising different approaches to the development of IT solutions. Learn why the above quote is very relevant for developers in the 21st century.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><a href="https://en.wikipedia.org/wiki/Business-driven_development" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">Business-driven development</span></a><span style="box-sizing: border-box;"> is a meta-methodology for developing IT solutions that directly satisfy </span><a href="https://en.wikipedia.org/wiki/Requirement" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">business requirements</span></a><span style="box-sizing: border-box;">. This leads to increased flexibility and shorter turnaround times when changing the business and adapting the IT systems. </span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">This is achieved by adopting a </span><a href="https://en.wikipedia.org/wiki/Model-driven_engineering" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">model-driven</span></a><span style="box-sizing: border-box;"> approach that starts with the business strategy, requirements and goals and then refines and transforms them into an IT solution. Due to the alignment of the business and IT layers, it is possible to propagate changes in the business automatically to the IT systems. </span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">This is partially replaced by Domain-Driven Design and Behaviour Driven Development in Agile terminology. </span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><a href="https://en.wikipedia.org/wiki/Domain-driven_design" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">Domain-Driven Design</span></a><span style="box-sizing: border-box;"> is a means of capturing requirements from domain experts to automate a business process using a common language.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><a href="https://en.wikipedia.org/wiki/Behavior-driven_development" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">Behaviour Driven Development</span></a><span style="box-sizing: border-box;"> is a means of automating the testing of an application as a high-level description of what the application must do. This is a form of </span><a href="https://en.wikipedia.org/wiki/Test-driven_development" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">Test-Driven Development</span></a><span style="box-sizing: border-box;"> that uses inputs, and expected results are modelled as data, e.g. events, data structures, or tables in a </span><a href="https://en.wikipedia.org/wiki/Domain-specific_language" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">Domain Specific Language</span></a><span style="box-sizing: border-box;">, rather than in code, allowing these descriptions of functional requirements to be written before coding starts, and automatically checked when code changes.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">To divide the functionality into easily maintainable, deployable, and replaced parts, a </span><a href="https://en.wikipedia.org/wiki/Service-oriented_architecture" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">Service Orientated Architecture</span></a><span style="box-sizing: border-box;"> models the applications as a collection of microservices. SOA is often implemented with request/response APIs to support user interfaces. However, backend automated services where servers communicate with other services are more efficient when an </span><a href="https://en.wikipedia.org/wiki/Event-driven_architecture" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">Event-Driven Architecture</span></a><span style="box-sizing: border-box;"> is used, allowing a higher volume of concurrent events to be in flight at once.</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><span style="box-sizing: border-box;">While all these things are important during the development of a project, a solution can easily cost many times its initial development over its lifetime. It is worth spending time on </span><a href="https://en.wikipedia.org/wiki/KISS_principle" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;">Keeping it Simple</span></a><span style="box-sizing: border-box;"> to reduce the cost of maintaining it.</span> <span style="box-sizing: border-box;">This is something I am always trying to fulfil in</span><a href="https://chronicle.software/" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><span style="box-sizing: border-box; font-weight: 400;"> the Chronicle libraries</span></a>,<span style="box-sizing: border-box;"> regardless if it is an Open Source project or Enterprise project. Let’s finish with my favourite quote about engineering from the French writer Antoine de Saint Exupéry: </span><span style="box-sizing: border-box; font-weight: 700;">“It seems that perfection is reached not when there is nothing left to add, but when there is nothing left to take away”</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"> </p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px; overflow-wrap: break-word;"><img alt="" class="aligncenter wp-image-3569 size-full ls-is-cached lazyloaded" data-sizes="(max-width: 2000px) 100vw, 2000px" data-src="https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM.png" data-srcset="https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM.png 2000w, https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM-300x153.png 300w, https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM-1024x521.png 1024w, https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM-768x391.png 768w, https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM-1536x782.png 1536w" height="1018" sizes="(max-width: 2000px) 100vw, 2000px" src="https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM.png" srcset="https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM.png 2000w, https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM-300x153.png 300w, https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM-1024x521.png 1024w, https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM-768x391.png 768w, https://chronicle.software/wp-content/uploads/2022/04/Screen-Shot-2022-04-29-at-9.21.06-AM-1536x782.png 1536w" style="border: 0px; box-sizing: border-box; clear: both; display: block; height: auto; margin: 5px auto; max-width: 100%; vertical-align: middle;" width="2000" /></p>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-30985036436160941222022-04-14T11:59:00.020+00:002022-12-06T12:05:19.959+00:00Nine Core Java Questions<p>
My previous post with <a href="https://blog.vanillajava.blog/2022/04/eight-core-java-questions.html">Eight Core Java Questions</a> was popular so I created nine more.
</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjd0jtbssJkwkmM2tkAXJgIT7pta7zeKKtTyye15Qioc_y4AyJ5oRMGf1hUcEQOmTvyJWEL1E7sCWoPDzZgFThJhGilBvwBc6bL5lchp2VviE7NHk3YsxNetqWGR2_wkcwOHuYnaqL9kBK1vR3ai99qBifNs5OAg2sbTQASTaxN0R7v0dZip8ES9GllZA/s393/java-lang.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="393" data-original-width="393" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjd0jtbssJkwkmM2tkAXJgIT7pta7zeKKtTyye15Qioc_y4AyJ5oRMGf1hUcEQOmTvyJWEL1E7sCWoPDzZgFThJhGilBvwBc6bL5lchp2VviE7NHk3YsxNetqWGR2_wkcwOHuYnaqL9kBK1vR3ai99qBifNs5OAg2sbTQASTaxN0R7v0dZip8ES9GllZA/s320/java-lang.png"/></a></div>
<p>
Please join the discussion of the answers for these questions on Twitter
</p>
<h2>1.</h2>
<p><a href="https://twitter.com/PeterLawrey/status/1514960409215832066?s=20&t=1uieAeSSIpQokxyKY3umJA" target="_blank">Comment on this question</a><br>
How many elements does this set have?</p>
<pre>
Set set = new HashSet(Arrays.asList(
-0, +0, -0L, +0L, -0F, 0F, -0D, 0D, 0xF, 0xD, 0x0.DP+0));
System.out.println(set.size());
</pre>
<ol type="A">
<li>12</li>
<li>1</li>
<li>6</li>
<li>9</li>
</ol>
<h2>2.</h2>
<p><a href="https://twitter.com/PeterLawrey/status/1514576425696772099" target="_blank">Comment on this question</a><br>
This compiles in Java 17 due to</p>
<pre>
static int[] a(int[]... a)[] { return a; }
static final int one = a(new int[0]).length; // 1
</pre>
<ol type="A">
<li>It confuses the compiler</li>
<li>It’s a static method</li>
<li>Backward Compatibility</li>
<li>JEP 747</li>
</ol>
<h2>3.</h2>
<p><a href="https://twitter.com/PeterLawrey/status/1514577333138636800" target="_blank">Comment on this question</a><br>
The code below prints "23 & 52" the following due to</p>
<pre>
System.out.println(
new BigDecimal(2.008f).toString().length() + " & " +
new BigDecimal(2.008).toString().length());
</pre>
<ol type="A">
<li>A bug in Java 23</li>
<li>The randomness of floating-point</li>
<li>Length of the mantissa</li>
<li>Magic numbers</li>
</ol>
<h2>4.</h2>
<p><a href="https://twitter.com/PeterLawrey/status/1514578518717390850" target="_blank">Comment on this question</a><br>
This code prints "hello world" due to</p>
<pre>
public static void main(String[] args) {
System.out.println(r(604568751) + " " + r(401174283));
}
public static String r(int num) {
return Integer.toUnsignedString(new Random(num).nextInt(), 33);
}
</pre>
<ol type="A">
<li>Secret code in Java</li>
<li>Using Magic numbers</li>
<li>A bug in Java 13</li>
<li>(char) 33 is '!'</li>
</ol>
<h2>5.</h2>
<p><a href="https://twitter.com/PeterLawrey/status/1514579058255925249" target="_blank">Comment on this question</a><br>
This is class is</p>
<pre>
public class StackTrace extends Throwable { }
</pre>
<ol type="A">
<li>An unchecked exception</li>
<li>A checked exception</li>
<li>Neither</li>
<li>A compilation error</li>
</ol>
<h2>6.</h2>
<a href="https://twitter.com/PeterLawrey/status/1600098998643093504" target="_blank">Comment on this question</a><br>
<p>This code prints the following in Java 17</p>
<pre>
public static void main(String[] args) {
test(new IdentityHashMap<>());
test(new WeakHashMap<>());
test(new ConcurrentSkipListMap<>());
}
static void test(Map<String, Integer> map) {
map.computeIfAbsent("key", (String k) -> {
map.putIfAbsent(k, 2);
return 1;
});
System.out.println(map.getClass().getSimpleName() + " " + map);
}
IdentityHashMap {key=1}
WeakHashMap {key=1}
ConcurrentSkipListMap {key=2}
</pre>
<ol type="A">
<li>It depends on whether the map is concurrent or not</li>
<li>It’s a memory leak</li>
<li>It's a thread safety issue</li>
<li>The behaviour is undefined.</li>
</ol>
<h2>7.</h2>
<p><a href="https://twitter.com/PeterLawrey/status/1514579523127361542" target="_blank">Comment on this question</a><br>
In Java 17, the stack trace StackTraceElement[] of a Throwable is created when</p>
<ol type="A">
<li>It is thrown</li>
<li>It is used for the first time</li>
<li>Never really exists</li>
<li>The Throwable is created</li>
</ol>
<h2>8.</h2>
<p><a href="https://twitter.com/PeterLawrey/status/1514582852800765961" target="_blank">Comment on this question</a><br>
If -Dfalse=true is set on the command line, which of these is true</p>
<ol type="A">
<li>(Boolean) false</li>
<li>Boolean.parseBoolean("false")</li>
<li>Boolean.getBoolean("false")</li>
<li>"true" == "false"</li>
</ol>
<h2>9.</h2>
<p><a href="https://twitter.com/PeterLawrey/status/1514583233245102083" target="_blank">Comment on this question</a><br>
This expression is true for powers of 2 and one other value.</p>
<pre>
n & ( n - 1 ) == 0
</pre>
<ol type="A">
<li>Integer.MAX_VALUE</li>
<li>Character.MIN_VALUE</li>
<li>Double.MIN_VALUE</li>
<li>Float.NaN</li>
</ol>
<h2>Hint</h2>
<p>In the questions above, there are a total of three answers for each for B, C,and D</p>
Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-84192248950101401622022-04-05T21:06:00.014+00:002022-04-06T07:59:31.852+00:00Eight Core Java Questions<p>
Please join the discussion of the answers for these questions on Twitter
</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjd0jtbssJkwkmM2tkAXJgIT7pta7zeKKtTyye15Qioc_y4AyJ5oRMGf1hUcEQOmTvyJWEL1E7sCWoPDzZgFThJhGilBvwBc6bL5lchp2VviE7NHk3YsxNetqWGR2_wkcwOHuYnaqL9kBK1vR3ai99qBifNs5OAg2sbTQASTaxN0R7v0dZip8ES9GllZA/s393/java-lang.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="393" data-original-width="393" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjd0jtbssJkwkmM2tkAXJgIT7pta7zeKKtTyye15Qioc_y4AyJ5oRMGf1hUcEQOmTvyJWEL1E7sCWoPDzZgFThJhGilBvwBc6bL5lchp2VviE7NHk3YsxNetqWGR2_wkcwOHuYnaqL9kBK1vR3ai99qBifNs5OAg2sbTQASTaxN0R7v0dZip8ES9GllZA/s320/java-lang.png"/></a></div>
<p>
The answers to each question can be combined for a bonus question at the end.
</p>
<h2>1.</h2>
<p>Which of these is NOT a means of communicating between processes in Core Java.
<a href="https://twitter.com/PeterLawrey/status/1511452574146306055" target="_blank">Comment on Twitter</a>
</p>
<ol type="A">
<li>UDP</li>
<li>Pipes/Files</li>
<li>Pass by reference</li>
<li>TCP</li>
</ol>
<h2>2.</h2>
<p>Which of these methods of copying an object is the LEAST efficient?
<a href="https://twitter.com/PeterLawrey/status/1511453641198157827" target="_blank">Comment on Twitter</a>
</p>
<ol type="A">
<li>Java Serialization</li>
<li>clone()</li>
<li>Copying field by field</li>
<li>Using a builder</li>
</ol>
<h2>3.</h2>
<p>Which of these is the lowest amount of time
<a href="https://twitter.com/PeterLawrey/status/1511454769705111558" target="_blank">Comment on Twitter</a>
</p>
<ol type="A">
<li>A micro-day</li>
<li>A nano-year</li>
<li>0.001 seconds</li>
<li>A millsecond</li>
<li>A million nanoseconds</li>
<li>100 microseconds</li>
</ol>
<h2>4.</h2>
<p>This loop doesn’t throw an Exception
<a href="https://twitter.com/PeterLawrey/status/1511455964519673857" target="_blank">Comment on Twitter</a>
</p>
<p>List<String> words = new ArrayList<>(Arrays.asList("one,two,three".split(",")));<br />
for (String word : words)<br />
if (word.startsWith("t"))<br />
words.remove(word);</p>
<p>Because</p>
<ol type="A">
<li>It’s in proportional font</li>
<li>A thread safety race condition</li>
<li>It is looping over an array</li>
<li>Arrays.asList() cannot be resized</li>
<li>The Iterator first compares the number of iterations against the size</li>
</ol>
<h2>5.</h2>
<p>By the time the OpenJDK JVM has started the main() method, roughly how many Strings does it create
<a href="https://twitter.com/PeterLawrey/status/1511603146371612676" target="_blank">Comment on Twitter</a></p>
<ol type="A">
<li>No strings</li>
<li>5,000 Strings</li>
<li>5 Strings</li>
<li>A million strings</li>
</ol>
<h2>6.</h2>
<p>The stack trace of a Throwable shows where it was
<a href="https://twitter.com/PeterLawrey/status/1511603763919921152" target="_blank">Comment on Twitter</a></p>
<ol type="A">
<li>Instantiated</li>
<li>Thrown</li>
<li>On the try line</li>
<li>On the caught line</li>
<li>On the finally line</li>
</ol>
<h2>7.</h2>
<p>Which double value can be represented without representation error
<a href="https://twitter.com/PeterLawrey/status/1511604921875013635" target="_blank">Comment on Twitter</a></p>
<ol type="A">
<li>1.28</li>
<li>128.0</li>
<li>0.1</li>
<li>3.14159265358979323846</li>
</ol>
<h2>8.</h2>
<p>On Linux, if a text file is redirected to standard input, you can read it concurrently by using
<a href="https://twitter.com/PeterLawrey/status/1511604478792904707" target="_blank">Comment on Twitter</a></p>
<ol type="A">
<li>Horizontal scalability</li>
<li>Calling read() from multiple threads</li>
<li>Stream.parallel()</li>
<li>Adding a REST API</li>
<li>Memory mapping /proc/self/fd/0 and partitioning it</li>
</ol>
<h2>Bonus Question.</h2>
<p>Take the answers to the 8 questions above</p>
<pre> _ _ _ _ _ _ _ _ </pre>
<p>As a hexadecimal number, what is it’s significance to the JVM?
</p>
<p>To learn more about <a href="https://en.wikipedia.org/wiki/Hexspeak">Hexspeak</a></p>
<h2>We are hiring</h2>
<p>If you enjoyed this and would like to help solve difficult problems in low level Java, please consider applying <a href="https://chronicle.software/careers/">https://chronicle.software/careers/</a></p>
Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-22078239066525310142022-01-20T09:51:00.011+00:002022-01-20T15:28:52.705+00:00Benchmarking Kafka vs Chronicle for Microservices: which is 750 times faster?<div>
<p style="font-family: arial;">Apache Kafka is a common choice for inter-service communication. Kafka facilitates the parallel processing of messages and is a good choice for log aggregation. Kafka <a href="https://www.confluent.io/blog/kafka-fastest-messaging-system/" target="_blank">claims to be low latency, high throughput</a>. However, is Kafka fast enough for many microservices applications in the cloud?</p>
<p style="font-family: arial; text-align: left;">When I wrote <a href="https://chronicle.software/open-hft/queue/" target="_blank">Chronicle Queue Open Source</a> my aim was to develop a messaging framework with microsecond latencies, and banks around the world have adopted it for use in their latency-sensitive trading systems.</p>
<p style="font-family: arial; text-align: left;">In this article, I will describe how Kafka does not scale in terms of throughput as easily as Chronicle Queue for microservices applications. As a teaser, I will show you this chart showing that Chronicle Queue is around <b>750 times</b> faster even for lower throughput.</p>
<h2 style="text-align: left;">Visualising delay as a distance</h2>
<p style="font-family: arial; text-align: left;">In order to illustrate the difference, let me start with an analogy. Light travels through optic fibre and copper at about two thirds the speed of light in a vacuum, so to appreciate very short delays, they can be visualised as the distance a signal can travel in the time. This can really matter when you have machines in different data centres.</p>
</div>
<div>
<h4>Microservice latency using Chronicle</h4>
<p style="font-family: arial; text-align: left;">The 99%ile single microservice end-to-end latency for Chronicle Queue Enterprise at 500 kmsg/s was 3.69 microseconds or about a 10-minute walk in central London.</p>
<img src="https://lh3.googleusercontent.com/DNM65M2dR67C8EBYjxLL_TnD-KaC7mTtqoU_0pmih2OCj5nz0PvDhng7ywZBPZXgzrcfT7OK0DrkWarpJj6r3Vexc5CL9pzH0me_nwlyelbvNm1hqZUv-n8GyMakDd0doaK-oED1=s16000" style="font-family: inherit; margin-left: 0px; margin-top: 0px; white-space: pre-wrap;" />
</div>
<div>
<h4>Microservice latency using Kafka</h4>
<p style="font-family: arial; white-space: pre-wrap;">Using Kafka for the same test, but at a lower throughput of 100 kmsg/s the 99%ile single-stage microservice end-to-end latency was around 2633 microseconds (from 150kmsg/s, the latencies increase dramatically) This is the time it takes a signal to travel 526 km, a distance of about the same as walking from London to Amsterdam.</p>
<img src="https://lh6.googleusercontent.com/QEov-Rn_fVqMPViissuYKX2vGaIhQXDjswhBqcyaWVap9obrlMQiO8KI8jv5NTvt-lP0vsFrkNrlDoaWhwbNR0dCk-DH9PUW1zGfIuVlOnjbUCVHIprVvq3qLNJjzEoButIrYSMs=s16000" style="margin-left: 0px; margin-top: 0px;" />
</div>
<div>
<h2>Log Aggregation</h2>
<p style="font-family: arial; white-space: pre-wrap;">Kafka was originally designed for log aggregation. It has many connectors and for this use case, it does an excellent job. I measured good results which show using Kafka to replace writing to log files in a typical system could improve performance as well as give significantly more manageability. https://docs.confluent.io/cloud/current/client-apps/optimizing/latency.html</p>
<h4>Test Scenarios</h4>
<p style="font-family: arial; white-space: pre-wrap;">In each case, the same test hardness was used. Everything was deployed onto a Ryzen 9 5950X running Ubuntu 21.04. The same MP600 PRO XT 2TB M.2 NVMe drive was used in all tests. The source for the benchmark is available here. https://github.com/OpenHFT/Microservice-Benchmark</p>
<ul style="text-align: left;"><li><span style="font-family: arial;"><span style="white-space: pre-wrap;">Chronicle Queue open-source v5.22ea14 writing at 500 k messages/second, using Chronicle Wire for serialization. Single producer (and a single consumer downstream)
</span>-Dworkload=500kps.yaml chronicle.yaml<br /><br /></span></li><li><span style="font-family: arial;"><span style="white-space: pre-wrap;">Chronicle Queue Enterprise v2.22ea72 writing at 500 k messages/second, using Chronicle Wire for serialization, Single producer in Asynchronous buffer mode (and a single consumer downstream)
</span>-Dworkload=500kps.yaml chronicle-async.yaml<br /><br /></span></li><li><span style="font-family: arial;"><span style="white-space: pre-wrap;">Kafka 3.0.0 with Jackson writing JSON at 100 k message/second in high throughput latency configuration (primarily linger.ms=1) Four partitions and eight consumers
</span>-Dworkload=100kps.yaml kafka.yaml<br /><br /></span></li><li><span style="font-family: arial;"><span style="white-space: pre-wrap;">Kafka 3.0.0 with Jackson writing JSON at 250 k message/second in high throughput latency configuration (primarily linger.ms=1) Four partitions and eight consumers.
</span>-Dworkload=250kps.yaml kafka.yaml</span></li></ul>
</div>
<div>
<h3>Notes</h3>
<p style="font-family: arial; white-space: pre-wrap;">The number of partitions and consumers were selected which produced the best latencies 99.99% of the time.</p>
<p style="font-family: arial; white-space: pre-wrap;">For Chronicle Queue, the performance of 100 kmsg/s or 500 kmsg/s was much the same so I included the 500 kmsg/s results. One publisher, one consumer and one microservice were used.</p>
<p style="font-family: arial; white-space: pre-wrap;">Benchmarking Kafka at 500kmsg/s messages resulted in messages queuing, with latencies increasing the longer the benchmark ran. I.e. a 2-minute burst resulted in a typical latency of close to 1 minute.</p>
<p style="font-family: arial; white-space: pre-wrap;">For Kafka to process 250kmsg/s messages, at least four were needed, and a benchmark with eight is reported here as this produced a better result. My understanding is this is a recommended scaling technique for Kafka.</p>
<p style="font-family: arial; white-space: pre-wrap;">The low latency configuration (linger.ms=0) failed for throughputs over 25 kmsg/s from a single producer.</p>
</div>
<div>
<h3>Publish Latency</h3>
<p style="font-family: arial; white-space: pre-wrap;">As can be seen, the typical latency to publish is comparable. However, the outliers are much higher. Depending on the use case, the performance difference might not matter, and the typical publish latency across tests was no more than 2.6 microseconds.</p>
<img src="https://lh3.googleusercontent.com/L3Y5F5i2TDHOdPxn5iKrYfnErSVJmXDc2xFOXo5we1IkIIaZ64h18rfGfK0Tk3V0bgc5b0RVs9Xe_1rzDeDa4CWArBwYkpgNxG9jHWdijKqzTpy34b97SRG9sloKj8H_OFlrQlrV=s16000" style="margin-left: 0px; margin-top: 0px;" />
<p style="font-family: arial; white-space: pre-wrap;">In each case, the same event is published which is 512 bytes long as JSON. Two fields were added to trace when the message was sent.</p><p style="font-family: arial; white-space: pre-wrap;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-zJR87vdazQM/Yekp_rln_vI/AAAAAAAASrY/_Fc5l7zjgSAZ3w9MCCiuwBtIje3RFKY2ACNcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"><img data-original-height="759" data-original-width="843" height="576" src="https://lh3.googleusercontent.com/-zJR87vdazQM/Yekp_rln_vI/AAAAAAAASrY/_Fc5l7zjgSAZ3w9MCCiuwBtIje3RFKY2ACNcBGAsYHQ/w640-h576/image.png" width="640" /></a></div><br /><br /><p></p>
</div>
<div>
<h2>Microservice Messaging Transport</h2>
<p style="font-family: arial; white-space: pre-wrap;">While the time to publish, or the time to send/receive a pre-serialized message can be a good comparison of messaging solutions, this is only a piece of the puzzle. For microservices, you need to know from the time you have a DTO describing the event to process until a downstream consumer reads the resulting DTO from the original microservice.</p>
<p style="font-family: arial; white-space: pre-wrap;">For a microservices benchmark, we look at the time to send the same event as above, end to end.</p>
<div style="text-align: left;"><ul style="text-align: left;"><li><span style="font-family: arial;">Add a high-resolution timestamp (System.nanoTime())</span></li><li><span style="font-family: arial;">Serialize the first message</span></li><li><span style="font-family: arial;">Publish the first message</span></li><li><span style="font-family: arial;">Consume the first message</span></li><li><span style="font-family: arial;">Deserialize the first message</span></li><li><span style="font-family: arial;">Call the microservice</span></li><li><span style="font-family: arial;">Add a second high-resolution timestamp</span></li><li><span style="font-family: arial;">Serialize the second message on another topic/queue</span></li><li><span style="font-family: arial;">Publish the second message</span></li><li><span style="font-family: arial;">Consumer the second message</span></li><li><span style="font-family: arial;">Deserialize the second message.</span></li><li><span style="font-family: arial;">Record the end to end latency</span></li></ul></div>
</div>
<div><span style="font-family: arial;">NOTE: every message produced creates a second message as a response, so the actual number of messages is doubled compared to a single-hop messaging benchmark.</span></div>
<div>
<h3>How does Kafka Perform in Their Published Benchmarks?</h3>
<p style="font-family: arial; text-align: left;">While publishing events on Kafka typically takes single-digit microseconds, the end to end transport can take milliseconds.</p>
<p style="font-family: arial; text-align: left;">Confluent published a benchmark that is one-hop but includes replicated messaging. They report 99 percentile (worst 1 in 100) latencies of 5 milliseconds for an end to end time.<br /><a href="https://www.confluent.io/blog/kafka-fastest-messaging-system/">https://www.confluent.io/blog/kafka-fastest-messaging-system/</a></p>
<p style="font-family: arial; text-align: left;">In our benchmark, we have two hops, serialization and deserialization, all on one host. I expect that for 100k msg/s out and 100k msg/s returned we should get a similar delay as 200 k msg/s over a single hop.</p>
</div>
<div>
<h3 style="text-align: left;">End to End Latency</h3>
<p style="font-family: arial;">It’s hard to illustrate how much lower latency Chronicle exhibits compared to Kafka, so in the series of charts below, each chart also has a zoomed out version at 10x the scale of the previous one.</p>
</div>
<div>
<h4>Latencies up to 100 microseconds</h4>
<p style="font-family: arial;">With the same scale as we had before, it can be seen that Chronicle Queue Enterprise has consistent latencies even across two hops including serialization. Chronicle Queue open-source performs much the same, most of the time, however, it has much higher latencies. Chronicle Queue Enterprise includes specific features (over open source) to better control outliers. You can’t see Kafka in this chart as the latencies are all much higher.</p>
<img src="https://lh6.googleusercontent.com/l9OEWi1hClKNzBNmqi-J7e3yvNLj0NXYxZ_tb6zkWmCt4SGEib2gMcbz99ym_LtYTZp3YjC7fRdCw0VBdsZjoP1mXb4V6_GCdiaL37V2jwyjBfh1kZlv4VrMBlCgE0qk1SpeFeVr=s16000" style="margin-left: 0px; margin-top: 0px;" />
</div>
<div>
<h4>Latencies up to 1000 microseconds</h4>
<p style="font-family: arial; white-space: pre-wrap;">The chart below has a 10x scale, and it can be seen that while Chronicle Queue has higher outliers they are reasonably consistent up to the 99.99 percentile. Kafka is yet to appear.</p>
<img src="https://lh5.googleusercontent.com/q0O4_bR6CcmCeM7a9gpLQbVBYHLAJmP_55QqtyfAZaW3agN1EHBzXWYGTL1EW9YSn5D64BEfFwwWtDVPq5SQo_OzLTy-6Uj5zUQdPj17-LZThBRbxm3ztzCCnJJvoZGeoLnptpjv=s16000" style="margin-left: 0px; margin-top: 0px;" />
</div>
<div>
<h4>Latencies up to 10,000 microseconds</h4>
<p style="font-family: arial; white-space: pre-wrap;">The chart below has a scale again made 10x larger. In this scale, not much detail can be seen for the Chronicle benchmarks, but the typical latencies for two of the Kafka configurations now appear. In particular, it can be seen that the 99% latency for 100 kmsg/s (200kmsg/s total) is around 2,630 microseconds, similar to the 5 milliseconds for Confluent's benchmark.</p>
<img src="https://lh4.googleusercontent.com/ZwwvyDPJqOZUojfRG36bdRutWGL6ccgg5dAwnO328dbKbLqCGsN1ljuy0inus8xemoZvWULDmWkipyGZeW0KZX1fp8ssPqH1tU6KL7kgHXZ9eIi1j9wweIzsT2cxx9VMkDCXjjNb=s16000" style="margin-left: 0px; margin-top: 0px;" />
</div>
<div>
<h4>Using a logarithmic scale for the latencies</h4>
<p style="font-family: arial;">With a large range of values, it can be useful to use a logarithmic scale. While this can be more readable, it can be harder to appreciate how different the latencies are as many people are not used to reading logarithmic scale charts.</p>
<img src="https://lh6.googleusercontent.com/6spjngnanaiXVVQs0H5h-o99SJ9edRK3PpnyWeahydYNHHGQfItumQ0vbmaycLQWN1l4CvvMRZSd7Ss86Qkg5VV-PZ9LWBWhJ6720NSuUsS3DABeFRfQ6Bw8oA3bSNa97qIH_KPY=s16000" style="margin-left: 0px; margin-top: 0px;" />
</div>
<div>
<h3>How much higher are the latencies?</h3>
<p style="font-family: arial;">Another way to visualise just how much higher the latencies are for Kafka is to plot the ratio of latencies between Kafka and Chronicle. The chart below is a plot of the ratio of latencies between Kafka@100 kmsg/s which is one of the best results, and Chronicle Queue Enterprise@500kmsg/s ie at 5x the load. </p>
<p style="font-family: arial;">Kafka is consistently at least 680x slower for this benchmark, even for one-fifth of the throughput.</p>
<p style="font-family: arial;">For Kafka to achieve its lowest latencies with a 100 kmsg/s throughput, four partitions and eight microservices were used, however Chronicle Queue only needed one in all cases.</p>
<img src="https://lh4.googleusercontent.com/gqmBIr99Hxhm0VImsoceESjwIFtonrB_WkMKXHOqEf9lblanHH1yCm0cO1HpE1mKmD4WB4m9bxX7MBj3zfHGMaoGXSfoeoF1WqnzUs7OOCkUIdZBydPTOWvV_-S7PV6WZ1WFo1UL=s16000" style="margin-left: 0px; margin-top: 0px;" />
</div>
<div>
<h3>Chronicle Queue Heap Usage</h3>
<p style="font-family: arial;">The Chronicle Queue benchmark with 500 k/s messages for 5 minutes (300 million messages total), used a peak heap size of 40 MB with the G1 collector and default GC parameters. The benchmark runs with a 32 MB heap. No GCs occurred after warm-up.</p>
<p style="font-family: arial;">NOTE: Most of the garbage is from the Flight Recorder doing its job and Chronicle Queue doesn’t use the standard Java serialization features.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-LxISxCxTznE/YehERWTKIzI/AAAAAAAASqA/5psDScBwxGEb-LFZT1Hx0LnlU-uB13FzQCNcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"><img data-original-height="876" data-original-width="1637" src="https://lh3.googleusercontent.com/-LxISxCxTznE/YehERWTKIzI/AAAAAAAASqA/5psDScBwxGEb-LFZT1Hx0LnlU-uB13FzQCNcBGAsYHQ/s16000/image.png" /></a></div><br /><br /></div>
<div><h3>Kafka memory usage</h3>
<p style="font-family: arial;">The Kafka benchmark of 250 k/s messages for 10 minutes (300 million messages total), used a peak of 2.87 GB of the heap and triggered 2,410 young pause collections, and 182 concurrent cycle collections after warm-up.</p>
<p style="font-family: arial;">This can be run with a 128 MB heap size but results in over 139k GCs which is sub-optimal. In this recording, the heap size was set to 1 GiB.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-LOK70N426Kc/YehEq0sBgkI/AAAAAAAASqI/C5mIc9dgznY64B8eP9Iqqvml3u0UgnsUgCNcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"><img data-original-height="880" data-original-width="1637" src="https://lh3.googleusercontent.com/-LOK70N426Kc/YehEq0sBgkI/AAAAAAAASqI/C5mIc9dgznY64B8eP9Iqqvml3u0UgnsUgCNcBGAsYHQ/s16000/image.png" /></a></div><br /><br /></div>
<div>
<h2>Conclusion</h2>
<p style="font-family: arial;">While Kafka is a good choice for log aggregation, it might not be low latency enough for many use cases involving microservices due to its relatively high end-to-end latencies.</p>
<p style="font-family: arial;">Chronicle Queue open-source achieves consistent latencies below 100 microseconds more than 99.99% of the time while Kafka had outliers of 7 ms even at 1/5th of the throughput.</p>
<p style="font-family: arial;">Chronicle Queue Enterprise has additional features to keep latencies more consistent with latencies of below 10 microseconds more than 99.99% of the time.</p>
</div>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com4tag:blogger.com,1999:blog-1729822519392175009.post-44444583084914720122022-01-04T13:02:00.012+00:002022-01-12T20:22:33.949+00:00Distributed Unique Time Stamp Identifiers<p><span style="font-family: inherit;">Recently I published an article on using <a href="https://blog.vanillajava.blog/2021/12/system-wide-unique-nanosecond-timestamps.html" target="_blank">timestamps as unique identifiers</a>, generated in a fraction of a microsecond. This article covers an implementation that supports distributed identifier generation directly.</span></p><p><span style="font-family: inherit;">This specific implementation supports up to one billion new 64-bit identifiers every second only repeating after 520 years. They can also be printed as timestamps containing the wall clock to make it easier to read.</span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 16pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Concurrent identifier generation in a distributed system</span></h2><div style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: left;"><span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Each host has a predefined, unique host identifier, or </span><span style="background-color: transparent; color: black; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">hostId</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">.<br /></span></span><span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">This </span><span style="background-color: transparent; color: black; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><a href="https://github.com/OpenHFT/Chronicle-Core/blob/ea/src/main/java/net/openhft/chronicle/core/time/TimeProvider.java" target="_blank">TimeProvider</a></span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><a href="https://github.com/OpenHFT/Chronicle-Core/blob/ea/src/main/java/net/openhft/chronicle/core/time/TimeProvider.java" target="_blank"> </a>assumes up to 100 hosts to produce different identifiers concurrently. <br /></span></span><span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">JVMs using the same </span><span style="background-color: transparent; color: black; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">hostId </span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">must be on the same physical machine using the same memory-mapped file, <br /></span></span><span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">or you can give each JVM a different </span><span style="background-color: transparent; color: black; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">hostId</span></span></div><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 16pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">A nano-second timestamp with a host identifier</span></h2><div style="text-align: left;"><span style="background-color: transparent; font-family: inherit; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre;"><a href="https://github.com/OpenHFT/Chronicle-Bytes/blob/ea/src/main/java/net/openhft/chronicle/bytes/DistributedUniqueTimeProvider.java" target="_blank">DistributedUniqueTimeProvider </a>stores a host identifier in the lower two digits of the timestamp making it easier to read. </span></div><div style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: transparent; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre;">The previous implementation used bit shifting so the HostId could be obtained, </span><span style="background-color: transparent; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre;">but difficult for a human to read. <br /></span><span style="background-color: transparent; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre;">This allows you to produce guaranteed unique identifiers, encoded with up to 100 sources, </span><span style="background-color: transparent; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre;">across up to 100 machines, </span></span></div><div style="text-align: left;"><span style="font-family: inherit;"><span style="background-color: transparent; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre;">with multiple JVMs on the same machine sharing a hostId. The timestamp looks like this on a machine with a hostId of 28.</span></span></div><div><br /></div><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 14pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">2021-12-28T14:07:02.9541001</span><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 14pt; font-style: normal; font-variant: normal; font-weight: 700; text-decoration: none; vertical-align: baseline; white-space: pre;">28</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Where the date/time/microseconds are the time and the last two digits are the host identifier, </span><span style="font-family: inherit; white-space: pre;">making it easier to see the source in the time stamp. </span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: inherit; white-space: pre;">This gives a resolution of one-tenth of </span><span style="color: black; font-family: inherit; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre;">a microsecond (hundreds of nano-seconds) This is often the limit of the available wall clock </span><span style="font-family: inherit; white-space: pre;">in many systems anyway.</span></p><p><span style="font-family: inherit;"><span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">The </span><span style="font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">hostId</span><span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> can be set as a system property by default on the command line with </span><span style="font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">-DhostId=</span><span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">xx, or programmatically by calling the </span></span></p><p><span style="white-space: pre-wrap;"><span style="font-family: courier;">DistributedUniqueTimeProvider.INSTANCE.hostId(hostId)</span>;</span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 16pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Speeding up the assignment with a host identifier</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Having a preconfigured host identifier and keeping track of the most recent identifier in shared memory, </span><span style="font-family: inherit; white-space: pre;">allows fast concurrent generation of identifiers across machines. </span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: inherit; white-space: pre;">Up to the theoretical limit of </span><span style="font-family: inherit; white-space: pre;">one billion per second.</span></p><p><span style="font-family: inherit;"><span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">The happy path is simple. Take the current time, remove the lower two digits and add the </span><span style="font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">hostId</span><span style="font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">. As long as this is higher than the last identifier, it’s ok. Should the machine fail and the information as to the last identifier be lost, the assumption is that the time taken to restart the service is enough time to ensure there is no overlap. If the service fails, but not the machine, the information is retained.</span></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">NOTE: This used the MappedFile in shared memory supported by<a href="https://github.com/OpenHFT/Chronicle-Bytes" target="_blank"> Chronicle Bytes</a>, an open-source library.</span></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><br /></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><span style="border: none; display: inline-block; height: 213px; overflow: hidden; width: 643px;"><img height="213" src="https://lh6.googleusercontent.com/aiQI5xZAGTsQ4jzQ1SW-kQaJHrREd-PSt31hQXBmKySoagp7EpZ7cH3CasOTSwQiiR_VpKfh3aEULey0W-oxcIF22QWfKITeK-iC-Rk_GLd8v80K9AqE7lW25lXl2HI7y5ZGo5Tz" style="margin-left: 0px; margin-top: 0px;" width="643" /></span></span></p><p><span style="font-family: inherit; white-space: pre-wrap;">If the time hasn’t progressed, either due to high contention, or the wall clock going backwards e.g. due to a correction, a loop is called to find the next available identifier.</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><span style="border: none; display: inline-block; height: 224px; overflow: hidden; width: 643px;"><img height="224" src="https://lh6.googleusercontent.com/jRnCXagn8uHsgwEv33WVonpP9D9SuRoX6N-horC-B_bjtduSdqZRkWP-9ZrzDkxp-RLvlC7u17vmptpIJpIjNa5KtM-4c_55FU6j0QGrrtVrsrYwCRh4sg4grPSGdmebH-3vNB-M" style="margin-left: 0px; margin-top: 0px;" width="643" /></span></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: inherit;"><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">This loop looks for the next possible timestamp (with the </span><span style="background-color: transparent; color: black; font-style: italic; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">hostId</span><span style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">) and attempts to update it.</span></span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 16pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Using JMH to benchmark the timestamp provider</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">With JMH, benchmarking this utility in a single-threaded manner is pretty easy.</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><span style="border: none; display: inline-block; height: 495px; overflow: hidden; width: 643px;"><img height="495" src="https://lh6.googleusercontent.com/6_4fm6oiyF3UzRoTmFTM62ZMJ8o7yRnbR7Uu5t3ylBfePc1nmJqbY9PkKuQq7xmwKUVE7xciAujKOG-Mnvv-mSNFiwIaMFL8rgYTS-jH6nAMH8S3NyoDWUZ2LcKBiI2meYcC_qJU" style="margin-left: 0px; margin-top: 0px;" width="643" /></span></span></p><p><span style="font-family: inherit; white-space: pre-wrap;">After less than five minutes, we get the following result on my windows laptop. You can get better results on a high-end server or desktop. The average time is around 37.4 nanoseconds. While this is single-threaded, this is generally on the unhappy path, as timestamps need to be at least 100 ns apart or they temporarily run ahead of the wall clock.</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">UUID.randomUUID() is also very fast, only six times longer, however, if you need a timestamp </span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">and a source identifier for your event anyway, this is additional work/data.</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><br /></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">On an i9-10980HK</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 8pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Benchmark Mode Cnt Score Error Units</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 8pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">DistributedUniqueTimeProviderBenchmark.currentTimeNanos avgt 25 37.395 ± 0.391 ns/op</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 8pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">DistributedUniqueTimeProviderBenchmark.randomUUID avgt 25 207.709 ± 1.586 ns/op</span></p><p><span style="font-family: inherit; white-space: pre-wrap;">On a Ryzen 9 5950X</span><span style="font-family: Arial; font-size: 11pt; white-space: pre-wrap;">
</span><span style="font-family: "Courier New"; font-size: 8pt; white-space: pre-wrap;">Benchmark Mode Cnt Score Error Units
</span><span style="font-family: "Courier New"; font-size: 8pt; white-space: pre-wrap;">DistributedUniqueTimeProviderBenchmark.currentTimeNanos avgt 25 43.557 ± 0.801 ns/op
</span><span style="font-family: "Courier New"; font-size: 8pt; white-space: pre-wrap;">DistributedUniqueTimeProviderBenchmark.randomUUID avgt 25 265.285 ± 2.690 ns/op<br /></span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 16pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Downsides</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">There are some advantages to using UUIDs.</span></p><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">It’s built-in and the extra overhead might not be a concern</span></p></li><li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">No configuration is required</span></p></li><li aria-level="1" dir="ltr" style="background-color: transparent; color: black; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">They are not predictable, the timestamp-based ones are highly predictable</span></p></li></ul><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 16pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">Conclusion</span></h2><p style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: left;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">You can have an 8-byte lightweight identifier that is unique across many hosts if you can use </span></p><p style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: left;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">some predetermined partitioning by host identifier. The identifier is still easily readable as text in </span></p><p style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: left;"><span style="background-color: transparent; color: black; font-family: inherit; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">a slightly modified form of a timestamp.</span></p><p><br /></p>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com3tag:blogger.com,1999:blog-1729822519392175009.post-77171209398188733402021-12-21T12:06:00.006+00:002021-12-22T09:12:10.917+00:00System wide unique nanosecond timestamps<p>A <a href="https://en.wikipedia.org/wiki/Unique_identifier">Unique Identifier</a> can be very useful for tracing. Those ids are even more useful when they contain a high-resolution timestamp. </p><p>Not only do they record the time of an event, but if unique can help trace events as they pass through the system. Such unique timestamps however can be expensive depending on how they are implemented. </p><p>This post explores a lightweight means of producing a unique, monotonically increasing system-wide nano-second resolution timestamp available in our open-source library.</p><h1 style="text-align: left;">Uses for Unique Identifiers</h1><div>Unique identifiers can be useful to associate with a piece of information so that information can be referred to later unambiguously. This could be an event, a request, an order id, or a customer id.</div><div><br /></div><div>They can naturally be used as a primary key in a database or key/value store to retrieve that information later.</div><div><br /></div><div>One of the challenges of generating these identifiers is avoiding creating duplicates while not having an increasing cost. </div><div><br /></div><div>You could record every identifier created in a database, however, this uses O(n) storage as you add more identifiers. </div><div><br /></div><div>You could generate a random identifier such as a UUID which is unlikely to repeat, however, this creates large ids that otherwise don't hold any information. e.g. a UUID can look like <br /><span style="font-family: courier;"><b>d85686f5-7a53-4682-9177-0b64037af336</b></span></div><div><span style="font-family: inherit;">This UUID could be stored in 16 bytes however is often stored as an object taking 40 bytes of memory.</span></div><div><span style="font-family: inherit;">Using 256 bits reduces the risk of a repeated identifier, but doubles the memory used.</span></div><div><h1>Timestamps as Unique Identifiers</h1></div><div><span style="font-family: inherit;">Using a timestamp has two benefits. You don't need to store much information as the wall clock is the driver. You only need to check two threads that don't have the same time, but if this information is lost on a restart, for example, wall clock time should have progressed enough that you still won't get a duplicate. </span></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;">Such identifiers are also easier to read and give additional information which is useful for tracing. A timestamp-based unique identifier can look like <br /></span><span style="font-family: courier;"><b>2021-12-20T23:30:51.8453925</b></span></div><div><span style="font-family: inherit;">This timestamp could be stored in a LocalDateTime object however can be stored as just 8 bytes as a long, which is the way we typically use it.</span></div><h1 style="text-align: left;">MappedUniqueTimeProvider code</h1><div>This is the <b>abridged </b>version of the <a href="https://github.com/OpenHFT/Chronicle-Bytes/blob/ea/src/main/java/net/openhft/chronicle/bytes/MappedUniqueTimeProvider.java" target="_blank">MappedUniqueTimeProvider </a>available on GitHub</div><pre style="background-color: white; font-family: Verdana;"><span style="color: grey; font-style: italic;">/**<br /></span><span style="color: grey; font-style: italic;"> * Timestamps are unique across threads/processes on a single machine.<br /></span><span style="color: grey; font-style: italic;"> */<br /></span><span style="color: navy; font-weight: bold;">public enum </span>MappedUniqueTimeProvider <span style="color: navy; font-weight: bold;">implements </span>TimeProvider {<br /> <span style="color: #660e7a; font-style: italic; font-weight: bold;">INSTANCE</span>;<br /><br /> <span style="color: navy; font-weight: bold;">private final </span>Bytes <span style="color: #660e7a; font-weight: bold;">bytes</span>;<br /> <span style="color: navy; font-weight: bold;">private </span>TimeProvider <span style="color: #660e7a; font-weight: bold;">provider </span>= SystemTimeProvider.<span style="color: #660e7a; font-style: italic; font-weight: bold;">INSTANCE</span>;<br /><br /> MappedUniqueTimeProvider() {<br /> String user = System.<span style="font-style: italic;">getProperty</span>(<span style="color: green; font-weight: bold;">"user.name"</span>, <span style="color: green; font-weight: bold;">"unknown"</span>);<br /> MappedFile file = MappedFile.<span style="font-style: italic;">mappedFile</span>(OS.<span style="color: #660e7a; font-style: italic; font-weight: bold;">TMP </span>+ <span style="color: green; font-weight: bold;">"/.time-stamp." </span>+ user + <span style="color: green; font-weight: bold;">".dat"</span>, OS.<span style="font-style: italic;">pageSize</span>(), <span style="color: blue;">0</span>);<br /> <span style="color: #660e7a; font-weight: bold;">bytes </span>= file.acquireBytesForWrite(mumtp, <span style="color: blue;">0</span>);<br /> }<br /><br /> <span style="color: olive;">@Override<br /></span><span style="color: olive;"> </span><span style="color: navy; font-weight: bold;">public long </span>currentTimeNanos() <span style="color: navy; font-weight: bold;">throws </span>IllegalStateException {<br /> <span style="color: navy; font-weight: bold;">long </span>time = <span style="color: #660e7a; font-weight: bold;">provider</span>.currentTimeNanos(), time5 = time >>> <span style="color: blue;">5</span>;<br /> <span style="color: navy; font-weight: bold;">long </span>time0 = <span style="color: #660e7a; font-weight: bold;">bytes</span>.readVolatileLong(<span style="color: #660e7a; font-style: italic; font-weight: bold;">LAST_TIME</span>), timeNanos5 = time0 >>> <span style="color: blue;">5</span>;<br /><br /> <span style="color: navy; font-weight: bold;">if </span>(time5 > timeNanos5 && <span style="color: #660e7a; font-weight: bold;">bytes</span>.compareAndSwapLong(<span style="color: #660e7a; font-style: italic; font-weight: bold;">LAST_TIME</span>, time0, time))<br /> <span style="color: navy; font-weight: bold;">return </span>time;<br /><br /> <span style="color: navy; font-weight: bold;">while </span>(<span style="color: navy; font-weight: bold;">true</span>) {<br /> time0 = <span style="color: #660e7a; font-weight: bold;">bytes</span>.readVolatileLong(<span style="color: #660e7a; font-style: italic; font-weight: bold;">LAST_TIME</span>);<br /> <span style="color: navy; font-weight: bold;">long </span>next = (time0 + <span style="color: blue;">0x20</span>) & ~<span style="color: blue;">0x1f</span>;<br /> <span style="color: navy; font-weight: bold;">if </span>(<span style="color: #660e7a; font-weight: bold;">bytes</span>.compareAndSwapLong(<span style="color: #660e7a; font-style: italic; font-weight: bold;">LAST_TIME</span>, time0, next))<br /> <span style="color: navy; font-weight: bold;">return </span>next;<br /> Jvm.<span style="font-style: italic;">nanoPause</span>();<br /> }<br /> }<br />}</pre><h2 style="text-align: left;"><span id="docs-internal-guid-eab9ba71-7fff-a70d-b282-b16f66412e23" style="font-weight: normal;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">The following techniques have been used to ensure </span><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">time stamps’ </span><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">uniqueness and </span><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">efficiency</span><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span></span></h2><h2 style="text-align: left;">Shared memory</h2><div>This <a href="https://github.com/OpenHFT/Chronicle-Core/blob/ea/src/main/java/net/openhft/chronicle/core/time/TimeProvider.java" target="_blank">TimeProvider</a> uses shared memory to ensure a nanosecond resolution time is unique. A memory-mapped file is accessed in a thread-safe way to ensure the timestamps are monotonically increasing. <a href="https://github.com/OpenHFT/Chronicle-Bytes" target="_blank">Chronicle Bytes</a> has a library to support thread-safe access to a memory-mapped file. </div><div><br /></div><div>A long value in the memory-mapped file is read and attempted to be updated in a loop. The CAS or compare-and-swap operation is atomic and checks the previous value hasn't been changed by another thread. This will only succeed for one thread on the same machine.</div><h2 style="text-align: left;">Storing a nanosecond timestamp in a long</h2><div><span style="font-family: inherit;">We use a primitive long to store times stamps for efficiency, this can be harder to work with as a result, however, we have support for printing and parsing a long timestamp called the <span style="background-color: white;"><a href="https://github.com/OpenHFT/Chronicle-Wire/blob/ea/src/main/java/net/openhft/chronicle/wire/NanoTimestampLongConverter.java" target="_blank">NanoTimestampLongConverter</a> Our wire format also parses and renders these timestamps as text implicitly making it easier to print, debug and create units tests for.</span></span></div><div><br /></div><div><pre style="background-color: white;"><span style="font-family: verdana;"><span style="color: navy; font-weight: bold;">public class </span>Event <span style="color: navy; font-weight: bold;">extends </span>SelfDescribingMarshallable {<br /> <span style="color: olive;">@LongConversion</span>(NanoTimestampLongConverter.<span style="color: navy; font-weight: bold;">class</span>)<br /> <span style="color: navy; font-weight: bold;">long </span><span style="color: #660e7a; font-weight: bold;">time</span>;<br />}</span></pre><pre style="background-color: white;"><pre><span style="font-family: verdana;">Event e = <span style="color: navy; font-weight: bold;">new </span>Event();<br />e.<span style="color: #660e7a; font-weight: bold;">time </span>= <span style="color: #660e7a; font-style: italic;">CLOCK</span>.currentTimeNanos();<br />String str = e.toString();<br />Event e2 = Marshallable.<span style="font-style: italic;">fromString</span>(str);<br />System.<span style="color: #660e7a; font-style: italic; font-weight: bold;">out</span>.println(e2);</span></pre><pre><span style="font-family: inherit;">Prints</span></pre><pre><span style="font-family: verdana;">!net.openhft.chronicle.wire.Event {
<span style="color: navy; font-weight: bold;">time:</span> 2021-12-20T23:30:51.8453925
}</span></pre></pre></div><div><span style="font-family: inherit;"><span style="background-color: white;"><br /></span></span></div><div><span style="font-family: inherit;"><span style="background-color: white;">As nano-second timestamps are a high-resolution format, it will only last until the year 2262 as a signed long or 2554 if you assume it's an unsigned long, before the values overflow.</span></span></div><div><span style="font-family: inherit;"><span style="background-color: white;"><br /></span></span></div><div><span style="background-color: white;">We have used for using extra bits in the timestamp for other purposes, such as storing the host identifier or a source id. For this reason, we also ensure the timestamp is unique to a multiple of 32 ns, allowing us to use the lower 5 bits for other purposes if we wish. If you were implementing this yourself you could drop this requirement.</span></div><h2 style="text-align: left;">Performance</h2><div>Under normal operation, obtaining the unique nanosecond timestamp takes well under 50 ns on modern machines. Under heavy multi-threaded load in benchmarks, it can take a few hundred nanoseconds. However, this assumes the timestamps are discarded, so I consider such a benchmark an unrealistic use case.</div><div><br /></div><div>The MappedUniqueTimeProvider application can sustain the generation of over 30 million/second and not run ahead of the wall clock due to the mentioned techniques</div><h2 style="text-align: left;">Restartability</h2><div>As long as time doesn't go backward, this strategy can lose all states and still ensure uniqueness from the wall clock alone. If wall clock time does go backward by say an hour, the state will ensure there are no duplicates, however, the timestamps won't match the wall clock until the wall clock catches up.</div><h2 style="text-align: left;">Conclusion</h2><div>It is possible to have a lightweight, unique identifier generator that holds nanosecond timestamps.</div><h2 style="text-align: left;">Links</h2><div>Chronicle Bytes <a href="https://github.com/OpenHFT/Chronicle-Bytes">https://github.com/OpenHFT/Chronicle-Bytes</a></div><div>Chronicle Performance Engineers <a href="https://www.linkedin.com/groups/12138236/">https://www.linkedin.com/groups/12138236/</a></div><div>Chronicle Software <a href="https://chronicle.software/">https://chronicle.software/</a></div><h2 style="text-align: left;">Authors</h2><div>Peter Lawrey <a href="https://www.linkedin.com/in/peterlawrey/">https://www.linkedin.com/in/peterlawrey/</a></div><div>Reviewed by Forough Goudarzi <a href="https://www.linkedin.com/in/forough-goudarzi-29946280/">https://www.linkedin.com/in/forough-goudarzi-29946280/</a></div><div><br /></div>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com1tag:blogger.com,1999:blog-1729822519392175009.post-13423386936547067132021-12-20T11:25:00.004+00:002021-12-20T11:29:02.220+00:00Unusual Java: StackTrace Extends Throwable<p><span style="font-family: Arial; font-size: 11pt; white-space: pre-wrap;">There are things you can do in Java you rarely see, generally because there is no use for it. However, there are some unusual things in Java that could be surprisingly useful.</span></p><span id="docs-internal-guid-b0b4f144-7fff-b4a4-c66f-992dac0a9d91"><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Chronicle Software uses a number of different usual patterns in it’s low-level libraries most developers wouldn’t generally come across.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">One of them is a class that extends Throwable but isn’t an Error or an Exception.</span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="font-family: Arial; font-size: 16pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">StackTrace Extends Throwable</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">package </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">net.openhft.chronicle.core;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: grey; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">/**</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: grey; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">* Throwable created purely for the purposes of reporting a stack trace.</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: grey; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">* This is not an Error or an Exception and is not expected to be thrown or caught.</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: grey; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">*/</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public class </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">extends </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Throwable {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace() { </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">this</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">"stack trace"</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">); }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace(String message) { </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">this</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(message, </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">null</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">); }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace(String message, Throwable cause) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">super</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(message + </span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">" on " </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">+ Thread.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">currentThread</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">().getName(), cause);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: olive; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public static </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace forThread(Thread t) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">if </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(t == </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">null</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">) </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">return null</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> StackTrace st = </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace(t.toString());</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> StackTraceElement[] stackTrace = t.getStackTrace();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">int </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">start = </span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">if </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(stackTrace.</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">length </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">> </span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">2</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">if </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(stackTrace[</span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">].isNativeMethod()) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> start++;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;"> if </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(start > </span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> StackTraceElement[] ste2 = </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTraceElement[stackTrace.</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">length </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">- start];</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> System.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">arraycopy</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(stackTrace, start, ste2, </span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">, ste2.</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">length</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> stackTrace = ste2;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> st.setStackTrace(stackTrace);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">return </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">st;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Some important side notes to get out of the way first</span></p><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="1" dir="ltr" style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; list-style-type: disc; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Yes, I really do use a proportional font in my IDE. I use Verdana on Windows, which I got used to very easily and haven’t wanted to go back.</span></p></li><li aria-level="1" dir="ltr" style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; list-style-type: disc; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">This isn’t a class that I expect to ever get thrown. Classes directly extending Throwable are checked, as Exception is, so the compiler will help you enforce this.</span></p></li><li aria-level="1" dir="ltr" style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; list-style-type: disc; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">The stack trace of a Throwable is determined when the Throwable is created, not where it is thrown. Usually, this is the same line, but it doesn’t have to be. A Throwable doesn’t have to be thrown to have a stack trace.</span></p></li><li aria-level="1" dir="ltr" style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; list-style-type: disc; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">The stack trace element objects aren’t created until they are needed. Instead, metadata is added to the object itself to reduce overhead and the array of StackTraceElements is populated on first use.</span></p></li></ul><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">However, let’s look at the class in more detail. The class will record both the stack trace of where it was created and the thread which created it. You should see how this is useful later.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">It can also be used to hold a stack trace of another running thread. A stack trace of another thread is only taken when the thread reaches a safe point, which can be some time after you attempt to get it. This is due to the JVM stopping the thread, and typically JVMs wait to stop every thread, so it can inspect the stack of the thread you are attempting to capture.</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">i.e. It has a high overhead but can be very useful.</span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="font-family: Arial; font-size: 16pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">StackTrace as a deferred Exception</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">We don’t expect this Throwable to be thrown but it can record the cause of an Exception that may be thrown later.</span></p><h3 dir="ltr" style="line-height: 1.38; margin-bottom: 4pt; margin-top: 16pt;"><span style="color: #434343; font-family: Arial; font-size: 14pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">Why was a resource closed</span></h3><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public class </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">EgMain {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">static class </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">MyCloseable </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">implements </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Closeable {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">protected transient volatile </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">closedHere</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: olive; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">@Override</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: olive; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">close() {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">closedHere </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">= </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace(</span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">"Closed here"</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">); </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// line 13</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">useThis() {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">if </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">closedHere </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">!= </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">null</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">)</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">throw new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">IllegalStateException(</span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">"Closed"</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">, </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">closedHere</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public static void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">main(String[] args) </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">throws </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">InterruptedException {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> MyCloseable mc = </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">MyCloseable(); </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// line 27</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> Thread t = </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Thread(mc::close, </span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">"closer"</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> t.start();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> t.join();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> mc.useThis();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Produces the following Exception when run</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: "Courier New"; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="border: none; display: inline-block; height: 104px; overflow: hidden; width: 643px;"><img height="104" src="https://lh3.googleusercontent.com/1TIREDyW-TLfOURKNHTkSee3ihKa0utxcyGXTWNGmQDb5e9LZR0UvohmjeFlf6p_PBHyuRc_FiS3kghQtWgFWK3-Iv4X4_enzPu-5zWGRKj2S-p-7BdlL_ZLtGeL4aQa2UbQwkKA" style="margin-left: 0px; margin-top: 0px;" width="643" /></span></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Normally you would see the IllegalStateException and where your code tried to use the closed resource, but this doesn’t tell you why it was closed without additional information.</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">As StackTrace is a Throwable, you can make it the cause of a subsequent Exception or Error. </span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">You can see the thread which closed the resource, so you know it occurred in another thread and you can see the stack trace of why it was closed. This can help diagnose hard-to-find issues for premature closing of resources very quickly.</span></p><h3 dir="ltr" style="line-height: 1.38; margin-bottom: 4pt; margin-top: 16pt;"><span style="color: #434343; font-family: Arial; font-size: 14pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">Which Resource Was Discarded?</span></h3><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Long-lived Closeable objects can have a complex life cycle and ensuring they are close when they need to be can be hard to trace, and can lead to resource leaks. Some resources are not cleaned up when the GC frees the object e.g. a RandomAccessFile object is cleaned up on a GC by the file it represents isn’t closed unless you close it, leading to a potential resource leak of file handles.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public class </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">CreatedMain {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">static class </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">MyResource </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">implements </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Closeable {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">private final transient </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">createdHere </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">= </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace(</span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">"Created here"</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">volatile transient boolean </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">closed</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: olive; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">@Override</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: olive; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">close() </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">throws </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">IOException {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">closed </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">= </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">true</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: olive; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">@Override</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: olive; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">protected void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">finalize() </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">throws </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Throwable {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">super</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">.finalize();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">if </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(!</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">closed</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">)</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> Logger.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">getAnonymousLogger</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">().log(Level.</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">WARNING</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">, </span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">"Resource discarded but not closed"</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">, </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">createdHere</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public static void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">main(String[] args) </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">throws </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">InterruptedException {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">MyResource(); </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// line 27</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> System.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">gc</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> Thread.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">sleep</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">1000</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Prints the following</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="border: none; display: inline-block; height: 148px; overflow: hidden; width: 643px;"><img height="148" src="https://lh3.googleusercontent.com/5ydM4MI-hByA-zYxklwrBarVTXTkid8YdEr3C2Zb4fMDkZ6g46ZalksmP08Tl-VS05GineuarUFuvyOv_Mx-eQQvznnTkBPl_fEj04ORU-_zmM0OjILb-P2D4jYRV6_zE7CyX-Mc" style="margin-left: 0px; margin-top: 0px;" width="643" /></span></span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">This allows you to not just see where a resource was created so you can try to determine why it wasn’t closed, but it’s trivial to log in a manner your IDE understands, as your logger will already have support for printing out the stack trace. e.g. you can click on the line numbers to look through the code which created it.</span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="font-family: Arial; font-size: 16pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">Performance Monitoring a Critical Thread in Production</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">In some environments, you want a low overhead way of monitoring the jitter of a critical event in production, without running a profiler. This can be achieved by adding your own monitoring to only sample a stack trace when it exceeds some threshold. This can find problems you can’t reproduce in a test or development environment, so it can be invaluable.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">When we have added this to our infrastructure, the number of mysterious delays reported to us by our clients dropped dramatically as clients could diagnose for themselves what the issue was from the stack trace.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public class </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">JitteryMain </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">implements </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Runnable {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">volatile long </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">loopStartMS </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">= Long.</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">MIN_VALUE</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">volatile boolean </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">running </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">= </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">true</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: olive; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">@Override</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: olive; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">run() {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">while </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">running</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">loopStartMS </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">= System.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">currentTimeMillis</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> doWork();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">loopStartMS </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">= Long.</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">MIN_VALUE</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">private void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">doWork() {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">int </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">loops = </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Random().nextInt(</span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">100</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">for </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">int </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">i = </span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">0</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">; i < loops; i++)</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">pause</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">1</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">); </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// line 24</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">static void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">pause(</span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">int </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">ms) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">try </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">{</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> Thread.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">sleep</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(ms); </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// line 29</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> } </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">catch </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(InterruptedException e) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">throw new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">AssertionError(e); </span><span style="background-color: white; color: grey; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// shouldn't happen</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: grey; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public static void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">main(String[] args) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">final </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">JitteryMain jittery = </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">JitteryMain();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> Thread thread = </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Thread(jittery, </span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">"jitter"</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> thread.setDaemon(</span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">true</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> thread.start();</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: grey; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// monitor loop</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: grey; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">long </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">endMS = System.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">currentTimeMillis</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">() + </span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">1_000</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">while </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(endMS > System.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">currentTimeMillis</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">()) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">long </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">busyMS = System.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">currentTimeMillis</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">() - jittery.</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">loopStartMS</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">if </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(busyMS > </span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">100</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> Logger.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">getAnonymousLogger</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">()</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> .log(Level.</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">INFO</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">, </span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">"Thread spent longer than expected here, was " </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">+ busyMS + </span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">" ms."</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">,</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> StackTrace.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">forThread</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(thread));</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">pause</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="background-color: white; color: blue; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">50</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> jittery.</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">running </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">= </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">false</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Prints the following, which again you can see is easy to navigate the stack in your IDE.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="border: none; display: inline-block; height: 120px; overflow: hidden; width: 643px;"><img height="120" src="https://lh4.googleusercontent.com/Ogwp_w79uIRIIYXIUnCIAQ037ucDZoBx3gQskqqMlbi2PZGvkStnPtd6rn9ydpCeUP0m6BDm5X0t_bvz4ie_L4GUKyAFopZQ2axXFNey8v4Z0Jlr3Wfc20MmG5evva02LxLNx9O0" style="margin-left: 0px; margin-top: 0px;" width="643" /></span></span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">You might be wondering why this happens in this case. The most likely cause is that </span><span style="font-family: Arial; font-size: 11pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Thread.sleep(time)</span><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> sleeps for a minimum amount of time, not a maximum and on Windows sleep 1 ms actually takes about 1.9 ms fairly consistently.</span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="font-family: Arial; font-size: 16pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">Detecting When a Single-Threaded Resource is Accessed Concurrently Between Threads</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">package </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">net.openhft.chronicle.core;</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public class </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">ConcurrentUsageMain {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">static class </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">SingleThreadedResource {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">private </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">usedHere</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">private </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Thread </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">usedByThread</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">use() {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> checkMultithreadedAccess();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: grey; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// BLAH</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: grey; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">private void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">checkMultithreadedAccess() {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">if </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(</span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">usedHere </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">== </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">null </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">|| </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">usedByThread </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">== </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">null</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">usedHere </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">= </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace(</span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">"First used here"</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">usedByThread </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">= Thread.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">currentThread</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> } </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">else if </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">(Thread.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">currentThread</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">() != </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">usedByThread</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">) {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">throw new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">IllegalStateException(</span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">"Used two threads " </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">+ Thread.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">currentThread</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">() + </span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">" and " </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">+ </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">usedByThread</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">, </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">usedHere</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">);</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">public static void </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">main(String[] args) </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">throws </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">InterruptedException {</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> SingleThreadedResource str = </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">SingleThreadedResource();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">final </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Thread thread = </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Thread(() -> </span><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">str</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">.use(), </span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">"Resource user"</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">); </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// line 25</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> thread.start();</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> thread.join();</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> str.use(); </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">// line 29</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> }</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">}</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Prints the following</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="border: none; display: inline-block; height: 107px; overflow: hidden; width: 716px;"><img height="107" src="https://lh6.googleusercontent.com/O56IBnq5KdcEPDnDHwOJXWc45nyc5fOQ2qcmpIDYZNiBzebXch77VildGzNnq1sVyucMW-49DNXZMgtAX-vaW8YuneZwL9rlaKRx_RW339xQWxSOOYiceYSud58_gRwxH9I-t044" style="margin-left: 0px; margin-top: 0px;" width="716" /></span></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">You can see the resource was used by two threads with their names, however, you can also see where in the stack they were used to determine the possible cause.</span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="font-family: Arial; font-size: 16pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">Turning Off This Tracing</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Creating a StackTrace has a significant impact on the thread and possibly the JVM. However, it is easily turned off using a control flag such as a system property and replaced with a </span><span style="font-family: Arial; font-size: 11pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">null </span><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">value.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; color: #660e7a; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">createdHere </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">= Jvm.</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">isResourceTracing</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">() </span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> ? </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">new </span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">StackTrace(getClass().getName() + </span><span style="background-color: white; color: green; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">" created here"</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">)</span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> : </span><span style="background-color: white; color: navy; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 700; vertical-align: baseline; white-space: pre-wrap;">null</span><span style="background-color: white; font-family: Verdana; font-size: 10pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">;</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">This use of a </span><span style="font-family: Arial; font-size: 11pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">null </span><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">doesn’t require much special handling as loggers will ignore a Throwable which is </span><span style="font-family: Arial; font-size: 11pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">null</span><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">, and you can give a </span><span style="font-family: Arial; font-size: 11pt; font-style: italic; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">null </span><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">cause to an Exception and it’s the same as not providing one.</span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="font-family: Arial; font-size: 16pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">Conclusion</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">While having a class that directly extends Throwable is surprising, it is allowed and is also surprisingly useful for providing additional information about the life cycle of a resource, or adding simple monitoring you can run in production.</span></p><h2 dir="ltr" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;"><span style="font-family: Arial; font-size: 16pt; font-variant-east-asian: normal; font-variant-numeric: normal; font-weight: 400; vertical-align: baseline; white-space: pre-wrap;">Links</span></h2><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">OpenHFT Chronicle Core </span><a href="https://github.com/OpenHFT/Chronicle-Core" style="text-decoration-line: none;"><span style="color: #1155cc; font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space: pre-wrap;">https://github.com/OpenHFT/Chronicle-Core</span></a><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Chronicle Performance Engineers </span><a href="https://www.linkedin.com/groups/12138236/" style="text-decoration-line: none;"><span style="color: #1155cc; font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space: pre-wrap;">https://www.linkedin.com/groups/12138236/</span></a><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">Chronicle Software </span><a href="https://chronicle.software/" style="text-decoration-line: none;"><span style="color: #1155cc; font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space: pre-wrap;">https://chronicle.software/</span></a><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"> </span></p><div><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></div></span>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-35755101699621343942021-12-18T15:55:00.006+00:002021-12-23T11:32:05.743+00:00Low Latency Microservices, A Retrospective<p> <span face="Poppins, sans-serif" style="background-color: white; color: #181f4c; font-size: 16px;">I wrote an article on </span><a href="https://vanilla-java.github.io/2016/03/22/Micro-services-for-performance.html" rel="noopener noreferrer" style="box-sizing: border-box; color: #3155a5; font-family: Poppins, sans-serif; font-size: 16px; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;" target="_blank">low latency microservices</a><span face="Poppins, sans-serif" style="background-color: white; color: #181f4c; font-size: 16px;"> </span><span face="Poppins, sans-serif" style="background-color: white; color: #181f4c; font-size: 16px;">almost five years ago now. Chronicle Software has worked with a number of tier-one investment banks to implement and support those systems. What has changed in that time and what lessons have we learnt?</span></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Read this article and learn what we learned after five years of developing and supporting low latency microservices.</p><h3 id="testability" style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px;">Separation of Concerns Give Better Testability</h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Microservices repeatedly demonstrated that testing and debugging business components were much easier with simple, stand-alone components with clear contracts between microservices.</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Unit tests were still used to start with. However, in 2017 we moved almost entirely to behavior-driven development of microservices. Unit tests are still used for lower-level libraries and utilities. As our microservices are all based on <a href="https://milinda.pathirage.org/kappa-architecture.com/" rel="noopener noreferrer" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;" target="_blank">Kappa Architecture</a>, all our behaviour driven tests are modeled as a series of events in and out of the service.</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">An input test might look like this</p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><pre style="background-color: white; color: black; font-family: Verdana; font-size: 9.8pt;">---<br /><span style="color: navy; font-weight: bold;">oms</span>: OMS1 <span style="color: grey; font-style: italic;"># the service to receive this message<br /></span><span style="color: navy; font-weight: bold;">newOrder</span>: {<br /> <span style="color: navy; font-weight: bold;">eventId</span>: orderevent1,<br /> <span style="color: navy; font-weight: bold;">eventTime</span>: 2017-04-27T07:26:40.9836487,<br /> <span style="color: navy; font-weight: bold;">triggerTime</span>: 2017-05-05T12:56:40.7534873,<br /> <span style="color: navy; font-weight: bold;">instrument</span>: USDCHF,<br /> <span style="color: navy; font-weight: bold;">settlementTime</span>: 2017-04-26T09:46:40,<br /> <span style="color: navy; font-weight: bold;">market</span>: FXALL_MID,<br /> <span style="color: navy; font-weight: bold;">orderId</span>: orderid1,<br /> <span style="color: navy; font-weight: bold;">hedgerName</span>: Hedger1,<br /> <span style="color: navy; font-weight: bold;">user</span>: MidHedger,<br /> <span style="color: navy; font-weight: bold;">orderType</span>: MARKET,<br /> <span style="color: navy; font-weight: bold;">side</span>: SELL,<br /> <span style="color: navy; font-weight: bold;">quantity</span>: 500E3,<br /> <span style="color: navy; font-weight: bold;">maxShowQuantity</span>: 500E3,<br /> <span style="color: navy; font-weight: bold;">timeInForceType</span>: GTC,<br /> <span style="color: navy; font-weight: bold;">timeInForceExpireTime</span>: 2018-01-01T01:00:00<br />}<br />---<br /><span style="color: grey; font-style: italic;"># more messages</span></pre></pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">The output looks very similar as this is an Order Management Service. The job of OMS and it’s job is to normalise, filter and track orders.</p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><pre style="background-color: white; color: black; font-family: Verdana; font-size: 9.8pt;">---<br /><span style="color: navy; font-weight: bold;">newOrder</span>: {<br /> <span style="color: navy; font-weight: bold;">eventId</span>: orderevent1,<br /> <span style="color: navy; font-weight: bold;">eventTime</span>: 2017-04-27T07:26:40.9836487,<br /> <span style="color: navy; font-weight: bold;">triggerTime</span>: 2017-05-05T12:56:40.7534873,<br /> <span style="color: navy; font-weight: bold;">instrument</span>: USDCHF,<br /> <span style="color: navy; font-weight: bold;">settlementTime</span>: 2017-04-26T09:46:40,<br /> <span style="color: navy; font-weight: bold;">market</span>: FXALL_MID,<br /> <span style="color: navy; font-weight: bold;">orderId</span>: orderid1,<br /> <span style="color: navy; font-weight: bold;">hedgerName</span>: Hedger1,<br /> <span style="color: navy; font-weight: bold;">orderType</span>: MARKET,<br /> <span style="color: navy; font-weight: bold;">quantity</span>: 500E3,<br /> <span style="color: navy; font-weight: bold;">user</span>: MidHedger,<br /> <span style="color: navy; font-weight: bold;">side</span>: SELL,<br /> <span style="color: navy; font-weight: bold;">maxShowQuantity</span>: 500E3,<br /> <span style="color: navy; font-weight: bold;">timeInForceType</span>: GTC,<br /> <span style="color: navy; font-weight: bold;">timeInForceExpireTime</span>: 2018-01-01T01:00:00<br />}<br />---<br /><span style="color: grey; font-style: italic;"># more results</span></pre></pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Building variations on tests to explore all the things which could go wrong and check how they are handled is easy.</p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px;">What we needed to add</h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Beyond implementing what we envisioned five years ago, there were some features we discovered we needed to add.</p><h4 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 18px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 10px;">A deterministic clock</h4><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">To ensure our services produced the same results every time, whether in tests or between production and any redundant system, we made the time an input. This appeared in our test like this</p><pre style="background-color: whitesmoke; border-radius: 4px; border: 1px solid rgb(204, 204, 204); box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; line-height: 1.42857; margin-bottom: 10px; margin-top: 0px; overflow-wrap: break-word; overflow: auto; padding: 9.5px; word-break: break-all;"><pre style="background-color: white; color: black; font-family: Verdana; font-size: 9.8pt;"><span style="color: navy; font-weight: bold;">periodicUpdate</span>: 2017-04-27T07:26:51<br />---<br /></pre></pre><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">This ensured that all time-outs or events triggered by the clock could be tested, but also ensure each redundant system did the same things at the same point and produced the same output.</p><h4 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 18px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 10px;">Nanosecond timestamps</h4><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">We started with millisecond timestamps but quickly found we needed greater resolution switching to microseconds timestamps, and now use nanosecond resolution timestamps.</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Nanosecond timestamps were more useful if we could also ensure some level of uniqueness. Nanosecond timestamps can be made unique on a single host in a low latency way. This takes well under 100 nanoseconds. That way a timestamp can be used as a unique id for tracing events through a system (adding a pre-set host id if needed).</p><p style="background-color: white; box-sizing: border-box; margin: 0px 0px 10px;"><span style="color: #181f4c; font-family: Poppins, sans-serif;"><a href="https://blog.vanillajava.blog/2021/12/system-wide-unique-nanosecond-timestamps.html|">https://blog.vanillajava.blog/2021/12/system-wide-unique-nanosecond-timestamps.html|</a></span></p><h4 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 18px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 10px;">Ability to store complex data as primitives</h4><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">For testing purposes, all messages appear as text, however for performance reasons all data is written/read in a binary form. The typical latency of a persisted message between microservices is less than a microsecond so how the objects are stored can make a big difference.</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">The use of String and LocalDateTime was very expensive for our use case. To reduce the impact of storing this information, we developed a number of strategies for:</p><ul style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin-bottom: 10px; margin-top: 0px;"><li style="box-sizing: border-box;">encoding Strings and dates in <code style="background-color: #f9f2f4; border-radius: 4px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 14.4px; padding: 2px 4px;">long</code> fields.</li><li style="box-sizing: border-box;">object pooling Strings</li><li style="box-sizing: border-box;">storing text in a mutable/reusable field</li></ul><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Ultimately, this lead to the support of <a href="https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable" rel="noopener noreferrer" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;" target="_blank">Trivially Copyable</a> objects, a concept adopted from C++, where the majority (or entire) Java object could be copied as a memory copy without any serialization logic. This allowed us to support passing complex market data with around 50 fields between microservices in different processes at well under a microsecond most of the time.</p><h4 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 18px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 10px;">Ability to run microservices as a single process or a single thread</h4><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">We have solved the problem of how to test and debug many microservices but allow them to run in a single JVM or a single thread. This gave our customers the flexibility of running parts of the system as a compound microservice in the test environment while they could still deploy individual microservices independently in production.</p><h4 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 18px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 10px;">Simplifying restarts with idempotency</h4><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Idempotency allows an operation to be harmlessly attempted multiple times. Restarts are simplified by replaying any messages you are not sure if they were processed fully.</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">In low latency systems, transactionality needs to be as simple as possible. This suits most needs, however when you get a complex transaction, idempotency can significantly reduce the complexity of recovery.</p><h4 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 18px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 10px;">Multiple replay strategies</h4><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Having a complete deterministic persisted record of every message made restarts and failover simpler, however, we found that different use cases needed different strategies as to how that is done. We have learnt a lot about real replayability/restartability requirements from customers’ real use cases and the trade-offs they make for service start time vs accuracy etc.</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">One key feature is ensuring upstream messages are replicated before downstream messages to simplify rebuilding the current state.</p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px;">What became less important</h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Some of the features we thought would be vital five years ago, turned out to be not always required as clients used our technology in broader contexts.</p><h4 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 18px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 10px;">Ultra-low garbage collection</h4><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Five years ago, we were entirely focused on no minor collections over a day of processing. However, many clients wanted the productivity gains we offered but didn’t have stringent performance requirements and occasional garbage collections were not a concern. Creating microservices naturally supports having latency-critical services as well as less latency-critical services in the same system.</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">This required a shift in some of our thinking which assumed GCs never occurred normally. We significantly reduced our use of WeakReferences for example.</p><h4 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 18px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 10px;">Low throughput data processing</h4><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">The lowest latencies tend to be at around 1% of the peak capacity. At lower throughputs, you tend to get either your hardware trying to power save, increasing latency when an event does occur, and at higher throughputs, you increase the chance of a message coming in while you are still processing previous ones, adding to latency.</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Again, we saw a broadening of use cases to very low message rates which showed up behaviour that is only seen when the machine is spending most of it’s time waiting. We added <a href="https://github.com/OpenHFT/Chronicle-Core/tree/ea/src/main/java/net/openhft/chronicle/core/cooler" rel="noopener noreferrer" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;" target="_blank">performance test tools to see how our code behaves when the CPU is running cold</a>.</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">We also saw the need to support higher throughputs of messages for hours at a time (rather than seconds or minutes). For example, if we had a microservice that could process a million messages per second, we would test the latency at 1% of this as this was considered the normal volume. It also wasn’t possible to get high-performance, high-volume drives that could sustain this rate for hours without filling up. Today, we are testing the latency of systems sustaining long bursts of one million messages per second for many hours at a time.</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">If you are looking for such a drive you can test on a desktop, I suggest looking at the <a href="https://www.corsair.com/uk/en/Categories/Products/Storage/M-2-SSDs/MP600-PRO-XT/p/CSSD-F4000GBMP600PXT" rel="noopener noreferrer" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;" target="_blank">Corsair MP600 Pro series</a></p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px;">Make your infrastructure as fast as your application needs.</h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Over the last five years, the requirements for core systems have been more stringent, however, as we need to integrate with the existing system we have seen the need to easily support systems that don’t have the same requirements (and would rather it be easy and natural to work with)</p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">For the more stringent systems, the latencies clients care about</p><ul style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin-bottom: 10px; margin-top: 0px;"><li style="box-sizing: border-box;">have moved from the 99%ile (worst 1 in 100) to the 99.9%ile or 99.99%ile</li><li style="box-sizing: border-box;">The latencies they are looking to achieve, wire to wire (as measured on the network), is more around a 99.9%ile at 100 microseconds (less strict) or the 99.99%ile at 20 microseconds (more strict).</li><li style="box-sizing: border-box;">have a clearer idea as the worst-case latencies they need to see. Many are looking for low milliseconds end to end worst case</li></ul><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">At the same time, our clients need to integrate with existing systems where all they need is for that to be as easy as possible.</p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px;">Make the message format a configuration consideration</h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Five years ago I imagined we would need to support all sorts of formats however a relatively small number turned out to be really useful.</p><ul style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin-bottom: 10px; margin-top: 0px;"><li style="box-sizing: border-box;">An existing format. Make using a corporate standard format easy, no need to use ours</li><li style="box-sizing: border-box;">Text format, YAML seems the best one, esp for readability and typed data</li><li style="box-sizing: border-box;">Binary form of YAML. Good trade-off between ease of use and performance</li><li style="box-sizing: border-box;">Typed JSON for use over websockets to Javascript based UIs</li><li style="box-sizing: border-box;">Marshalling of fields as binary</li><li style="box-sizing: border-box;">Direct memory copy objects e.g. Trivially Copyable, to maximise speed</li><li style="box-sizing: border-box;">FIX protocol</li></ul><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">We regularly use a single DTO in multiple formats depending on what is most appropriate without the need to copy data between DTO specialised for a given format.</p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px;">Conclusion</h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">For the use case of our clients, I believe most of the concerns around replacing microservices with a monolith have been solved. However, having the option to run multiple microservices as if it was a monolith handles those cases where it is easier to work with e.g. testing and debugging multiple services.</p><h3 style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.2; margin-bottom: 10px; margin-top: 20px;">Links</h3><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-size: 16px; margin: 0px 0px 10px;"><a href="https://github.com/OpenHFT" rel="noopener noreferrer" style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-family: Poppins, sans-serif; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;" target="_blank">OpenHFT open-source libraries</a><br style="box-sizing: border-box;" /></p><div style="text-align: left;"><span style="background-color: transparent; box-sizing: border-box; color: #3155a5; font-family: inherit; font-weight: 700; text-decoration-line: none; transition: all 0.15s ease 0s;"><a href="https://github.com/OpenHFT">https://github.com/OpenHFT</a></span></div><p></p><p style="background-color: white; box-sizing: border-box; color: #181f4c; font-family: Poppins, sans-serif; font-size: 16px; margin: 0px 0px 10px;">Chronicle Software Microservices Framework<br /><a href="https://chronicle.software/solutions/microservices-framework/">https://chronicle.software/solutions/microservices-framework/</a></p>Peter Lawreyhttp://www.blogger.com/profile/17982030676088168612noreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-51484912196921267942017-03-10T08:48:00.004+00:002021-12-18T15:47:01.237+00:00Reviewing Exception Handling<h1 class="post-title" itemprop="name headline" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 2.5em; letter-spacing: -1px; line-height: 1; margin: 1em 0px 0.5em; padding: 0px 0px 15px; text-indent: -2px; text-rendering: optimizeLegibility; word-wrap: break-word;">
Reviewing Exception Handling</h1>
<div>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; margin: 0px; padding: 0px;">
<div style="box-sizing: border-box; direction: ltr; line-height: 1.6; margin-bottom: 1.25em; padding: 0px;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">When developing an application it can be hard enough to get the happy path working, let alone worry about what might happen when something goes wrong.</span></div>
</div>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; margin: 0px; padding: 0px;">
<div style="box-sizing: border-box; direction: ltr; line-height: 1.6; margin-bottom: 1.25em; padding: 0px;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">I have asked a number of developers recently what they do when they get an exception and usually they log it or pass it back to the user.</span></div>
</div>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; margin: 0px; padding: 0px;">
<div style="box-sizing: border-box; direction: ltr; line-height: 1.6; margin-bottom: 1.25em; padding: 0px;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">What are some alternatives? If you have to pass on the exception how might you do that?</span></div>
</div>
</div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<a href="https://vanilla-java.github.io/2016/06/21/Reviewing-Exception-Handling.html"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Read more by following this link to the new blog!</span></a>Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-1729822519392175009.post-74485736761720318272017-03-10T08:47:00.004+00:002018-01-19T11:13:09.094+00:00<h1 class="post-title" itemprop="name headline" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 2.5em; letter-spacing: -1px; line-height: 1; margin: 1em 0px 0.5em; padding: 0px 0px 15px; text-indent: -2px; text-rendering: optimizeLegibility; word-wrap: break-word;">
Distributing Common Java APIs</h1>
<div>
<h3 id="_distributing_data_stores_vs_private_data_stores_in_microservices" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 1.5em; line-height: 1.4; margin: 1em 0px 0.5em; padding: 0px; text-rendering: optimizeLegibility; word-wrap: break-word;">
Distributing data stores vs Private data stores in Microservices</h3>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-size: 16px; margin: 0px; padding: 0px;">
<div style="box-sizing: border-box; direction: ltr; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Distributing data containers e.g. Maps, can be a way of avoiding having to think too much about distributing your application. Your business logic is much the same, and it is your data collections which are visible to all your services.</span></div>
</div>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-size: 16px; margin: 0px; padding: 0px;">
<div style="box-sizing: border-box; direction: ltr; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Using centralised or even distributed data stores have a number of scalability issues, as it requires very low-level data access to be distributed in a generic way which isn’t optimised for particular business requirements.</span></div>
</div>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-size: 16px; margin: 0px; padding: 0px;">
<div style="box-sizing: border-box; direction: ltr; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Distributing business components with private data stores is the favoured approach of Microservices and it limits the "surface area" of each service which reduces security issues, performance considerations and gives you more freedom for independent changes to service’s data structures.</span></div>
</div>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-size: 16px; margin: 0px; padding: 0px;">
<div style="box-sizing: border-box; direction: ltr; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">In this review, I will be focusing on distributed data containers, largely because the interfaces are available in the JDK and available for everyone to look at. I expect the conclusions drawn here are broadly similar for Business focused APIs, though each business component will vary.</span></div>
</div>
</div>
<a href="https://vanilla-java.github.io/2016/06/04/Distributing-Common-Java-A-P-Is.html"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Read more by following this link to the new blog!</span></a><br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-9296273754249715472017-03-10T08:46:00.004+00:002018-01-19T11:14:03.662+00:00<h1 class="post-title" itemprop="name headline" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 2.5em; letter-spacing: -1px; line-height: 1; margin: 1em 0px 0.5em; padding: 0px 0px 15px; text-indent: -2px; text-rendering: optimizeLegibility; word-wrap: break-word;">
Modelling Microservice Patterns in Code</h1>
<div>
<h3 id="_service_interactions" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 1.5em; line-height: 1.4; margin: 1em 0px 0.5em; padding: 0px; text-rendering: optimizeLegibility; word-wrap: break-word;">
Service Interactions</h3>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div style="box-sizing: border-box; direction: ltr; font-family: inherit; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
There is a number of simple interactions a service can support. Which pattern is best for your application can depend on what an existing application expects, and what latency requirements you have. Broadly speaking these interactions fall into client-server and peir-to-peir messaging.</div>
</div>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div style="box-sizing: border-box; direction: ltr; font-family: inherit; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
For peir-to-peir messaging, one approach to take is <a href="https://vanilla-java.github.io/2016/05/16/Simple-Asynchronous-Microservices-using-Lambda-Architecture.html" style="background: transparent; box-sizing: border-box; color: #007cc3; line-height: inherit; text-decoration: none; text-rendering: optimizeLegibility; transition: color 0.3s;">Lambda Architecture</a> however from supporting GUIs, client-server models can be easier to work with.</div>
</div>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div style="box-sizing: border-box; direction: ltr; font-family: inherit; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
I feel it is important to design components which could be tested and debugged together, as in a monolith, but can be deployed as multiple <strong style="box-sizing: border-box; line-height: inherit; text-rendering: optimizeLegibility;">right sized</strong> services to different threads, JVMs, or machines.</div>
</div>
</div>
<a href="https://vanilla-java.github.io/2016/05/17/Modelling-Microservice-Patterns-in-Code.html">Read more by following this link to the new blog!</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-10466731357328355052017-03-10T08:45:00.004+00:002018-01-19T11:15:30.972+00:00<h1 class="post-title" itemprop="name headline" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 2.5em; letter-spacing: -1px; line-height: 1; margin: 1em 0px 0.5em; padding: 0px 0px 15px; text-indent: -2px; text-rendering: optimizeLegibility; word-wrap: break-word;">
Simple Asynchronous Microservices using Lambda Architecture.</h1>
<div>
<h3 id="_lambda_architecture" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 1.5em; line-height: 1.4; margin: 1em 0px 0.5em; padding: 0px; text-rendering: optimizeLegibility; word-wrap: break-word;">
Lambda Architecture</h3>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-size: 16px; margin: 0px; padding: 0px;">
<div style="box-sizing: border-box; direction: ltr; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Lambda Architecture is a simple, powerful, though limited example of a Microservice. As it is so simple, you want to use it as much as possible, to expose the more complex services/component in your system which cannot support this interaction model.</span></div>
</div>
</div>
<a href="https://vanilla-java.github.io/2016/05/16/Simple-Asynchronous-Microservices-using-Lambda-Architecture.html"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Read more by following this link to the new blog!</span></a><br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-71237019011612139832017-03-10T08:44:00.001+00:002018-01-19T11:16:59.884+00:00<h1 class="post-title" itemprop="name headline" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 2.5em; letter-spacing: -1px; line-height: 1; margin: 1em 0px 0.5em; padding: 0px 0px 15px; text-indent: -2px; text-rendering: optimizeLegibility; word-wrap: break-word;">
Microservices are about applying a group of Best Practices</h1>
<div>
<h3 id="_microservices_denial" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 1.5em; line-height: 1.4; margin: 1em 0px 0.5em; padding: 0px; text-rendering: optimizeLegibility; word-wrap: break-word;">
Microservices Denial</h3>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-size: 16px; margin: 0px; padding: 0px;">
<div style="box-sizing: border-box; direction: ltr; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">A number of times clients have said; they can’t imagine their organisation using Microservices. I found this surprising as I know those people are using many of the principles of Microservices already.</span></div>
</div>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-size: 16px; margin: 0px; padding: 0px;">
<div style="box-sizing: border-box; direction: ltr; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">I can understand that they feel no need to join the hype around microservices, but the reality is, like it or not, you are most likely using some of the best practices Microservices advocates.</span></div>
</div>
</div>
<a href="https://vanilla-java.github.io/2016/04/30/Microservices-are-about-applying-a-group-of-Best-Practices.html"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Read more by following this link to the new blog!</span></a><br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-85281960380847962017-03-10T08:43:00.001+00:002018-01-19T11:18:23.400+00:00<h1 class="post-title" itemprop="name headline" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 2.5em; letter-spacing: -1px; line-height: 1; margin: 1em 0px 0.5em; padding: 0px 0px 15px; text-indent: -2px; text-rendering: optimizeLegibility; word-wrap: break-word;">
Bad String</h1>
<div>
<span style="background-color: white; color: #222222; font-family: "helvetica neue" , "helvetica" , "helvetica" , "arial" , sans-serif; font-size: 19.5px;">We have a program here that has two threads printing messages alternatively. However, if you change a </span><code class=" language-markup" style="background: rgb(245, 242, 240); border-radius: 0.3em; border: 0px solid rgb(221, 221, 221); box-sizing: border-box; direction: ltr; font-family: Consolas, Monaco, "Andale Mono", monospace; font-size: 15.6px; font-weight: bold; hyphens: none; line-height: inherit; max-width: 100%; padding: 0.1em; tab-size: 4; text-rendering: optimizeLegibility; text-shadow: rgb(255, 255, 255) 0px 1px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;">String </code><span style="background-color: white; color: #222222; font-family: "helvetica neue" , "helvetica" , "helvetica" , "arial" , sans-serif; font-size: 19.5px;">from </span><code class=" language-markup" style="background: rgb(245, 242, 240); border-radius: 0.3em; border: 0px solid rgb(221, 221, 221); box-sizing: border-box; direction: ltr; font-family: Consolas, Monaco, "Andale Mono", monospace; font-size: 15.6px; font-weight: bold; hyphens: none; line-height: inherit; max-width: 100%; padding: 0.1em; tab-size: 4; text-rendering: optimizeLegibility; text-shadow: rgb(255, 255, 255) 0px 1px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;">"cC"</code><span style="background-color: white; color: #222222; font-family: "helvetica neue" , "helvetica" , "helvetica" , "arial" , sans-serif; font-size: 19.5px;"> to </span><code class=" language-markup" style="background: rgb(245, 242, 240); border-radius: 0.3em; border: 0px solid rgb(221, 221, 221); box-sizing: border-box; direction: ltr; font-family: Consolas, Monaco, "Andale Mono", monospace; font-size: 15.6px; font-weight: bold; hyphens: none; line-height: inherit; max-width: 100%; padding: 0.1em; tab-size: 4; text-rendering: optimizeLegibility; text-shadow: rgb(255, 255, 255) 0px 1px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;">"cc"</code><span style="background-color: white; color: #222222; font-family: "helvetica neue" , "helvetica" , "helvetica" , "arial" , sans-serif; font-size: 19.5px;"> it doesn’t print anything, WHY?</span></div>
<div>
<span style="background-color: white; color: #222222; font-family: "helvetica neue" , "helvetica" , "helvetica" , "arial" , sans-serif; font-size: 19.5px;">. . . </span></div>
<br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><a href="https://vanilla-java.github.io/2016/04/21/Bad-String.html">Read more by following this link to the new blog!</a></span><br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-48870085089717471342017-03-10T08:41:00.002+00:002017-03-10T08:41:38.635+00:00<h1 class="post-title" itemprop="name headline" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 2.5em; letter-spacing: -1px; line-height: 1; margin: 1em 0px 0.5em; padding: 0px 0px 15px; text-indent: -2px; text-rendering: optimizeLegibility; word-wrap: break-word;">
A JDBC Gateway Microservice</h1>
<div>
<h3 id="_a_deep_dive_into_a_low_latency_microservice" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 1.5em; line-height: 1.4; margin: 1em 0px 0.5em; padding: 0px; text-rendering: optimizeLegibility; word-wrap: break-word;">
A deep dive into a low latency microservice</h3>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div style="box-sizing: border-box; direction: ltr; font-family: inherit; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
We look at a microservice which can run in it’s own JVM, can perform JDBC updates and queries via a persistent queue for in bound request and a queue for results.</div>
</div>
<div class="paragraph" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div style="box-sizing: border-box; direction: ltr; font-family: inherit; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
In previous posts I looked at the theory behind there low latency micro-services so lets have a look at a micro-service which can do something useful.</div>
<div style="box-sizing: border-box; direction: ltr; font-family: inherit; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
<span style="color: black; font-family: "Times New Roman"; font-size: small;">https://vanilla-java.github.io/2016/04/12/A-J-D-B-C-Gateway-Microservice.html</span></div>
<div style="box-sizing: border-box; direction: ltr; font-family: inherit; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
<br /></div>
</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-36262619097624869232017-02-27T11:47:00.000+00:002017-02-27T11:47:04.293+00:00<header class="post-header" style="background-color: white; box-sizing: border-box; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; text-rendering: optimizeLegibility;"><h1 class="post-title" itemprop="name headline" style="box-sizing: border-box; direction: ltr; font-size: 2.1em; letter-spacing: -1px; line-height: 1; margin: 1em 0px 0.5em; padding: 0px 0px 15px; text-indent: -2px; text-rendering: optimizeLegibility; word-wrap: break-word;">
<a data-pjax="" href="https://vanilla-java.github.io/2016/04/02/Microservices-in-the-Chronicle-World-Part-5.html" itemprop="url" style="background: transparent; box-sizing: border-box; color: #007cc3; line-height: inherit; text-decoration: none; text-rendering: optimizeLegibility; transition: color 0.3s;" title="Microservices in the Chronicle World - Part 5">Microservices in the Chronicle World - Part 5</a></h1>
</header><div class="post-body" itemprop="articleBody" style="background-color: white; box-sizing: border-box; direction: ltr; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div id="preamble" style="box-sizing: border-box; direction: ltr; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div class="sectionbody" style="box-sizing: border-box; direction: ltr; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div class="paragraph" style="box-sizing: border-box; direction: ltr; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div style="box-sizing: border-box; color: #222222; direction: ltr; font-family: inherit; font-size: 1.21875em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
In this part we look at putting a micro service together as a collection of services, and consider how we can evaluate the performance of these services. We introduce JLBH (Java Latency Benchmark Harness) to test these services.</div>
<div style="box-sizing: border-box; direction: ltr; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
<span style="color: #222222; font-family: Helvetica Neue, Helvetica, Helvetica, Arial, sans-serif;"><span style="font-size: 19.5px;">https://vanilla-java.github.io/2016/04/02/Microservices-in-the-Chronicle-World-Part-5.html</span></span></div>
</div>
</div>
</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-58755637581595756032017-02-27T11:46:00.004+00:002017-02-27T11:46:31.479+00:00<header class="post-header" style="background-color: white; box-sizing: border-box; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; text-rendering: optimizeLegibility;"><h1 class="post-title" itemprop="name headline" style="box-sizing: border-box; direction: ltr; font-size: 2.1em; letter-spacing: -1px; line-height: 1; margin: 1em 0px 0.5em; padding: 0px 0px 15px; text-indent: -2px; text-rendering: optimizeLegibility; word-wrap: break-word;">
<a data-pjax="" href="https://vanilla-java.github.io/2016/03/29/Microservices-in-the-Chronicle-world-Part-4.html" itemprop="url" style="background: transparent; box-sizing: border-box; color: #007cc3; line-height: inherit; text-decoration: none; text-rendering: optimizeLegibility; transition: color 0.3s;" title="Microservices in the Chronicle world - Part 4">Microservices in the Chronicle world - Part 4</a></h1>
</header><div class="post-body" itemprop="articleBody" style="background-color: white; box-sizing: border-box; direction: ltr; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div id="preamble" style="box-sizing: border-box; direction: ltr; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div class="sectionbody" style="box-sizing: border-box; direction: ltr; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div class="paragraph" style="box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div style="box-sizing: border-box; direction: ltr; font-family: inherit; font-size: 1.21875em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
A common issue we cover in our workshops is, <em style="box-sizing: border-box; line-height: inherit; text-rendering: optimizeLegibility;">how to restart a queue reader after a failure?</em></div>
</div>
<div class="paragraph" style="box-sizing: border-box; direction: ltr; margin: 0px; padding: 0px; text-rendering: optimizeLegibility;">
<div style="box-sizing: border-box; color: #222222; direction: ltr; font-family: inherit; font-size: 1em; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
The answer is not a simple as you might think.</div>
<div style="box-sizing: border-box; direction: ltr; line-height: 1.6; margin-bottom: 1.25em; padding: 0px; text-rendering: optimizeLegibility;">
<span style="color: #222222; font-family: Helvetica Neue, Helvetica, Helvetica, Arial, sans-serif;">https://vanilla-java.github.io/2016/03/29/Microservices-in-the-Chronicle-world-Part-4.html</span></div>
</div>
</div>
</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-57021122423879648032017-02-27T11:45:00.005+00:002017-02-27T11:45:45.798+00:00<h1 class="post-title" itemprop="name headline" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 2.1em; letter-spacing: -1px; line-height: 1; margin: 1em 0px 0.5em; padding: 0px 0px 15px; text-indent: -2px; text-rendering: optimizeLegibility; word-wrap: break-word;">
<a data-pjax="" href="https://vanilla-java.github.io/2016/03/26/Microservices-in-the-Chronicle-World-Part-3.html" itemprop="url" style="background: transparent; box-sizing: border-box; color: #007cc3; line-height: inherit; text-decoration: none; text-rendering: optimizeLegibility; transition: color 0.3s;" title="Microservices in the Chronicle World - Part 3">Microservices in the Chronicle World - Part 3</a></h1>
<div>
<span style="background-color: white; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 19.5px;">One of the problems with using microservices is performance. </span><strong style="background-color: white; box-sizing: border-box; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 19.5px; line-height: inherit; text-rendering: optimizeLegibility;">Latencies</strong><span style="background-color: white; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 19.5px;"> can be higher due to the cost of </span><strong style="background-color: white; box-sizing: border-box; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 19.5px; line-height: inherit; text-rendering: optimizeLegibility;">serialization</strong><span style="background-color: white; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 19.5px;">, messaging and deserialization, and this reduces </span><strong style="background-color: white; box-sizing: border-box; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 19.5px; line-height: inherit; text-rendering: optimizeLegibility;">throughput</strong><span style="background-color: white; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 19.5px;">. In particular, poor throughput is a problem because the reason we are designing a </span><a href="http://searchdatacenter.techtarget.com/definition/scalability" style="background: rgb(255, 255, 255); box-sizing: border-box; color: #007cc3; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 19.5px; line-height: inherit; text-decoration: none; text-rendering: optimizeLegibility; transition: color 0.3s;">scalable system</a><span class="footnote" style="background-color: white; box-sizing: border-box; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 14.625px; line-height: 0; position: relative; text-rendering: optimizeLegibility; top: -0.5em; vertical-align: baseline;">[<a class="footnote" href="https://vanilla-java.github.io/2016/03/26/Microservices-in-the-Chronicle-World-Part-3.html#_footnote_1" id="_footnoteref_1" style="background: transparent; box-sizing: border-box; color: #007cc3; line-height: inherit; text-decoration: none; text-rendering: optimizeLegibility; transition: color 0.3s;" title="View footnote.">1</a>]</span><span style="background-color: white; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 19.5px;"> is to increase throughput.</span></div>
<div>
<span style="background-color: white; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 19.5px;"><br /></span></div>
<div>
<span style="background-color: white; font-size: 19.5px;"><span style="color: #222222; font-family: Helvetica Neue, Helvetica, Helvetica, Arial, sans-serif;">https://vanilla-java.github.io/2016/03/26/Microservices-in-the-Chronicle-World-Part-3.html</span></span></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-1729822519392175009.post-51569740485021482742017-02-27T11:45:00.001+00:002017-02-27T11:45:04.926+00:00<h1 class="post-title" itemprop="name headline" style="background-color: white; box-sizing: border-box; color: #222222; direction: ltr; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 2.1em; letter-spacing: -1px; line-height: 1; margin: 1em 0px 0.5em; padding: 0px 0px 15px; text-indent: -2px; text-rendering: optimizeLegibility; word-wrap: break-word;">
<a data-pjax="" href="https://vanilla-java.github.io/2016/03/24/Microservices-in-the-Chronicle-world-Part-2.html" itemprop="url" style="background: transparent; box-sizing: border-box; color: #007cc3; line-height: inherit; text-decoration: none; text-rendering: optimizeLegibility; transition: color 0.3s;" title="Microservices in the Chronicle world - Part 2">Microservices in the Chronicle world - Part 2</a></h1>
<div>
<span style="background-color: white; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px;">In </span><a href="https://vanilla-java.github.io/2016/03/23/Microservices-in-the-Chronicle-world-Part-1.html" style="background: rgb(255, 255, 255); box-sizing: border-box; color: #007cc3; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: inherit; text-decoration: none; text-rendering: optimizeLegibility; transition: color 0.3s;">Part 1</a><span style="background-color: white; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px;">, we looked at how we can easily create and test components which expect asynchronous messages </span><span style="background-color: white; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px;">in and produce asynchronous messages out. However, how do we turn this into a </span><strong style="background-color: white; box-sizing: border-box; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: inherit; text-rendering: optimizeLegibility;">service</strong><span style="background-color: white; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px;">?</span></div>
<div>
<span style="background-color: white; color: #222222; font-family: "Helvetica Neue", Helvetica, Helvetica, Arial, sans-serif; font-size: 16px;"><br /></span></div>
<div>
<span style="background-color: white;"><span style="color: #222222; font-family: Helvetica Neue, Helvetica, Helvetica, Arial, sans-serif;">https://vanilla-java.github.io/2016/03/24/Microservices-in-the-Chronicle-world-Part-2.html</span></span></div>
Unknownnoreply@blogger.com0