Skip to content

Commit

Permalink
deploy: 05ca192
Browse files Browse the repository at this point in the history
  • Loading branch information
lihaoyi committed Jan 18, 2025
1 parent d7ef712 commit 3739b4a
Showing 1 changed file with 75 additions and 2 deletions.
77 changes: 75 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
.Styles-subtleLink{
text-decoration: none;
}
</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px; background-color: #f8f8f8;"><div class="WideStyles-header NarrowStyles-header Styles-headerStyle"><div class="NarrowStyles-headerContent"><h1 style="text-align: center; padding: 30px 30px; margin: 0px;"><a style="color: #f8f8f8; font-weight: bold;" href="" class="Styles-subtleLink NarrowStyles-flexFont"> Cask</a></h1><div class="Styles-headerLinkBox"><div class="WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class="NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto; flex-shrink: 1; min-height: 0px;"><ul style="overflow: hidden; text-align: start; margin-top: 10px; white-space: nowrap; text-overflow: ellipsis; margin-right: 10px;"><li class="WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="index.html">Cask - a Scala HTTP micro-framework</a></li><li class="WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="page/main-customization.html">Main Customization</a></li><li class="WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="page/about-cask.html">About Cask</a></li></ul></div></div></div></div><hr class="NarrowStyles-disappear" style="background-color: #f8f8f8; width: 80%;" /><div class="WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class="NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto; flex-shrink: 1; min-height: 0px;"><ul style="overflow: hidden; text-align: start; margin-top: 10px; white-space: nowrap; text-overflow: ellipsis; margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#getting-started">Getting Started</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#minimal-example">Minimal Example</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#variable-routes">Variable Routes</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#query-params">Query Params</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#multi-method-routes">Multi-method Routes</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#receiving-form-encoded-or-json-data">Receiving Form-encoded or JSON data</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#processing-cookies">Processing Cookies</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#serving-static-files">Serving Static Files</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#redirects-or-aborts">Redirects or Aborts</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#html-rendering">HTML Rendering</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#extending-endpoints-with-decorators">Extending Endpoints with Decorators</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#custom-endpoints">Custom Endpoints</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#gzip--deflated-responses">Gzip &amp; Deflated Responses</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#websockets">Websockets</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#todomvc-api-server">TodoMVC Api Server</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#todomvc-database-integration">TodoMVC Database Integration</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#todomvc-full-stack-web">TodoMVC Full Stack Web</a></li></ul></div></div></div><div class="WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Cask - a Scala HTTP micro-framework</h1><div style="margin-bottom: 10px;"><div style="display: flex; flex-direction: row; justify-content: space-between;"><div></div><a href="page/main-customization.html">Main Customization <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><p><a href="https://discord.gg/scala"><div style="text-align: center"><img src="https://img.shields.io/badge/discord-join_chat-61AA8F.svg?logo=discord" alt="Discord Chat" style="max-width: 100%; max-height: 500px" /></div></a> <a href="https://www.patreon.com/lihaoyi"><div style="text-align: center"><img src="https://img.shields.io/badge/patreon-sponsor-ff69b4.svg" alt="Patreon" style="max-width: 100%; max-height: 500px" /></div></a></p>
</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px; background-color: #f8f8f8;"><div class="WideStyles-header NarrowStyles-header Styles-headerStyle"><div class="NarrowStyles-headerContent"><h1 style="text-align: center; padding: 30px 30px; margin: 0px;"><a style="color: #f8f8f8; font-weight: bold;" href="" class="Styles-subtleLink NarrowStyles-flexFont"> Cask</a></h1><div class="Styles-headerLinkBox"><div class="WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class="NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto; flex-shrink: 1; min-height: 0px;"><ul style="overflow: hidden; text-align: start; margin-top: 10px; white-space: nowrap; text-overflow: ellipsis; margin-right: 10px;"><li class="WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="index.html">Cask - a Scala HTTP micro-framework</a></li><li class="WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="page/main-customization.html">Main Customization</a></li><li class="WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="page/about-cask.html">About Cask</a></li></ul></div></div></div></div><hr class="NarrowStyles-disappear" style="background-color: #f8f8f8; width: 80%;" /><div class="WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class="NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto; flex-shrink: 1; min-height: 0px;"><ul style="overflow: hidden; text-align: start; margin-top: 10px; white-space: nowrap; text-overflow: ellipsis; margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#getting-started">Getting Started</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#minimal-example">Minimal Example</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#variable-routes">Variable Routes</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#query-params">Query Params</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#multi-method-routes">Multi-method Routes</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#receiving-form-encoded-or-json-data">Receiving Form-encoded or JSON data</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#processing-cookies">Processing Cookies</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#serving-static-files">Serving Static Files</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#redirects-or-aborts">Redirects or Aborts</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#html-rendering">HTML Rendering</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#extending-endpoints-with-decorators">Extending Endpoints with Decorators</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#custom-endpoints">Custom Endpoints</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#gzip--deflated-responses">Gzip &amp; Deflated Responses</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#websockets">Websockets</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#todomvc-api-server">TodoMVC Api Server</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#todomvc-database-integration">TodoMVC Database Integration</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#todomvc-full-stack-web">TodoMVC Full Stack Web</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class="WideStyles-tableOfContentsItem" href="#running-cask-with-virtual-threads">Running Cask with Virtual Threads</a></li></ul></div></div></div><div class="WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Cask - a Scala HTTP micro-framework</h1><div style="margin-bottom: 10px;"><div style="display: flex; flex-direction: row; justify-content: space-between;"><div></div><a href="page/main-customization.html">Main Customization <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><p><a href="https://discord.gg/scala"><div style="text-align: center"><img src="https://img.shields.io/badge/discord-join_chat-61AA8F.svg?logo=discord" alt="Discord Chat" style="max-width: 100%; max-height: 500px" /></div></a> <a href="https://www.patreon.com/lihaoyi"><div style="text-align: center"><img src="https://img.shields.io/badge/patreon-sponsor-ff69b4.svg" alt="Patreon" style="max-width: 100%; max-height: 500px" /></div></a></p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">package app
object MinimalApplication extends cask.MainRoutes{
@cask.get(&quot;/&quot;)
Expand Down Expand Up @@ -1222,4 +1222,77 @@
</code></pre>
<ul>
<li><a href="https://github.com/lihaoyi/cask/releases/download/0.9.5/todo-0.9.5.zip">example project</a></li>
</ul><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Cask, the <a href="lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Cask, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex; flex-direction: row; justify-content: space-between;"><div></div><a href="page/main-customization.html">Main Customization <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html>
</ul><h2 id="running-cask-with-virtual-threads" class="Styles-hoverBox">Running Cask with Virtual Threads<a href="#running-cask-with-virtual-threads" class="Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
<p>$$minimalApplicationWithLoom</p>
<p>Cask can support using Virtual Threads to handle the request out of the box, you can enable it with the next steps:</p>
<ol>
<li>Running cask with Java 21 or later</li>
<li>add <code>--add-opens java.base/java.lang=ALL-UNNAMED</code> to your JVM options, which is needed to name the virtual threads.</li>
<li>add <code>-Dcask.virtual-threads.enabled=true</code> to your JVM options, which is needed to enable the virtual threads.</li>
<li>tweak the underlying carrier threads with <code>-Djdk.virtualThreadScheduler.parallelism</code>, <code>jdk.virtualThreadScheduler.maxPoolSize</code> and <code>jdk.unparker.maxPoolSize</code>.</li>
</ol>
<p><strong>Advanced Features</strong>: 1. You can change the default scheduler of the carrier threads with <code>cask.internal.Util.createVirtualThreadExecutor</code> method, but keep in mind, that's not officially supported by JDK for now. 2. You can supply your own <code>Executor</code> by override the <code>handlerExecutor()</code> method in your <code>cask.Main</code> object, which will be called only once when the server starts. 3. You can use <code>jdk.internal.misc.Blocker</code>'s <code>begin</code> and <code>end</code> methods to help the <code>ForkJoinPool</code> when needed.</p>
<p><strong>NOTE</strong>: 1. If your code is CPU-bound, you should not use virtual threads, because it will not improve the performance, but will increase the overhead. 2. A common deadlock can happen when both a virtual thread and a platform thread try to load the same class, but there is no carrier thread available to execute the virtual thread, which will lead to a deadlock, make sure <code>jdk.virtualThreadScheduler.maxPoolSize</code> is large enough to avoid it. 3. Virtual thread does some kind of <code>rescheduling</code> which may lead to higher latency when the task is actually cpu bound. 4. OOM is a common issue when you have many virtual threads, you should limit the max in-flight requests to avoid it. 5. There are some known issues which can leads to a deadlock, you should be careful when using it in production, at least after long time stress test. 6. <a href="https://openjdk.org/jeps/491">JEP 491: Synchronize Virtual Threads without Pinning</a> will be shipped in Java 24. 7. Some info from early adaptor <a href="https://craft.faire.com/java-virtual-threads-increasing-search-performance-while-avoiding-deadlocks-f12fa296d521">faire</a></p>
<p><strong>Some benchmark results</strong>:</p><table class="table table-bordered">
<thead>
<tr>
<th>Test Case </th>
<th>Thread Type </th>
<th>Requests/sec </th>
<th>Avg Latency </th>
<th>Max Latency </th>
<th>Transfer/sec </th>
</tr>
</thead>
<tbody>
<tr>
<td>staticFilesWithLoom </td>
<td>Platform </td>
<td>81,766.27 </td>
<td>1.23ms </td>
<td>28.64ms </td>
<td>11.38MB </td>
</tr>
<tr>
<td>staticFilesWithLoom </td>
<td>Virtual </td>
<td>75,488.32 </td>
<td>4.41ms </td>
<td>157.91ms </td>
<td>10.51MB </td>
</tr>
<tr>
<td>todoDbWithLoom </td>
<td>Platform </td>
<td>81,929.40 </td>
<td>1.22ms </td>
<td>11.67ms </td>
<td>13.13MB </td>
</tr>
<tr>
<td>todoDbWithLoom </td>
<td>Virtual </td>
<td>76,072.80 </td>
<td>3.97ms </td>
<td>160.29ms </td>
<td>12.19MB </td>
</tr>
<tr>
<td>minimalApplicationWithLoom </td>
<td>Platform </td>
<td>38.36 </td>
<td>1.05s </td>
<td>1.99s </td>
<td>5.73KB </td>
</tr>
<tr>
<td>minimalApplicationWithLoom </td>
<td>Virtual </td>
<td>935.74 </td>
<td>106.11ms </td>
<td>126.59ms </td>
<td>139.81KB </td>
</tr>
</tbody></table>
<p><a href="https://github.com/com-lihaoyi/cask/pull/159">data source</a></p>
<p><em>Minimal Application (minimalApplicationWithLoom)</em> - Virtual threads show significantly better performance: - ~24x higher throughput (935.74 vs 38.36 requests/sec) - Much better latency (106.11ms vs 1.05s) - Platform threads experienced 1,076 timeout errors while virtual threads had none</p><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Cask, the <a href="lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Cask, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex; flex-direction: row; justify-content: space-between;"><div></div><a href="page/main-customization.html">Main Customization <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html>

0 comments on commit 3739b4a

Please sign in to comment.