<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Gamlor</title>
	<atom:link href="https://www.gamlor.info/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.gamlor.info/wordpress</link>
	<description>thoughts about programming, tv-series and other geeky stuff.</description>
	<lastBuildDate>Thu, 11 Mar 2021 08:42:56 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.3</generator>
	<item>
		<title>Blog moved to https://gamlor.info</title>
		<link>https://www.gamlor.info/wordpress/2019/09/blog-moved-to-https-gamlor-info/</link>
		
		<dc:creator><![CDATA[gamlerhart]]></dc:creator>
		<pubDate>Wed, 04 Sep 2019 20:18:50 +0000</pubDate>
				<category><![CDATA[42]]></category>
		<guid isPermaLink="false">https://www.gamlor.info/wordpress/?p=3737</guid>

					<description><![CDATA[<p>The main blog moved to https://gamlor.info. This blog stays up as an archive =)</p>
<p>The post <a href="https://www.gamlor.info/wordpress/2019/09/blog-moved-to-https-gamlor-info/">Blog moved to https://gamlor.info</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>The main blog moved to <a href="https://gamlor.info">https://gamlor.info</a>. This blog stays up as an archive =)</p><p>The post <a href="https://www.gamlor.info/wordpress/2019/09/blog-moved-to-https-gamlor-info/">Blog moved to https://gamlor.info</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Korean Hangul Stopped Working After IBus Update to 1.5.18? A Work Around.</title>
		<link>https://www.gamlor.info/wordpress/2018/05/ibus-1-5-18-stopped-working-en/</link>
		
		<dc:creator><![CDATA[gamlerhart]]></dc:creator>
		<pubDate>Sun, 06 May 2018 00:47:26 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Technical Wibbly Wobbly]]></category>
		<guid isPermaLink="false">https://www.gamlor.info/wordpress/?p=3713</guid>

					<description><![CDATA[<p>When I&#8217;m using Linux I use IBus to write Korean. A few days ago when I updated my Manjaro installation writing Korean stopped working. After booting everything looked fine. The&#8230;</p>
<p>The post <a href="https://www.gamlor.info/wordpress/2018/05/ibus-1-5-18-stopped-working-en/">Korean Hangul Stopped Working After IBus Update to 1.5.18? A Work Around.</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>When I&#8217;m using Linux I use <a href="ttps://github.com/ibus/ibus/">IBus</a> to write Korean. A few days ago when I updated my <a href="https://manjaro.org/">Manjaro</a> installation writing Korean stopped working. After booting everything looked fine. The IBus tray icon was there, switching languages with Win+Space seemed to work.</p>
<p><div id="attachment_3695" style="width: 310px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/icon-ok.png"><img decoding="async" aria-describedby="caption-attachment-3695" class="size-medium wp-image-3695" src="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/icon-ok-300x146.png" alt="OK!" width="300" height="146" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/icon-ok-300x146.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/icon-ok.png 679w" sizes="(max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-3695" class="wp-caption-text">OK!</p></div></p>
<p><div id="attachment_3697" style="width: 310px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/switch-ok.png"><img decoding="async" aria-describedby="caption-attachment-3697" class="size-medium wp-image-3697" src="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/switch-ok-300x135.png" alt="Win+Space=OK" width="300" height="135" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/switch-ok-300x135.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/switch-ok.png 603w" sizes="(max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-3697" class="wp-caption-text">Win+Space=OK</p></div></p>
<p>However, when I started to type the IBus icon suddenly changed and it wrote in English. I didn&#8217;t know that icon and it seemed strange. There was no error message. IBus just always switched to that icon and then wrote in the English alphabet.</p>
<p><div id="attachment_3717" style="width: 310px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/not-ok-en.png"><img decoding="async" aria-describedby="caption-attachment-3717" class="size-medium wp-image-3717" src="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/not-ok-en-300x121.png" alt="What is this?" width="300" height="121" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/not-ok-en-300x121.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/not-ok-en.png 763w" sizes="(max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-3717" class="wp-caption-text">What is this?</p></div></p>
<p>Well, first I searched the Internet without success. I found only old entries which did no help. So, maybe there are logs? I couldn&#8217;t find any IBus log in /var/logs or something like that. However, the IBus man page told about a &#8211;verbose flag. So, I used that and tada, there were error messages:</p>
<pre>[gamlor@gamlor-t470p ~]$ ibus-daemon --verbose -r &amp;
[4] 13270
[gamlor@gamlor-t470p ~]$ 
(ibus-daemon:13170): GLib-WARNING **: 21:33:08.140: GChildWatchSource: Exit status of a child process was requested but ECHILD was received by waitpid(). See the documentation of g_child_watch_source_new() for possible causes.
(ibus-engine-hangul:13296): IBUS-WARNING **: 21:33:08.224: org.freedesktop.IBus.Config.GetValue: GDBus.Error:org.freedesktop.DBus.Error.Failed: Config value [engine/hangul:on-keys] does not exist.
(ibus-engine-hangul:13296): IBUS-WARNING **: 21:33:08.224: org.freedesktop.IBus.Config.GetValue: GDBus.Error:org.freedesktop.DBus.Error.Failed: Config value [engine/hangul:off-keys] does not exist.
(ibus-daemon:13270): GLib-CRITICAL **: 21:33:08.229: g_variant_unref: assertion 'value != NULL' failed
(ibus-ui-gtk3:13277): IBUS-WARNING **: 21:33:13.143: ibus_bus_call_sync: org.freedesktop.DBus.Properties.Get: GDBus.Error:org.freedesktop.DBus.Error.Failed: No global engine.
</pre>
<p>Oh&#8230;&#8217;assert failed&#8217; doesn&#8217;t sound good. And whenever I tried to write Korean, the `bus_bus_call_sync&#8230;No global engine` message got printed. So I searched for that error message and found this <a href="https://github.com/ibus/ibus/issues/2004">Github issue</a>. There is a work around: When configuring an Emoji selection key, the issue goes away. Strange. So, I did that and everything worked again. Here&#8217;s how: IBus Preference -> Emoji -> &#8230; Button -> Select a impossible key combination -> Add -> Done!</p>
<p><div id="attachment_3707" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/fix-all.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3707" src="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/fix-all-1024x224.png" alt="Work around" width="700" height="153" class="size-large wp-image-3707" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/fix-all-1024x224.png 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/fix-all-300x66.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/fix-all-768x168.png 768w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3707" class="wp-caption-text">Work around</p></div></p>
<p>The end</p><p>The post <a href="https://www.gamlor.info/wordpress/2018/05/ibus-1-5-18-stopped-working-en/">Korean Hangul Stopped Working After IBus Update to 1.5.18? A Work Around.</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>IBus 1.5.18 업데이트 후에는 한글 멈췄어요? 임시 해결이 있어요.</title>
		<link>https://www.gamlor.info/wordpress/2018/05/ibus-1-5-18-stopped-working-kor/</link>
		
		<dc:creator><![CDATA[gamlerhart]]></dc:creator>
		<pubDate>Sat, 05 May 2018 13:03:54 +0000</pubDate>
				<category><![CDATA[Technical Wibbly Wobbly]]></category>
		<category><![CDATA[한국어 배우기]]></category>
		<category><![CDATA[ibus]]></category>
		<category><![CDATA[kde]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[manjaro]]></category>
		<category><![CDATA[unix]]></category>
		<guid isPermaLink="false">https://www.gamlor.info/wordpress/?p=3687</guid>

					<description><![CDATA[<p>저는 Linux 사용하면 한글 쓰기 위해 IBus 사용해요. 몇일 전에 Manjaro Linux 업데이트했어요. 이 업데이트 호에 한글 쓰는데 갑자기 멈췄어요. 부팅후에 다 괜찮게 보였어요. IBus의 아이콘 보이고, Win-Space 키보드 키로&#8230;</p>
<p>The post <a href="https://www.gamlor.info/wordpress/2018/05/ibus-1-5-18-stopped-working-kor/">IBus 1.5.18 업데이트 후에는 한글 멈췄어요? 임시 해결이 있어요.</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>저는 Linux 사용하면 한글 쓰기 위해 IBus 사용해요. 몇일 전에 Manjaro Linux 업데이트했어요. 이 업데이트 호에 한글 쓰는데 갑자기 멈췄어요. 부팅후에 다 괜찮게 보였어요. IBus의 아이콘 보이고, Win-Space 키보드 키로 언어 바꿀 수 있고 다 괜찮은 것 같았어요.<br />
<div id="attachment_3695" style="width: 310px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/icon-ok.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3695" src="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/icon-ok-300x146.png" alt="OK!" width="300" height="146" class="size-medium wp-image-3695" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/icon-ok-300x146.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/icon-ok.png 679w" sizes="(max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-3695" class="wp-caption-text">OK!</p></div><br />
<div id="attachment_3697" style="width: 310px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/switch-ok.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3697" src="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/switch-ok-300x135.png" alt="Win+Space=OK" width="300" height="135" class="size-medium wp-image-3697" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/switch-ok-300x135.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/switch-ok.png 603w" sizes="(max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-3697" class="wp-caption-text">Win+Space=OK</p></div></p>
<p>하지만, 쓰기 시작할 떼 IBus의 아이콘이 갑자기 바꿨고 영어로 썼어요. 제거 그 아이콘을 몰랐어서 이상하는 것 같아요. 에러 메시지도 없어요. IBus가 그냥 항상 그 아이콘 보여주고 영어로 썼어요 =(<br />
<div id="attachment_3699" style="width: 310px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/not-ok-kor.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3699" src="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/not-ok-kor-300x116.png" alt="이것 뭐예요?" width="300" height="116" class="size-medium wp-image-3699" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/not-ok-kor-300x116.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/not-ok-kor-768x298.png 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/not-ok-kor.png 804w" sizes="(max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-3699" class="wp-caption-text">이것 뭐예요?</p></div></p>
<p>그럼 제가 먼지 이 문제를 인터넷으로 검색했고 아무것도 못 찾아요. 그냥 오래된 못 도웠어요. 그럼 아마 오류 로그가 있어요? /var/log에 IBus의 로그가 없어요. 근데 man 페이지에 &#8211;verbose 명령 행을 찾았고 사용하면 오류 로그 있어요:</p>
<pre>
[gamlor@gamlor-t470p ~]$ ibus-daemon --verbose -r &
[4] 13270
[gamlor@gamlor-t470p ~]$ 
(ibus-daemon:13170): GLib-WARNING **: 21:33:08.140: GChildWatchSource: Exit status of a child process was requested but ECHILD was received by waitpid(). See the documentation of g_child_watch_source_new() for possible causes.
(ibus-engine-hangul:13296): IBUS-WARNING **: 21:33:08.224: org.freedesktop.IBus.Config.GetValue: GDBus.Error:org.freedesktop.DBus.Error.Failed: Config value [engine/hangul:on-keys] does not exist.
(ibus-engine-hangul:13296): IBUS-WARNING **: 21:33:08.224: org.freedesktop.IBus.Config.GetValue: GDBus.Error:org.freedesktop.DBus.Error.Failed: Config value [engine/hangul:off-keys] does not exist.
(ibus-daemon:13270): GLib-CRITICAL **: 21:33:08.229: g_variant_unref: assertion 'value != NULL' failed
(ibus-ui-gtk3:13277): IBUS-WARNING **: 21:33:13.143: ibus_bus_call_sync: org.freedesktop.DBus.Properties.Get: GDBus.Error:org.freedesktop.DBus.Error.Failed: No global engine.
</pre>
<p>어머&#8230;assert failed다로 진짜 안 좋아요. 근데 제가 한글 써보면 `bus_bus_call_sync&#8230;No global engine` 항상 났어요. 그래서 제가 이 오류를 검색했고 이 <a href="https://github.com/ibus/ibus/issues/2004">GitHub 문제 글</a> 찾았어요. 저기에 임시 해결이 있어요: 에모지의 선택 키를 설정하면 문제 멈출 것 예요. 이상해지? 그럼 제가 그렇게 했고 다 다시 작동했어요. 방법이에요: IBus Preference -> Emoji -> &#8230; 버튼 -> 제가 불가능한 키를 설정했어요 -> Add -> 완료됐어요!</p>
<p><div id="attachment_3707" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/fix-all.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3707" src="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/fix-all-1024x224.png" alt="임시 해결" width="700" height="153" class="size-large wp-image-3707" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/fix-all-1024x224.png 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/fix-all-300x66.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2018/05/fix-all-768x168.png 768w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3707" class="wp-caption-text">임시 해결</p></div></p>
<p>끝 =)</p><p>The post <a href="https://www.gamlor.info/wordpress/2018/05/ibus-1-5-18-stopped-working-kor/">IBus 1.5.18 업데이트 후에는 한글 멈췄어요? 임시 해결이 있어요.</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Async Database Connector for Java (ADBCJ) on JCenter.</title>
		<link>https://www.gamlor.info/wordpress/2017/10/async-database-connector-for-java-adbcj-on-jcenter/</link>
		
		<dc:creator><![CDATA[gamlerhart]]></dc:creator>
		<pubDate>Tue, 24 Oct 2017 11:55:57 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Technical Wibbly Wobbly]]></category>
		<category><![CDATA[adbcj]]></category>
		<category><![CDATA[async]]></category>
		<guid isPermaLink="false">https://www.gamlor.info/wordpress/?p=3660</guid>

					<description><![CDATA[<p>Due to lack of time and interest, ADBCJ is in &#8216;maintenance&#8217; mode. However, I still improve it from time to time =). ADBCJ in JCenter Finally, ADBCJ is in a&#8230;</p>
<p>The post <a href="https://www.gamlor.info/wordpress/2017/10/async-database-connector-for-java-adbcj-on-jcenter/">Async Database Connector for Java (ADBCJ) on JCenter.</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Due to lack of time and interest, ADBCJ is in &#8216;maintenance&#8217; mode. However, I still improve it from time to time =).</p>
<p><div id="attachment_3669" style="width: 394px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/adbcj-icu.jpg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3669" class=" wp-image-3669" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/adbcj-icu.jpg" alt="" width="384" height="642" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/adbcj-icu.jpg 574w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/adbcj-icu-179x300.jpg 179w" sizes="(max-width: 384px) 100vw, 384px" /></a><p id="caption-attachment-3669" class="wp-caption-text">ADBCJ will be fine ^.^</p></div></p>
<h2>ADBCJ in JCenter</h2>
<p>Finally, ADBCJ is in a decent Maven repository! That is a long standing to do crossed of the list. First, you&#8217;ll need to add JCenter to your projects maven repos. Unless your build tool has the JCenter by default.<br />
For Maven:</p>
<pre><code>&lt;repository&gt;
 &lt;snapshots&gt;
 &lt;enabled&gt;false&lt;/enabled&gt;
 &lt;/snapshots&gt;
 &lt;id&gt;central&lt;/id&gt;
 &lt;name&gt;bintray&lt;/name&gt;
 &lt;url&gt;https://jcenter.bintray.com&lt;/url&gt;
&lt;/repository&gt;
</code></pre>
<p>After than you include ADBCJ as a dependency.</p>
<p>MySQL driver:</p>
<pre><code>&lt;dependency&gt;
    &lt;groupId&gt;org.adbcj&lt;/groupId&gt;
    &lt;artifactId&gt;adbcj-api&lt;/artifactId&gt;
    &lt;version&gt;0.9&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.adbcj&lt;/groupId&gt;
    &lt;artifactId&gt;mysql-async-driver&lt;/artifactId&gt;
    &lt;version&gt;0.9&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
<p>H2 driver:</p>
<pre><code>&lt;dependency&gt;
    &lt;groupId&gt;org.adbcj&lt;/groupId&gt;
    &lt;artifactId&gt;adbcj-api&lt;/artifactId&gt;
    &lt;version&gt;0.9&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.adbcj&lt;/groupId&gt;
    &lt;artifactId&gt;h2-async-driver&lt;/artifactId&gt;
    &lt;version&gt;0.9&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
<h2>Changes&lt;/h2</h2>
<h3>Java 8</h3>
<p>Recent ADBCJ versions requires Java 8. Instead of ADBCJ&#8217;s own future implementations, methods now return Java 8&#8217;s <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html">completable futures</a> =).</p>
<h3>Callback API</h3>
<p>Java 8&#8217;s futures are not every bodies taste. Especially other JVM language have their own futures and concurrency constructs. Or you might really do not want a future based control flow. So, I changed ADBCJ&#8217;s basic API to be callback driven. That allows to use other concurrency constructs without going through Java futures as intermediate step. The Java 8 completable future methods are also implemented in term of these futures.</p>
<h2>Examples on Github</h2>
<p>Examples how to use ADBCJ are on <a href="https://github.com/gamlerhart/adbcj/blob/master/Readme.md">GitHub</a>.</p><p>The post <a href="https://www.gamlor.info/wordpress/2017/10/async-database-connector-for-java-adbcj-on-jcenter/">Async Database Connector for Java (ADBCJ) on JCenter.</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Need a CDN? Try out edgemesh.com.</title>
		<link>https://www.gamlor.info/wordpress/2017/10/need-a-cdn-try-out-edgemesh-com/</link>
		
		<dc:creator><![CDATA[gamlerhart]]></dc:creator>
		<pubDate>Mon, 09 Oct 2017 14:01:24 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Technical Wibbly Wobbly]]></category>
		<category><![CDATA[cdn]]></category>
		<category><![CDATA[edgemesh]]></category>
		<guid isPermaLink="false">https://www.gamlor.info/wordpress/?p=3627</guid>

					<description><![CDATA[<p>Do you need a CDN for your website? Maybe you want to try edgemesh.com. The basic subscription is free! Start First sign up on edgemesh.com. Then embed this script into&#8230;</p>
<p>The post <a href="https://www.gamlor.info/wordpress/2017/10/need-a-cdn-try-out-edgemesh-com/">Need a CDN? Try out edgemesh.com.</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Do you need a CDN for your website? Maybe you want to try edgemesh.com. The basic subscription is free!</p>
<h2>Start</h2>
<p>First sign up on <a href="https://edgemesh.com/">edgemesh.com</a>. Then embed this script into your website:</p>
<p><script src="https://gist.github.com/d71405db7a446220a11590dac0246a3b.js?file=edge-mesh.html"></script><noscript><pre><code class="language-html html">&lt;script
    type=&quot;application/javascript&quot;
    src=&quot;https://sig.edgeno.de/edgemesh.client.min.js&quot;
    onload=&quot;window.edgemesh = new Edgemesh()&quot;&gt;
&lt;/script&gt;</code></pre></noscript></p>
<p>Done. Really!</p>
<h2>So, how does Edgemesh work?</h2>
<p>A normal CDN has tons of servers all over the world. Those server caches your images, CSS and Javascript. So, visitors can download your content quickly from a close CDN server. However, if there is no CDN server in your visitors area, they won`t benefit from quick downloads. And CDN servers are not free!<br />
<div id="attachment_3649" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-en-final.jpg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3649" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-en-final-1024x696.jpg" alt="" width="700" height="476" class="size-large wp-image-3649" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-en-final-1024x696.jpg 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-en-final-300x204.jpg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-en-final-768x522.jpg 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-en-final.jpg 1177w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3649" class="wp-caption-text">Classic CDN</p></div><br />
Edgemesh works differently. Nowadays our phones and computers are really fast. Our web browsers are powerful. Browsers have an IndexeDB database and can do P2P networking with WebRTC. This is what Edgemesh uses. When visitors visit a website, Edgemesh stores some content in their browser. When another nearby visitor needs the same content, they download it from other visitor`s browsers. Therefore, if you have many visitors, they can fetch the content quickly from each other.</p>
<p><div id="attachment_3653" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-en-final.jpg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3653" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-en-final-1024x613.jpg" alt="" width="700" height="419" class="size-large wp-image-3653" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-en-final-1024x613.jpg 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-en-final-300x180.jpg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-en-final-768x460.jpg 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-en-final.jpg 1336w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3653" class="wp-caption-text">Edgemesh</p></div><br />
However, we can not trust the visitor`s internet connection. Maybe it is very slow, maybe it is suddenly interrupted. So, Edgemesh prefetches some content and falls back to regular downloads if it is to slow. Also, you can add Edgemesh &#8216;supernodes&#8217;, which act a bit like a regular CDN servers. Furthermore, you can combine Edgemesh with a traditional CDN.</p>
<h2>Does it work?</h2>
<p>Yes. This blog has close to no visitors, yet Edgemesh manages to store and distribute some content:<br />
<div id="attachment_3640" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh-1.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3640" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh-1-1024x576.png" alt="" width="700" height="394" class="size-large wp-image-3640" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh-1-1024x576.png 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh-1-300x169.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh-1-768x432.png 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh-1.png 1920w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3640" class="wp-caption-text">This sites Edgemesh network</p></div><br />
Just try it out on your site. =)</p><p>The post <a href="https://www.gamlor.info/wordpress/2017/10/need-a-cdn-try-out-edgemesh-com/">Need a CDN? Try out edgemesh.com.</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>CDN 필요하면 edgemesh.com 사용해보세요</title>
		<link>https://www.gamlor.info/wordpress/2017/10/cdn-edgemesh-com-kr/</link>
		
		<dc:creator><![CDATA[gamlerhart]]></dc:creator>
		<pubDate>Sat, 07 Oct 2017 13:37:05 +0000</pubDate>
				<category><![CDATA[Technical Wibbly Wobbly]]></category>
		<category><![CDATA[한국어 배우기]]></category>
		<category><![CDATA[cdn]]></category>
		<category><![CDATA[edgemesh]]></category>
		<guid isPermaLink="false">https://www.gamlor.info/wordpress/?p=3604</guid>

					<description><![CDATA[<p>콘텐츠 전송 네트워크 (CDN) 필요할까요? 아마 edgemesh.com 사용해보세요. 기본 구독이 무료예요! 시작 먼저 edgemesh.com에 회원가입해야 되고 당신의 웹사이트 이 JavaScript를 추가해요: 완전했어요. 진짜요! 그럼, edgemesh 어떻게 작동해요? 보통 CDN는 세상&#8230;</p>
<p>The post <a href="https://www.gamlor.info/wordpress/2017/10/cdn-edgemesh-com-kr/">CDN 필요하면 edgemesh.com 사용해보세요</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>콘텐츠 전송 네트워크 (CDN) 필요할까요? 아마 edgemesh.com 사용해보세요. 기본 구독이 무료예요!</p>
<h2>시작</h2>
<p>먼저 <a href="https://edgemesh.com/">edgemesh.com</a>에 회원가입해야 되고 당신의 웹사이트 이 JavaScript를 추가해요:</p>
<p><script src="https://gist.github.com/d71405db7a446220a11590dac0246a3b.js?file=edge-mesh.html"></script><noscript><pre><code class="language-html html">&lt;script
    type=&quot;application/javascript&quot;
    src=&quot;https://sig.edgeno.de/edgemesh.client.min.js&quot;
    onload=&quot;window.edgemesh = new Edgemesh()&quot;&gt;
&lt;/script&gt;</code></pre></noscript></p>
<p>완전했어요. 진짜요!</p>
<h2>그럼, edgemesh 어떻게 작동해요?</h2>
<p>보통 CDN는 세상 각국에 많은 서버를 가지고 있어요. 이 서버는 당신의 웹 사진과 CSS과 Javascript 캐싱해요. 그래서 고객들이 가까운 CDN 서버에서 콘텐츠를 발리 다운 받아요. 근데 고객의 나라에 CDN 서버 없으면 CDN 가속 하지 않아요. 그리고 이 서버들이 무료 아니에요.<br />
<div id="attachment_3614" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-kr-final.jpg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3614" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-kr-final-1024x696.jpg" alt="" width="700" height="476" class="size-large wp-image-3614" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-kr-final-1024x696.jpg 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-kr-final-300x204.jpg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-kr-final-768x522.jpg 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/classic-cdn-kr-final.jpg 1177w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3614" class="wp-caption-text">보통 CDN</p></div></p>
<p>Edgemesh는 작동 달라요. 요즘에 우리 핸드폰과 컴퓨터는 진짜 빨라요. 그리고 우리 웹 브라우저도 강력해요. 브라우저가 Indexed DB로 데이터베이스이고 WebRTC로 P2P 네트워크 할 수 있어요. 그래서 Edgemesh 이곳을  사용해요! 고객이 웹 사이트를 보면 Edgemesh가 브라우저에 콘텐츠를 저장해요. 그리고 다른 가까운 고객 도 같은 콘텐츠를 필요하면 고객의 브라우저한테서 다운 받을 거예요.<br />
그래서 많은 고객 있으면 콘텐츠 빨리 다운 받을 수 있어요.<br />
<div id="attachment_3616" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-kr-final.jpg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3616" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-kr-final-1024x613.jpg" alt="" width="700" height="419" class="size-large wp-image-3616" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-kr-final-1024x613.jpg 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-kr-final-300x180.jpg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-kr-final-768x460.jpg 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/edge-mesh-kr-final.jpg 1336w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3616" class="wp-caption-text">Edgemesh</p></div> </p>
<p>근데 우리는 고객의 인터넷 연결을 잘 안 믿어요! 아마 진짜 느리고 아마 갑자기 연결 꺼요! 그래서 Edgemesh 프리 페치 (prefetch) 하고 연결 느리면 그냥 보통 다운 받을 거예요. 그리고 아직 CDN 서버 사용할 수 있어요. Edgemesh의 &#8216;Supernode&#8217;는 조금 보통 CDN 서버 같아요. 그리고 Edgemesh는 다른 CDN 결합할 수 있어요.</p>
<h2>진짜 작동해요?</h2>
<p>예! 이 블로그는 방문객이 별로 없어요. 근데 edgemesh로 아직 콘텐츠를 세상 각국에 저장하고 배달해요:<br />
<div id="attachment_3618" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3618" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh-1024x576.png" alt="" width="700" height="394" class="size-large wp-image-3618" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh-1024x576.png 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh-300x169.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh-768x432.png 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/10/gamlor-on-edgemesh.png 1920w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3618" class="wp-caption-text">이 블로그의 Edgemesh P2P 네트워크</p></div></p>
<p>그냥 당신의 웹 사이트에 사용해보세요 =)</p><p>The post <a href="https://www.gamlor.info/wordpress/2017/10/cdn-edgemesh-com-kr/">CDN 필요하면 edgemesh.com 사용해보세요</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Adding Timestamp to Logs</title>
		<link>https://www.gamlor.info/wordpress/2017/09/adding-timestamp-to-logs/</link>
		
		<dc:creator><![CDATA[gamlerhart]]></dc:creator>
		<pubDate>Wed, 27 Sep 2017 09:24:46 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Technical Wibbly Wobbly]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[unix]]></category>
		<guid isPermaLink="false">https://www.gamlor.info/wordpress/?p=3592</guid>

					<description><![CDATA[<p>How many small script or process do you have which just log to stdout/stderr? A few, dozens? Their running as cronjobs or service? Stashing the logs somewhere, like: ./produces-some-log.sh 2>&#038;1&#8230;</p>
<p>The post <a href="https://www.gamlor.info/wordpress/2017/09/adding-timestamp-to-logs/">Adding Timestamp to Logs</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>How many small script or process do you have which just log to stdout/stderr? A few, dozens?<br />
Their running as cronjobs or  service?<br />
Stashing the logs somewhere, like:</p>
<pre>
./produces-some-log.sh 2>&1 > log-of-my-script.log
</pre>
<p>Do you have time stamps on those logs?<br />
If not, it is trivial to add. You just have to pipe the log through a time stamp tool.</p>
<p><div id="attachment_3600" style="width: 823px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/09/time-stamp.jpg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3600" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/09/time-stamp.jpg" alt="" width="813" height="353" class="size-full wp-image-3600" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/09/time-stamp.jpg 813w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/09/time-stamp-300x130.jpg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/09/time-stamp-768x333.jpg 768w" sizes="(max-width: 813px) 100vw, 813px" /></a><p id="caption-attachment-3600" class="wp-caption-text">Timestamp your lines</p></div></p>
<h2>Linux: ts</h2>
<p>On most Linux distros there the `ts` tool. If it is not installed, it is usually in the &#8216;moreutils&#8217; package. So get it via `apt-get`, `yum`, `pacman` or whatever you`re distro uses.</p>
<p>Then, pipe the output through `ts`:</p>
<pre>
[gamlor@gamlor-manjaro log-util]$ ./produces-some-log.sh 2>&1                                          
We are making progress. We are at step 1/5         
And some other info about the system:  13:39:24 up 2:10, 2 users, load average: 1.44, 1.74, 1.76       
We are making progress. We are at step 2/5         
And some other info about the system:  13:39:25 up 2:10, 2 users, load average: 1.44, 1.74, 1.76       
We are making progress. We are at step 3/5         
....
</pre>
<p>Will become:</p>
<pre>
[gamlor@gamlor-manjaro log-util]$ ./produces-some-log.sh 2>&1 | ts                                     
Sep 25 13:39:30 We are making progress. We are at step 1/5                                             
Sep 25 13:39:30 And some other info about the system:  13:39:30 up 2:10, 2 users, load average: 1.65, 1.78, 1.77                                                                                               
Sep 25 13:39:31 We are making progress. We are at step 2/5                                             
Sep 25 13:39:31 And some other info about the system:  13:39:31 up 2:10, 2 users, load average: 1.65, 1.78, 1.77                                                                                               
Sep 25 13:39:31 We are making progress. We are at step 3/5                                             
...          
</pre>
<p>You can specify a date format string to have more clear format:</p>
<pre>
[gamlor@gamlor-manjaro log-util]$ ./produces-some-log.sh 2>&1 | ts '%Y-%m-%dT%T%z'
2017-09-25T22:47:25+0900 We are making progress. We are at step 1/5
2017-09-25T22:47:25+0900 And some other info about the system:  22:47:25 up 2:18, 2 users, load average: 1.25, 1.29, 1.53
2017-09-25T22:47:26+0900 We are making progress. We are at step 2/5
2017-09-25T22:47:26+0900 And some other info about the system:  22:47:26 up 2:18, 2 users, load average: 1.25, 1.29, 1.53
...
</pre>
<p>Last, I recommend using the UTC time zone, to avoid confusion. Expecially when your servers are all over the world. Or you need to cross reference time stamps with other logs.<br />
If your server isn`t set to UTC, you can set the `TZ` enviroment variable:</p>
<pre>
[gamlor@gamlor-manjaro log-util]$ export TZ=UTC
[gamlor@gamlor-manjaro log-util]$ ./produces-some-log.sh 2>&1 | ts '%Y-%m-%dT%T%z'
2017-09-25T13:49:54+0000 We are making progress. We are at step 1/5
2017-09-25T13:49:54+0000 And some other info about the system:  13:49:54 up 2:21, 2 users, load average: 0.66, 1.13, 1.44
2017-09-25T13:49:55+0000 We are making progress. We are at step 2/5
...
</pre>
<p>For more details, check the <a href="https://linux.die.net/man/1/ts">man pages</a>.</p>
<h2>For all Unix-like systems, AWK to the rescue!</h2>
<p>BSD, illumos or some other Unix like system? Maybe there no `ts` util around? Good old awk has got you covered. On each line, print the date, then the rest of the line.</p>
<p>This method is more portable. AWK is installed most systems. So, if you plan do distribute your script, this is the way to go.</p>
<pre>
[gamlor@gamlor-manjaro log-util]$ ./produces-some-log.sh 2>&1 | awk '{ print strftime("%Y-%m-%dT%T%z"), $0;  }'                                                                                                     
2017-09-25T22:57:54+0900 We are making progress. We are at step 1/5                                    
2017-09-25T22:57:54+0900 And some other info about the system:  22:57:54 up 2:29, 2 users, load average: 1.29, 1.23, 1.39                                                                                      
2017-09-25T22:57:55+0900 We are making progress. We are at step 2/5                                    
...
</pre>
<p>Again, I recommend using UTC. Your server probably already uses UTC anyway:</p>
<pre>
[gamlor@gamlor-manjaro log-util]$ export TZ=UTC    
[gamlor@gamlor-manjaro log-util]$ ./produces-some-log.sh 2>&1 | awk '{ print strftime("%Y-%m-%dT%T%z"), $0;  }'                                                                                                     
2017-09-25T13:59:23+0000 We are making progress. We are at step 1/5                                    
2017-09-25T13:59:23+0000 And some other info about the system:  13:59:23 up 2:30, 2 users, load average: 1.09, 1.15, 1.35                                                                                      
2017-09-25T13:59:24+0000 We are making progress. We are at step 2/5                                    
...                                  
</pre>
<p>That`s it =).<br />
Thanks for the Stackoverflow <a href="https://stackoverflow.com/questions/21564/is-there-a-unix-utility-to-prepend-timestamps-to-stdin">answers</a>, which include both solutions.</p><p>The post <a href="https://www.gamlor.info/wordpress/2017/09/adding-timestamp-to-logs/">Adding Timestamp to Logs</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Java&#8217;s Enum.values() Hidden Allocations</title>
		<link>https://www.gamlor.info/wordpress/2017/08/javas-enum-values-hidden-allocations/</link>
		
		<dc:creator><![CDATA[gamlerhart]]></dc:creator>
		<pubDate>Thu, 31 Aug 2017 13:47:29 +0000</pubDate>
				<category><![CDATA[42]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Technical Wibbly Wobbly]]></category>
		<category><![CDATA[gc]]></category>
		<category><![CDATA[performance]]></category>
		<guid isPermaLink="false">https://www.gamlor.info/wordpress/?p=3562</guid>

					<description><![CDATA[<p>I recently profiled an app of mine. During profiling, I&#8217;ve noticed tons of array allocations. Something like: Well easy, a quick grep for TypeInfo[] array. Nothing. Ah, quick grep for&#8230;</p>
<p>The post <a href="https://www.gamlor.info/wordpress/2017/08/javas-enum-values-hidden-allocations/">Java’s Enum.values() Hidden Allocations</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>I recently profiled an app of mine. During profiling, I&#8217;ve noticed tons of array allocations. Something like:</p>
<p><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocation-madness.png"><img loading="lazy" decoding="async" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocation-madness-1024x332.png" alt="" width="700" height="227" class="aligncenter size-large wp-image-3570" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocation-madness-1024x332.png 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocation-madness-300x97.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocation-madness-768x249.png 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocation-madness.png 1311w" sizes="(max-width: 700px) 100vw, 700px" /></a></p>
<p>Well easy, a quick grep for TypeInfo[] array. Nothing. Ah, quick grep for TypeInfo collections. Nothing! Huh? Where the hell do I allocate the array then?<br />
Ok, more profiling! So, I enabled flight recorder with &#8216;-XX:+UnlockCommercialFeatures -XX:+FlightRecorder&#8217;. Then did a recording with <a href="http://www.oracle.com/technetwork/java/javaseproducts/mission-control/index.html">Java Mission Control</a>, capturing the allocation stack traces:</p>
<p><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocated-by-enum-values.png"><img loading="lazy" decoding="async" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocated-by-enum-values-1024x507.png" alt="" width="700" height="347" class="aligncenter size-large wp-image-3572" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocated-by-enum-values-1024x507.png 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocated-by-enum-values-300x149.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocated-by-enum-values-768x380.png 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/allocated-by-enum-values.png 1456w" sizes="(max-width: 700px) 100vw, 700px" /></a></p>
<p>Ok, the TypeInfo.values() method allocates the memory. TypeInfo is a enum, and I&#8217;m using the built in values() method. The code looked something like this:</p>
<p><script src="https://gist.github.com/d3f5a7f143dbc894b4f43c4fcbaae79f.js?file=Enum-Allocation-Example.java"></script><noscript><pre><code class="language-java java">package info.gamlor.blog;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

enum TypeInfo {
    UNKNOWN(0),
    INT(1),
    STRING(2);

    private final int id;

    TypeInfo(int id) {
        this.id = id;
    }

    public static TypeInfo findType(int type){
        for (TypeInfo t : values()){
            if(t.id == type){
                return t;
            }
        }
        return UNKNOWN;
    }
}

public class Main {
    private static Random rnd = new Random();

    public static void main(String[] args) throws Exception {
        List&lt;TypeInfo&gt; parsedData = new ArrayList&lt;&gt;();
        for (int i = 0; i &lt; 1000000000; i++) {
            int idParsedFromWire = readTypeIdFromData(rnd);

            TypeInfo type = TypeInfo.findType(idParsedFromWire);

            // Pretend we use the type for the exampe
            parsedData.add(type);
            consumeData(parsedData);
        }
        System.out.println(parsedData.size());
    }

    private static void consumeData(List&lt;TypeInfo&gt; parsedData) {
        // Parsed data is consumed
        if(rnd.nextBoolean()){
            parsedData.clear();
        }
    }

    private static int readTypeIdFromData(Random rnd) throws InterruptedException {
        // Data comes from the wire....let&#039;s run this example a bit slower
        int idParsedFromWire = rnd.nextInt(16);
        Thread.yield();
        return idParsedFromWire;
    }
}
</code></pre></noscript></p>
<p>Do you see the allocation? Why should it allocate that many arrays? The Enum values are constant, so it should be able to initialize an array once?<br />
Ok, let&#8217;s take a closer look and decompile the class file:</p>
<pre>
javap -c TypeInfo.class | grep -A 10 values
</pre>
<p>And we get:</p>
<pre>
  public static info.gamlor.blog.TypeInfo[] values();
    Code:
       0: getstatic     #1                  // Field $VALUES:[Linfo/gamlor/blog/TypeInfo;
       3: invokevirtual #2                  // Method "[Linfo/gamlor/blog/TypeInfo;".clone:()Ljava/lang/Object;
       6: checkcast     #3                  // class "[Linfo/gamlor/blog/TypeInfo;"
       9: areturn
</pre>
<p>As we can see, it deferences a static array of the Enum values. Then it clones that array before returning it, causing an array allocation. Why does it do that? It is a defensive copy:<br />
Java&#8217;s arrays are a mutable. If values() just returns the reference to the original array, then some code might change the array&#8217;s content. That creates havoc, since it would change what Enum.values() returns. Therefore, the defensive copy.</p>
<p><div id="attachment_3573" style="width: 958px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/enum-copies.jpg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3573" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/enum-copies.jpg" alt="" width="948" height="500" class="size-full wp-image-3573" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/enum-copies.jpg 948w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/enum-copies-300x158.jpg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/enum-copies-768x405.jpg 768w" sizes="(max-width: 948px) 100vw, 948px" /></a><p id="caption-attachment-3573" class="wp-caption-text">Safety First, Copy It</p></div></p>
<p>So, after seeing this, it is easy to fix our code. We call Enum.values() once, cache the array and use it for the parsing:</p>
<p><script src="https://gist.github.com/d3f5a7f143dbc894b4f43c4fcbaae79f.js?file=Fix.java"></script><noscript><pre><code class="language-java java">// Enum.values() does a defensive copy and allocates an array on each call
// To avoid that allocation, we call values() only once
private static final TypeInfo[] ALL_VALUES = values();

public static TypeInfo findType(int type){
    for (TypeInfo t : ALL_VALUES){
        if(t.id == type){
            return t;
        }
    }
    return UNKNOWN;
}</code></pre></noscript></p>
<p>Et voila, the allocations are gone =)</p>
<p><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/fixed.png"><img loading="lazy" decoding="async" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/fixed-1024x213.png" alt="" width="700" height="146" class="aligncenter size-large wp-image-3574" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/fixed-1024x213.png 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/fixed-300x63.png 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/fixed-768x160.png 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/08/fixed.png 1300w" sizes="(max-width: 700px) 100vw, 700px" /></a></p><p>The post <a href="https://www.gamlor.info/wordpress/2017/08/javas-enum-values-hidden-allocations/">Java’s Enum.values() Hidden Allocations</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Deploying JVM in tiny containers, be carefull!</title>
		<link>https://www.gamlor.info/wordpress/2017/04/deploying-jvm-in-tiny-containers-be-carefull/</link>
		
		<dc:creator><![CDATA[gamlerhart]]></dc:creator>
		<pubDate>Tue, 25 Apr 2017 14:59:39 +0000</pubDate>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Technical Wibbly Wobbly]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[joyent]]></category>
		<category><![CDATA[JVM]]></category>
		<category><![CDATA[triton]]></category>
		<guid isPermaLink="false">https://www.gamlor.info/wordpress/?p=3509</guid>

					<description><![CDATA[<p>I`ve deployed my rohrli.gamlor.info service into the smallest possible triton container. Except me, noone is going to use it anyway ^-^. This container has 128Mbyte of memory, and 1/16th CPU&#8230;</p>
<p>The post <a href="https://www.gamlor.info/wordpress/2017/04/deploying-jvm-in-tiny-containers-be-carefull/">Deploying JVM in tiny containers, be carefull!</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>I`ve deployed my <a href="https://rohrli.gamlor.info">rohrli.gamlor.info</a> service into the smallest possible triton container. Except me, noone is going to use it anyway ^-^. This container has 128Mbyte of memory, and 1/16th CPU time. The OpenJDK JVM is known for consuming tons of memory. And it is somewhat true. However, the JVM also runs in a small container. In this blog post I give some recommendations. The problems exists in small Docker and Triton containers. I show everything for both.<br />
<div id="attachment_3551" style="width: 810px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-usage-en-1.jpeg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3551" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-usage-en-1.jpeg" alt="Chrome &amp; JVM eat memory generously" width="800" height="567" class="size-full wp-image-3551" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-usage-en-1.jpeg 800w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-usage-en-1-300x213.jpeg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-usage-en-1-768x544.jpeg 768w" sizes="(max-width: 800px) 100vw, 800px" /></a><p id="caption-attachment-3551" class="wp-caption-text">Chrome &#038; JVM eat memory generously</p></div></p>
<h2>Web App Example</h2>
<p>The web app is just a &#8216;Hello World&#8217; app. For better explaination, it also consumes tons of memory. I created the example in Scala, but the other JVM languages have the same issue. The source code for the example is <a href="https://github.com/gamlerhart/blog-post-examples/tree/master/jvm-in-small-containers">here</a>.<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=Hello-Basics.scala"></script><noscript><pre><code class="language-scala scala">/** 
 * Snippet, memory limits 
 */
// Limit the amount of items in memory for this example.
// So, max ~192*256k=48MBytes
val maxMemoryItems = 192
val memoryPerItem = 256 * 1024
val memoryWasting = new ArrayBlockingQueue[Array[Byte]](maxMemoryItems)

/** 
 * Snippet, request handling
 */
// On each request, consume some memory.
// And keep things in memory to simulate memory use
case &quot;/&quot; :: Nil =&gt; {
    // On each request, consume some memory.
    // And keep things in memory to simulate memory use
    val chunkOfMemory = Array.ofDim[Byte](memoryPerItem)
    var addedToQueue = memoryWasting.offer(chunkOfMemory)

    // Throw things away until we&#039;ve space
    while (!addedToQueue) {
        memoryWasting.poll()
        addedToQueue = memoryWasting.offer(chunkOfMemory)
    }

    val createdSoFar = createdItemsCounter.incrementAndGet()
    response.getWriter.write(
        s&quot;&quot;&quot;
            |{
            |&quot;title&quot;:&quot;Hello World! Let&#039;s use some memory&quot;,
            |&quot;created-overall&quot;:&quot;$createdSoFar&quot;,
            |&quot;queue-size&quot;:&quot;${memoryWasting.size()}&quot;,
            |&quot;&quot;:&quot;Hello. I&#039;m so memory hungry. kthxbye!&quot;
            |}
        &quot;&quot;&quot;.stripMargin)
}</code></pre></noscript><br />
We compile and package the program into a Docker container. The Docker file is simple:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=version1.Dockerfile"></script><noscript><pre><code class="language-dockerfile dockerfile">FROM openjdk:8u121-jdk-alpine

# Assume already compiled for now
COPY target/scala-2.12/useless-demo-service.jar /app/useless-demo-service.jar

EXPOSE 8080
CMD java -jar /app/useless-demo-service.jar
</code></pre></noscript><br />
The we create the image with `build` and run it with `run`. With regular Docker we restrict the memory with the &#8216;-m 128m&#8217; option to 128Mbyte. And with &#8216;&#8211;cpus 0.065&#8217; we only give very little CPU time.<br />
When using Triton, the &#8216;-m 128m&#8217; option will find a <a href="https://apidocs.joyent.com/docker/features/resources">sufficient large</a> compute instance. Alternativly, you also can use &#8216;&#8211;label com.joyent.package=g4-highcpu-128M&#8217; to create a tiny instance.<br />
Once we started out container, we create some load with the &#8216;watch&#8217; and &#8216;curl&#8217; commands. Then, let`s watch the logs.<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=first-run.sh"></script><noscript><pre><code class="language-shell shell">##
# Local docker run 
##
sudo docker run -d -m 128m --cpus 0.065 --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:1
# Start to follow the logs
sudo docker logs -f jvm-on-small-container
# Then, start the simple load, in another termial
watch -n 0.01 curl http://localhost:8080/

##
# Joyent Triton run
##
eval &quot;$(triton env)&quot;
docker run -d -m 128m --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:1
# Get the IP
docker inspect --format &#039;{{ .NetworkSettings.IPAddress }}&#039; jvm-on-small-container
# Start to follow the logs
docker logs -f jvm-on-small-container
# Then, start the simple load, in another termial
watch -n 0.01 curl http://{ip-from-above}:8080/
</code></pre></noscript></p>
<h2>First Issue: Program Dies</h2>
<p>The Triton instance won`t expirience any issue. But the plain Docker instance (Linux 4.10, Docker 17.04) suddenly stops working. =( The program got killed.<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=unexpected-process-death.txt"></script><noscript><pre><code class="language-text text">[root@gamlor-manjaro useless-demo-service]# docker run -m 128m --cpus 0.065 -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:1
2017-04-20 12:58:20.248:INFO::main: Logging initialized @5900ms to org.eclipse.jetty.util.log.StdErrLog
2017-04-20 12:58:23.348:INFO:oejs.Server:main: jetty-9.4.z-SNAPSHOT
2017-04-20 12:58:30.650:INFO:oejs.AbstractConnector:main: Started ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2017-04-20 12:58:30.748:INFO:oejs.Server:main: Started @16602ms
Killed
</code></pre></noscript><br />
Hmmm&#8230;.Why did it got killed? Aha&#8230;the memory is small, so we might ran out of memory and got killed. We can, while the container runs, inspect the memory usage of the JVM with `jstat`:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=inspect-memory.sh"></script><noscript><pre><code class="language-shell shell">##
# Local docker run 
##
# Get memory usage of the running java process
sudo docker exec jvm-on-small-container sh -c &#039;jstat -gccapacity `pgrep java`&#039;
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC 
84480.0 1354240.0 84480.0 10240.0 10240.0 64000.0 169472.0 2708992.0 169472.0 169472.0 0.0 1056768.0 4480.0 0.0 1048576.0 384.0 1 0


##
# Joyent Triton run
##
# Get memory usage of the running java process
eval &quot;$(triton env)&quot;
docker exec jvm-on-small-container sh -c &#039;jstat -gccapacity `pgrep java`&#039;
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC 
  2688.0  21824.0  21824.0 2176.0 2176.0  17472.0     5504.0    43712.0    43712.0    43712.0      0.0 1060864.0  12544.0      0.0 1048576.0   1536.0     15    69
</code></pre></noscript><br />
<div id="attachment_3547" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-en.jpeg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3547" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-en-1024x478.jpeg" alt="The penguin and whale are dangerous. Be careful!" width="700" height="327" class="size-large wp-image-3547" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-en-1024x478.jpeg 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-en-300x140.jpeg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-en-768x358.jpeg 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-en.jpeg 1400w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3547" class="wp-caption-text">The penguin and whale are dangerous. Be careful!</p></div><br />
<a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html">jstat</a> is a bit confusing. All numbers are in KByte. The JVM has a few memory pools and each memory pool has a minimum (**MN), maximum (**MX) and current size (**C).<br />
So, inside the regular Docker container it create really big memory pools. On my computer (16GB, Linux 4.10, Docker 17.04), OGCMX (old generation heap) memory is about 2.5GByte. However, on the Triton instance it is about 40Mybte large. So, with a 2.5GByte pool, if it actually uses more than 128MByte, it will die. For now, Docker just kills processes which use too much memory. However, the JVM sees all the hosts memory, so it creates giant memory pools.<br />
However, the Triton container lies more convincingly, so the JVM sees the containers memory sizes and creates a sufficient small memory pool.<br />
Well, there a solution to this issue. We just configure a small memory size with the `-Xmx` option. Plus I configure the JVM such that when it runs out of memory, it dumps the memory and dies.<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=version2.Dockerfile"></script><noscript><pre><code class="language-dockerfile dockerfile">FROM openjdk:8u121-jdk-alpine

# Assume already compiled for now
COPY target/scala-2.12/useless-demo-service.jar /app/useless-demo-service.jar

# Defaults for a tiny container
ENV MEMORY=&quot;64m&quot;

EXPOSE 8080

CMD java -Xmx$MEMORY -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError=&quot;kill -9 %p&quot; \
    -jar /app/useless-demo-service.jar</code></pre></noscript><br />
After doing this, the JVM runs in the Docker container without any issue.</p>
<h2>So Many Threads</h2>
<p>Now, we configured the memory properly. However, there maybe more things we can configure properly? So, let`s see what threads are runing in the container with `jstack`:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=inspect-threads-1st.sh"></script><noscript><pre><code class="language-shell shell">##
# Local docker run 
##
# Run second version of our container
sudo docker run -d -m 128m --cpus 0.065 --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:2
# List the threads running
sudo docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
&quot;qtp791452441-23&quot; #23 prio=5 os_prio=0 tid=0x000056473bc03800 nid=0x42 waiting on condition [0x00007fefe4931000]
&quot;Attach Listener&quot; #22 daemon prio=9 os_prio=0 tid=0x000056473bf72800 nid=0x41 waiting on condition [0x0000000000000000]
&quot;DestroyJavaVM&quot; #21 prio=5 os_prio=0 tid=0x000056473bcd1800 nid=0x8 waiting on condition [0x0000000000000000]
&quot;qtp791452441-19-acceptor-0@27b0949f-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #19 prio=3 os_prio=0 tid=0x000056473bf75000 nid=0x24 runnable [0x00007fefe4b33000]
&quot;qtp791452441-17&quot; #17 prio=5 os_prio=0 tid=0x000056473bc2d800 nid=0x22 runnable [0x00007fefe8160000]
&quot;qtp791452441-16&quot; #16 prio=5 os_prio=0 tid=0x000056473bc2b000 nid=0x21 runnable [0x00007fefe8261000]
&quot;qtp791452441-15-lowPrioritySelector&quot; #15 prio=1 os_prio=0 tid=0x000056473bc29000 nid=0x20 waiting for monitor entry [0x00007fefe8363000]
&quot;qtp791452441-14-lowPrioritySelector&quot; #14 prio=1 os_prio=0 tid=0x000056473bc8c000 nid=0x1f waiting for monitor entry [0x00007fefe8464000]
&quot;qtp791452441-13-lowPrioritySelector&quot; #13 prio=1 os_prio=0 tid=0x000056473bc8a000 nid=0x1e waiting for monitor entry [0x00007fefe8565000]
&quot;qtp791452441-12-lowPrioritySelector&quot; #12 prio=1 os_prio=0 tid=0x000056473bc86800 nid=0x1d waiting for monitor entry [0x00007fefe8666000]
&quot;qtp791452441-11&quot; #11 prio=5 os_prio=0 tid=0x000056473bd8a800 nid=0x1c runnable [0x00007fefe8766000]
&quot;qtp791452441-10&quot; #10 prio=5 os_prio=0 tid=0x000056473bd84800 nid=0x1b runnable [0x00007fefe8867000]
&quot;Service Thread&quot; #9 daemon prio=9 os_prio=0 tid=0x000056473bc63800 nid=0x19 runnable [0x0000000000000000]
&quot;C1 CompilerThread3&quot; #8 daemon prio=9 os_prio=0 tid=0x000056473bc14000 nid=0x18 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread2&quot; #7 daemon prio=9 os_prio=0 tid=0x000056473bbf9000 nid=0x17 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x000056473bbea000 nid=0x16 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x000056473bbe7000 nid=0x15 waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x000056473bbe4800 nid=0x14 runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x000056473bbb5000 nid=0x13 in Object.wait() [0x00007fefe92cb000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x000056473bbb2000 nid=0x12 in Object.wait() [0x00007fefe93cc000]
&quot;VM Thread&quot; os_prio=0 tid=0x000056473bba8000 nid=0x11 runnable 
&quot;GC task thread#0 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f0000 nid=0x9 runnable 
&quot;GC task thread#1 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f2000 nid=0xa runnable 
&quot;GC task thread#2 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f3800 nid=0xb runnable 
&quot;GC task thread#3 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f5800 nid=0xc runnable 
&quot;GC task thread#4 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f7000 nid=0xd runnable 
&quot;GC task thread#5 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f9000 nid=0xe runnable 
&quot;GC task thread#6 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9fa800 nid=0xf runnable 
&quot;GC task thread#7 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9fc800 nid=0x10 runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x000056473bc59800 nid=0x1a waiting on condition

##
# Joyent Triton run
##
# Run second version of our container
eval &quot;$(triton env)&quot;
docker run -d -m 128m --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:2
# List the threads running
docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
&quot;qtp791452441-44&quot; #44 prio=5 os_prio=0 tid=0x000000000215e000 nid=0x12de4 runnable [0x00007fffe51f7000]
&quot;qtp791452441-43&quot; #43 prio=5 os_prio=0 tid=0x0000000000262000 nid=0x12aa4 waiting for monitor entry [0x00007fffe52fa000]
&quot;qtp791452441-42&quot; #42 prio=5 os_prio=0 tid=0x000000000068a000 nid=0x11808 waiting on condition [0x00007fffe7c7a000]
&quot;Scheduler-1896277646&quot; #41 prio=5 os_prio=0 tid=0x0000000000145000 nid=0x1176f waiting on condition [0x00007fffe4e34000]
&quot;Attach Listener&quot; #39 daemon prio=9 os_prio=0 tid=0x0000000000717800 nid=0x116e2 waiting on condition [0x0000000000000000]
&quot;DestroyJavaVM&quot; #33 prio=5 os_prio=0 tid=0x0000000000716000 nid=0x10796 waiting on condition [0x0000000000000000]
&quot;qtp791452441-32-acceptor-3@6dbc83d8-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #32 prio=3 os_prio=0 tid=0x0000000000714800 nid=0x1082a runnable [0x00007fffe5cff000]
&quot;qtp791452441-31-acceptor-2@1ac08473-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #31 prio=3 os_prio=0 tid=0x0000000000713000 nid=0x10829 waiting for monitor entry [0x00007fffe6000000]
&quot;qtp791452441-30-acceptor-1@34228b2c-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #30 prio=3 os_prio=0 tid=0x000000000070d800 nid=0x10828 waiting for monitor entry [0x00007fffe67fe000]
&quot;qtp791452441-29-acceptor-0@467e71fc-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #29 prio=3 os_prio=0 tid=0x000000000070b000 nid=0x10827 waiting for monitor entry [0x00007fffe6f72000]
&quot;qtp791452441-28-lowPrioritySelector&quot; #28 prio=1 os_prio=0 tid=0x0000000000695800 nid=0x10818 runnable [0x00007fffe72b3000]
&quot;qtp791452441-27&quot; #27 prio=5 os_prio=0 tid=0x000000000068d800 nid=0x10816 waiting on condition [0x00007fffe75f6000]
&quot;qtp791452441-26-lowPrioritySelector&quot; #26 prio=1 os_prio=0 tid=0x000000000068b800 nid=0x10815 runnable [0x00007fffe7937000]
&quot;qtp791452441-24-lowPrioritySelector&quot; #24 prio=1 os_prio=0 tid=0x0000000000687800 nid=0x10812 waiting for monitor entry [0x00007fffe7fbc000]
&quot;qtp791452441-23&quot; #23 prio=5 os_prio=0 tid=0x0000000000685800 nid=0x10810 waiting for monitor entry [0x00007fffe82fe000]
&quot;qtp791452441-22-lowPrioritySelector&quot; #22 prio=1 os_prio=0 tid=0x0000000000683800 nid=0x1080f waiting for monitor entry [0x00007fffe85ff000]
&quot;qtp791452441-21&quot; #21 prio=5 os_prio=0 tid=0x000000000067d000 nid=0x1080e runnable [0x00007fffe8b1d000]
&quot;Service Thread&quot; #20 daemon prio=9 os_prio=0 tid=0x00000000001ee800 nid=0x107c5 runnable [0x0000000000000000]
&quot;C1 CompilerThread14&quot; #19 daemon prio=9 os_prio=0 tid=0x00000000001e1800 nid=0x107c3 waiting on condition [0x0000000000000000]
&quot;C1 CompilerThread13&quot; #18 daemon prio=9 os_prio=0 tid=0x00000000001d7000 nid=0x107c1 waiting on condition [0x0000000000000000]
&quot;C1 CompilerThread12&quot; #17 daemon prio=9 os_prio=0 tid=0x00000000001d4000 nid=0x107bf waiting on condition [0x0000000000000000]
&quot;C1 CompilerThread11&quot; #16 daemon prio=9 os_prio=0 tid=0x00000000001b7800 nid=0x107bd waiting on condition [0x0000000000000000]
&quot;C1 CompilerThread10&quot; #15 daemon prio=9 os_prio=0 tid=0x00000000001ad800 nid=0x107bc waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread9&quot; #14 daemon prio=9 os_prio=0 tid=0x00000000001a2000 nid=0x107bb waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread8&quot; #13 daemon prio=9 os_prio=0 tid=0x0000000000197800 nid=0x107b9 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread7&quot; #12 daemon prio=9 os_prio=0 tid=0x0000000000172000 nid=0x107b8 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread6&quot; #11 daemon prio=9 os_prio=0 tid=0x0000000000186800 nid=0x107b7 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread5&quot; #10 daemon prio=9 os_prio=0 tid=0x000000000017c000 nid=0x107b6 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread4&quot; #9 daemon prio=9 os_prio=0 tid=0x0000000000165800 nid=0x107b5 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread3&quot; #8 daemon prio=9 os_prio=0 tid=0x000000000010f000 nid=0x107b3 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread2&quot; #7 daemon prio=9 os_prio=0 tid=0x0000000000104800 nid=0x107b2 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x00000000000f5000 nid=0x107b1 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x00000000000f2800 nid=0x107b0 waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x00000000000f0800 nid=0x107af runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x00000000000c1000 nid=0x107a3 in Object.wait() [0x00007ffffd5fe000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x00000000000be000 nid=0x107a1 in Object.wait() [0x00007ffffe9fe000]
&quot;VM Thread&quot; os_prio=0 tid=0x00000000000b4000 nid=0x1079d runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x00000000001f3800 nid=0x107c6 waiting on condition 
</code></pre></noscript><br />
<div id="attachment_3549" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-en.jpeg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3549" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-en-1024x707.jpeg" alt="Triton isn`t a fun guy!" width="700" height="483" class="size-large wp-image-3549" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-en-1024x707.jpeg 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-en-300x207.jpeg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-en-768x530.jpeg 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-en.jpeg 1400w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3549" class="wp-caption-text">Triton isn`t a fun guy!</p></div><br />
Howly! More than 30 threads are running. On my computer the regular Docker container has 8 `GC task thread`s, and 4 `CompilerThread`s. On Triton there are 15! The JVM saw a lot of CPU cores and created many threads to take advantage of it. However, our container is restricted to 0.065 cores. Those many threads won`t help. Of course, we can configure this:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=version3.Dockerfile"></script><noscript><pre><code class="language-dockerfile dockerfile">FROM openjdk:8u121-jdk-alpine

# Assume already compiled for now
COPY target/scala-2.12/useless-demo-service.jar /app/useless-demo-service.jar

# Defaults for a tiny container
ENV MEMORY=&quot;64m&quot; \
    CPUS=1

EXPOSE 8080

CMD java -Xmx$MEMORY -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError=&quot;kill -9 %p&quot; \
    -XX:CICompilerCount=&quot;$(($CPUS&gt;2?$CPUS:2))&quot; -XX:+UseSerialGC \
    -jar /app/useless-demo-service.jar</code></pre></noscript><br />
In this really small container the `ParallelGC` is not really needed and we can use the `SerialGC`. In case you use a bit larger container, you can use `-XX:-XX:+ParallelGCThreads=$CPU` for `ParallelGC`. Or `-XX:G1ConcRefinementThreads=$CPU` in case you use `-XX:+UseG1GC`.<br />
And we can use `-XX:CICompilerCount=$CPU` to reduce the compiler threads. However, it needs to be at least 2. </p>
<h2>Still Many Threads</h2>
<p>We still have many &#8216;acceptor&#8217; and &#8216;selector&#8217; threads. On Triton we&#8217;ve 4 acceptor and 4 selector threads:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=inspect-threads-2nd.sh"></script><noscript><pre><code class="language-shell shell">##
# Local docker run 
##
# Run third version of our container
sudo docker run -d -m 128m --cpus 0.065 --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:3
# List the threads running
sudo docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
&quot;Attach Listener&quot; #20 daemon prio=9 os_prio=0 tid=0x0000564e7cd17000 nid=0x37 waiting on condition [0x0000000000000000]
&quot;qtp791452441-19&quot; #19 prio=5 os_prio=0 tid=0x0000564e7cd15000 nid=0x36 waiting on condition [0x00007fdcc863f000]
&quot;qtp791452441-17-acceptor-0@77fe3be4-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #17 prio=3 os_prio=0 tid=0x0000564e7cc25000 nid=0x34 runnable [0x00007fdcc8841000]
&quot;DestroyJavaVM&quot; #16 prio=5 os_prio=0 tid=0x0000564e7c922800 nid=0x8 waiting on condition [0x0000000000000000]
&quot;qtp791452441-15-lowPrioritySelector&quot; #15 prio=1 os_prio=0 tid=0x0000564e7ce14000 nid=0x31 waiting for monitor entry [0x00007fdccbd6e000]
&quot;qtp791452441-14&quot; #14 prio=5 os_prio=0 tid=0x0000564e7ce12000 nid=0x30 runnable [0x00007fdccbe6e000]
&quot;qtp791452441-13-lowPrioritySelector&quot; #13 prio=1 os_prio=0 tid=0x0000564e7ce0f800 nid=0x2f waiting for monitor entry [0x00007fdccbf70000]
&quot;qtp791452441-12&quot; #12 prio=5 os_prio=0 tid=0x0000564e7ce0e000 nid=0x2e runnable [0x00007fdccc070000]
&quot;qtp791452441-11-lowPrioritySelector&quot; #11 prio=1 os_prio=0 tid=0x0000564e7ce0c000 nid=0x2d waiting for monitor entry [0x00007fdccc172000]
&quot;qtp791452441-10-lowPrioritySelector&quot; #10 prio=1 os_prio=0 tid=0x0000564e7ce0a000 nid=0x2b waiting for monitor entry [0x00007fdccc273000]
&quot;qtp791452441-9&quot; #9 prio=5 os_prio=0 tid=0x0000564e7ce07800 nid=0x2a runnable [0x00007fdccc373000]
&quot;qtp791452441-8&quot; #8 prio=5 os_prio=0 tid=0x0000564e7ce01000 nid=0x29 runnable [0x00007fdccc474000]
&quot;Service Thread&quot; #7 daemon prio=9 os_prio=0 tid=0x0000564e7c8c2800 nid=0xf runnable [0x0000000000000000]
&quot;C1 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x0000564e7c8b7800 nid=0xe waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x0000564e7c8ac800 nid=0xd waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x0000564e7c8aa800 nid=0xc runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x0000564e7c87d800 nid=0xb in Object.wait() [0x00007fdccccd4000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x0000564e7c873000 nid=0xa in Object.wait() [0x00007fdcccdd5000]
&quot;VM Thread&quot; os_prio=0 tid=0x0000564e7c869000 nid=0x9 runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x0000564e7c8c5800 nid=0x10 waiting on condition 


##
# Joyent Triton run
##
# Run third version of our container
eval &quot;$(triton env)&quot;
docker run -d -m 128m --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:3
# List the threads running
docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
&quot;Attach Listener&quot; #23 daemon prio=9 os_prio=0 tid=0x000000000028c000 nid=0x732a waiting on condition [0x0000000000000000]
&quot;qtp791452441-22&quot; #22 prio=5 os_prio=0 tid=0x00000000006eb000 nid=0x7178 waiting on condition [0x00007fffe81fe000]
&quot;qtp791452441-21-acceptor-3@161ab1a8-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #21 prio=3 os_prio=0 tid=0x00000000006ea000 nid=0x7177 waiting for monitor entry [0x00007fffe84ff000]
&quot;DestroyJavaVM&quot; #20 prio=5 os_prio=0 tid=0x00000000001df000 nid=0x7109 waiting on condition [0x0000000000000000]
&quot;qtp791452441-19-acceptor-2@70b4bcd9-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #19 prio=3 os_prio=0 tid=0x00000000006e7000 nid=0x7175 waiting for monitor entry [0x00007fffe8800000]
&quot;qtp791452441-18-acceptor-1@57033676-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #18 prio=3 os_prio=0 tid=0x0000000000747800 nid=0x7174 waiting for monitor entry [0x00007fffe97f6000]
&quot;qtp791452441-17-acceptor-0@67e0dd84-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #17 prio=3 os_prio=0 tid=0x00000000006e4800 nid=0x7173 runnable [0x00007fffe8ffe000]
&quot;qtp791452441-15-lowPrioritySelector&quot; #15 prio=1 os_prio=0 tid=0x000000000066b000 nid=0x7159 waiting for monitor entry [0x00007fffe9af7000]
&quot;qtp791452441-14&quot; #14 prio=5 os_prio=0 tid=0x000000000066c800 nid=0x7157 runnable [0x00007fffe9df7000]
&quot;qtp791452441-13-lowPrioritySelector&quot; #13 prio=1 os_prio=0 tid=0x0000000000668800 nid=0x7156 waiting for monitor entry [0x00007fffea0f9000]
&quot;qtp791452441-12&quot; #12 prio=5 os_prio=0 tid=0x0000000000666800 nid=0x7155 runnable [0x00007fffea3f9000]
&quot;qtp791452441-11&quot; #11 prio=5 os_prio=0 tid=0x0000000000664800 nid=0x7154 runnable [0x00007fffea6fa000]
&quot;qtp791452441-10-lowPrioritySelector&quot; #10 prio=1 os_prio=0 tid=0x0000000000662800 nid=0x7153 waiting for monitor entry [0x00007fffea9fc000]
&quot;qtp791452441-9&quot; #9 prio=5 os_prio=0 tid=0x0000000000660800 nid=0x7152 runnable [0x00007fffeacfc000]
&quot;qtp791452441-8-lowPrioritySelector&quot; #8 prio=1 os_prio=0 tid=0x0000000000659800 nid=0x7151 waiting for monitor entry [0x00007fffeaffe000]
&quot;Service Thread&quot; #7 daemon prio=9 os_prio=0 tid=0x0000000000130800 nid=0x7120 runnable [0x0000000000000000]
&quot;C1 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x0000000000104000 nid=0x711e waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x00000000000f2800 nid=0x711d waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x00000000000f0800 nid=0x711c runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x00000000000c1000 nid=0x7115 in Object.wait() [0x00007ffffd5fe000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x00000000000be000 nid=0x7113 in Object.wait() [0x00007ffffe9fe000]
&quot;VM Thread&quot; os_prio=0 tid=0x00000000000b4000 nid=0x710f runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x0000000000128800 nid=0x7121 waiting on condition 

</code></pre></noscript><br />
Those threads are created by the web server, so you have to configure the web server you are using. In this example Jetty is used, and we configure it via simple Java properties:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=DemoService.scala"></script><noscript><pre><code class="language-scala scala">// Version 1 did just start Jetty
// val server = new Server(8080)
// It creates many acceptors, selectors and threads on big machines, even when running in small container
// So, let&#039;s explicitly configure it.
val minThreads = System.getProperty(&quot;jetty.min-threads&quot;, &quot;8&quot;).toInt
val maxThreads = System.getProperty(&quot;jetty.max-threads&quot;, &quot;200&quot;).toInt
var threadPool = new QueuedThreadPool(minThreads, maxThreads)

val server = new Server(threadPool)
val acceptorCount = System.getProperty(&quot;jetty.acceptor-threads&quot;, &quot;-1&quot;).toInt
val selectorCount = System.getProperty(&quot;jetty.selector-threads&quot;, &quot;-1&quot;).toInt
server.setConnectors(Array(new ServerConnector(server, acceptorCount, selectorCount)))

server.setHandler(new OurHandling)
server.start()</code></pre></noscript><br />
And also change the Docker file:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=version4.Dockerfile"></script><noscript><pre><code class="language-dockerfile dockerfile">FROM openjdk:8u121-jdk-alpine

# Assume already compiled for now
COPY target/scala-2.12/useless-demo-service.jar /app/useless-demo-service.jar

# Defaults for a tiny container
ENV MEMORY=&quot;64m&quot; \
    CPUS=1\
    ACCEPTORS=1 \
    SELECTORS=1\
    JETTY_MIN_THREADS=4 \
    JETTY_MAX_THREADS=20

EXPOSE 8080

CMD java -Xmx$MEMORY -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError=&quot;kill -9 %p&quot; \
    -XX:CICompilerCount=&quot;$(($CPUS&gt;2?$CPUS:2))&quot; -XX:+UseSerialGC \
    -Djetty.acceptor-threads=$ACCEPTORS \
    -Djetty.selector-threads=$SELECTORS \
    -Djetty.min-threads=$JETTY_MIN_THREADS \
    -Djetty.max-threads=$JETTY_MAX_THREADS \
    -jar /app/useless-demo-service.jar</code></pre></noscript><br />
And now, it starts to look fine, right?<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=inspect-threads-3rd.sh"></script><noscript><pre><code class="language-shell shell">##
# Local docker run 
##
# Run forth version of our container
sudo docker run -d -m 128m --cpus 0.065 --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:4
# List the threads running
sudo docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
&quot;DestroyJavaVM&quot; #13 prio=5 os_prio=0 tid=0x000055927f487000 nid=0x8 waiting on condition [0x0000000000000000]
&quot;qtp2096171631-12-acceptor-0@38ffe3b-ServerConnector@457e2f02{HTTP/1.1,[http/1.1]}{0.0.0.0:45611}&quot; #12 prio=3 os_prio=0 tid=0x000055927f4b9800 nid=0x30 runnable [0x00007ff4bbd45000]
&quot;qtp2096171631-11-lowPrioritySelector&quot; #11 prio=1 os_prio=0 tid=0x000055927f4b4800 nid=0x2f waiting for monitor entry [0x00007ff4bbe46000]
&quot;qtp2096171631-10&quot; #10 prio=5 os_prio=0 tid=0x000055927f4b3000 nid=0x2e runnable [0x00007ff4bbf46000]
&quot;qtp2096171631-9&quot; #9 prio=5 os_prio=0 tid=0x000055927ec6d800 nid=0x2d waiting on condition [0x00007ff4bc048000]
&quot;Attach Listener&quot; #8 daemon prio=9 os_prio=0 tid=0x000055927f7f0000 nid=0x2c waiting on condition [0x0000000000000000]
&quot;Service Thread&quot; #7 daemon prio=9 os_prio=0 tid=0x000055927ea74000 nid=0xf runnable [0x0000000000000000]
&quot;C1 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x000055927ea59000 nid=0xe waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x000055927ea56800 nid=0xd waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x000055927ea54800 nid=0xc runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x000055927ea24000 nid=0xb in Object.wait() [0x00007ff4bc9a7000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x000055927ea19800 nid=0xa in Object.wait() [0x00007ff4bcaa8000]
&quot;VM Thread&quot; os_prio=0 tid=0x000055927ea0f000 nid=0x9 runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x000055927ea71800 nid=0x10 waiting on condition 


##
# Joyent Triton run
##
# Run forth version of our container
eval &quot;$(triton env)&quot;
docker run -d -m 128m --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:4
# List the threads running
docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
Attach Listener&quot; #13 daemon prio=9 os_prio=0 tid=0x0000000000a5f000 nid=0x91c2 waiting on condition [0x0000000000000000]
&quot;DestroyJavaVM&quot; #12 prio=5 os_prio=0 tid=0x0000000000f3f800 nid=0x8e75 waiting on condition [0x0000000000000000]
&quot;qtp2096171631-11-acceptor-0@5230b90f-ServerConnector@5cf74d39{HTTP/1.1,[http/1.1]}{0.0.0.0:54428}&quot; #11 prio=3 os_prio=0 tid=0x0000000001075000 nid=0x8ead runnable [0x00007fffea6fb000]
&quot;qtp2096171631-10-lowPrioritySelector&quot; #10 prio=1 os_prio=0 tid=0x0000000001073000 nid=0x8eac waiting for monitor entry [0x00007fffea9fc000]
&quot;qtp2096171631-9&quot; #9 prio=5 os_prio=0 tid=0x0000000001070800 nid=0x8eab waiting on condition [0x00007fffeacfd000]
&quot;qtp2096171631-8&quot; #8 prio=5 os_prio=0 tid=0x0000000001070000 nid=0x8eaa runnable [0x00007fffeaffd000]
&quot;Service Thread&quot; #7 daemon prio=9 os_prio=0 tid=0x0000000000179000 nid=0x8e81 runnable [0x0000000000000000]
&quot;C1 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x00000000000f5000 nid=0x8e7f waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x00000000000f3000 nid=0x8e7e waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x00000000000f1000 nid=0x8e7d runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x00000000000c4800 nid=0x8e78 in Object.wait() [0x00007ffffd5fe000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x00000000000be800 nid=0x8e77 in Object.wait() [0x00007ffffe9fe000]
&quot;VM Thread&quot; os_prio=0 tid=0x00000000000b4000 nid=0x8e76 runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x0000000000117800 nid=0x8e82 waiting on condition 

</code></pre></noscript></p>
<h2>Be Still Carefull of Many Threads</h2>
<p>Our example web app now runs fine. But keep an eye on the thread count. Other Java/programming language library might create a thread pool and many threads. However, you can configure these libraries too. </p>
<h2>Update 21th June, 2017</h2>
<p>Well, first the <a href="https://blogs.oracle.com/java-platform-group/java-se-support-for-docker-cpu-and-memory-limits">OpenJDK team is improving the situation</a>. As of JDK 8u131, the JVM does limit the CPU&#8217;s in Docker. And with the experimental flags &#8216;-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap&#8217; it does limit the memory.</p>
<p>Also, Matt Rasband has a <a href="https://medium.com/@matt_rasband/dockerizing-a-spring-boot-application-6ec9b9b41faf">good blog post</a> on how to estimate the memory usage of the JVM and set the flags properly.</p>
<p>Have fun running the JVM in a tiny container =)</p><p>The post <a href="https://www.gamlor.info/wordpress/2017/04/deploying-jvm-in-tiny-containers-be-carefull/">Deploying JVM in tiny containers, be carefull!</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>JVM는 작은 컨테이너 안에 배포하면 주의!</title>
		<link>https://www.gamlor.info/wordpress/2017/04/deploying-jvm-in-tiny-containers-be-carefull-kor/</link>
		
		<dc:creator><![CDATA[gamlerhart]]></dc:creator>
		<pubDate>Tue, 25 Apr 2017 13:57:22 +0000</pubDate>
				<category><![CDATA[Technical Wibbly Wobbly]]></category>
		<category><![CDATA[한국어 배우기]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[joyent]]></category>
		<category><![CDATA[JVM]]></category>
		<category><![CDATA[triton]]></category>
		<guid isPermaLink="false">https://www.gamlor.info/wordpress/?p=3475</guid>

					<description><![CDATA[<p>저는 저의 rohrli.gamlor.info 서비스가 재일 작은 트리톤(Triton) 컨테이너 안에 배포됐어요. 저 말고 아무도 사용해서 괜찮아요 ^-^. 이 컨테이너는 128MB 메모리만 있고, 1/16CPU만 있어요. OpenJDK JVM은 메모리를 많이 사용하기 잘 알려져요.&#8230;</p>
<p>The post <a href="https://www.gamlor.info/wordpress/2017/04/deploying-jvm-in-tiny-containers-be-carefull-kor/">JVM는 작은 컨테이너 안에 배포하면 주의!</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>저는 저의 <a href="https://rohrli.gamlor.info">rohrli.gamlor.info</a> 서비스가 재일 작은 트리톤(Triton) 컨테이너 안에 배포됐어요. 저 말고 아무도 사용해서 괜찮아요 ^-^. 이 컨테이너는 128MB 메모리만 있고, 1/16CPU만 있어요. OpenJDK JVM은 메모리를 많이 사용하기 잘 알려져요. 부분적으로 사실이에요. 근데 JVM이 작은 컨테이너 안에 도 작동해요.<br />
이 글에는 조언을 제공할 거예요. 모은 작은 도커(Docker)와  트리톤 컨테이너가 이 문제 있어요. 제가 둘 다 보여줄 거예요 =)<br />
<div id="attachment_3541" style="width: 810px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-usage-edit-1.jpeg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3541" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-usage-edit-1.jpeg" alt="Chrome와 JVM 메머리 잘 먹어요." width="800" height="567" class="size-full wp-image-3541" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-usage-edit-1.jpeg 800w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-usage-edit-1-300x213.jpeg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-usage-edit-1-768x544.jpeg 768w" sizes="(max-width: 800px) 100vw, 800px" /></a><p id="caption-attachment-3541" class="wp-caption-text">Chrome와 JVM 메머리 잘 먹어요.</p></div></p>
<h2>웹앱 예</h2>
<p>이 웹앱 예는 그냥 &#8216;안녕 세상&#8217; 프로그램 이에요. 그리고 설명 때문에 메모리 많이 사용해요. 제가 이 예를 Scala로 만들어요, 근데 모든 JVM의 프로그래밍 언어들이 도같는 문제 있어요. 소스 코드가 <a href="https://github.com/gamlerhart/blog-post-examples/tree/master/jvm-in-small-containers">여기</a> 있어요.<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=Hello-Basics.scala"></script><noscript><pre><code class="language-scala scala">/** 
 * Snippet, memory limits 
 */
// Limit the amount of items in memory for this example.
// So, max ~192*256k=48MBytes
val maxMemoryItems = 192
val memoryPerItem = 256 * 1024
val memoryWasting = new ArrayBlockingQueue[Array[Byte]](maxMemoryItems)

/** 
 * Snippet, request handling
 */
// On each request, consume some memory.
// And keep things in memory to simulate memory use
case &quot;/&quot; :: Nil =&gt; {
    // On each request, consume some memory.
    // And keep things in memory to simulate memory use
    val chunkOfMemory = Array.ofDim[Byte](memoryPerItem)
    var addedToQueue = memoryWasting.offer(chunkOfMemory)

    // Throw things away until we&#039;ve space
    while (!addedToQueue) {
        memoryWasting.poll()
        addedToQueue = memoryWasting.offer(chunkOfMemory)
    }

    val createdSoFar = createdItemsCounter.incrementAndGet()
    response.getWriter.write(
        s&quot;&quot;&quot;
            |{
            |&quot;title&quot;:&quot;Hello World! Let&#039;s use some memory&quot;,
            |&quot;created-overall&quot;:&quot;$createdSoFar&quot;,
            |&quot;queue-size&quot;:&quot;${memoryWasting.size()}&quot;,
            |&quot;&quot;:&quot;Hello. I&#039;m so memory hungry. kthxbye!&quot;
            |}
        &quot;&quot;&quot;.stripMargin)
}</code></pre></noscript><br />
그리고 우리는 이 프로그램은 컴파일하고 도커 컨테이너를 만들어요. 도커 파일가 단순해요:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=version1.Dockerfile"></script><noscript><pre><code class="language-dockerfile dockerfile">FROM openjdk:8u121-jdk-alpine

# Assume already compiled for now
COPY target/scala-2.12/useless-demo-service.jar /app/useless-demo-service.jar

EXPOSE 8080
CMD java -jar /app/useless-demo-service.jar
</code></pre></noscript><br />
그리고 도커 `build`로 이미지 만들고 `run`로 실행해요. 보통 도커는 &#8216;-m 128m&#8217; 명령 행 옵션으로 메모리를 128MB 줘요. 그리고 `&#8211;cpus 0.065`로 조금만 CPU 시간 제공해요.<br />
트리톤 사용하면 &#8216;-m 128m&#8217;가 매미로 <a href="https://apidocs.joyent.com/docker/features/resources">충분한 트리톤 컨테이너</a> 찾고 사용할 거예요. 아니면 &#8216;&#8211;label com.joyent.package=g4-highcpu-128M&#8217;도 작은 컨테이너를 사용할 수 있어요.<br />
우리 컨테이너 시작했는데 그냥 &#8216;watch&#8217; 명령과 &#8216;curl&#8217; 명령으로 이 웹앱 예 사용해요. 그리고 로그 파일을 도 보자!<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=first-run.sh"></script><noscript><pre><code class="language-shell shell">##
# Local docker run 
##
sudo docker run -d -m 128m --cpus 0.065 --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:1
# Start to follow the logs
sudo docker logs -f jvm-on-small-container
# Then, start the simple load, in another termial
watch -n 0.01 curl http://localhost:8080/

##
# Joyent Triton run
##
eval &quot;$(triton env)&quot;
docker run -d -m 128m --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:1
# Get the IP
docker inspect --format &#039;{{ .NetworkSettings.IPAddress }}&#039; jvm-on-small-container
# Start to follow the logs
docker logs -f jvm-on-small-container
# Then, start the simple load, in another termial
watch -n 0.01 curl http://{ip-from-above}:8080/
</code></pre></noscript></p>
<h2>처음 문제. 프로세스가 죽었어요.</h2>
<p>트리톤 컨테이너가 문제 없고 그냥 작동해요. 근데 보통 도커 (Linux 4.10, Docker 17.04) 컨테이너가 갑자기 작동하지 않아요. =(. 프로세스를 죽였어요:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=unexpected-process-death.txt"></script><noscript><pre><code class="language-text text">[root@gamlor-manjaro useless-demo-service]# docker run -m 128m --cpus 0.065 -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:1
2017-04-20 12:58:20.248:INFO::main: Logging initialized @5900ms to org.eclipse.jetty.util.log.StdErrLog
2017-04-20 12:58:23.348:INFO:oejs.Server:main: jetty-9.4.z-SNAPSHOT
2017-04-20 12:58:30.650:INFO:oejs.AbstractConnector:main: Started ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2017-04-20 12:58:30.748:INFO:oejs.Server:main: Started @16602ms
Killed
</code></pre></noscript><br />
흠~~~. 왜 죽였어요? 아&#8230;메모리가 작고 아마 메모리 없었어서 죽었어요. 우리는 컨테이너 작동하는 동안 &#8216;jstat&#8217;로 JVM의 메모리 할당 볼 수 있어요:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=inspect-memory.sh"></script><noscript><pre><code class="language-shell shell">##
# Local docker run 
##
# Get memory usage of the running java process
sudo docker exec jvm-on-small-container sh -c &#039;jstat -gccapacity `pgrep java`&#039;
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC 
84480.0 1354240.0 84480.0 10240.0 10240.0 64000.0 169472.0 2708992.0 169472.0 169472.0 0.0 1056768.0 4480.0 0.0 1048576.0 384.0 1 0


##
# Joyent Triton run
##
# Get memory usage of the running java process
eval &quot;$(triton env)&quot;
docker exec jvm-on-small-container sh -c &#039;jstat -gccapacity `pgrep java`&#039;
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC 
  2688.0  21824.0  21824.0 2176.0 2176.0  17472.0     5504.0    43712.0    43712.0    43712.0      0.0 1060864.0  12544.0      0.0 1048576.0   1536.0     15    69
</code></pre></noscript><br />
<div id="attachment_3534" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-edit.jpeg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3534" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-edit-1024x478.jpeg" alt="펭귄과 고래 위험 조심해주세요." width="700" height="327" class="size-large wp-image-3534" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-edit-1024x478.jpeg 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-edit-300x140.jpeg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-edit-768x358.jpeg 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/memory-edit.jpeg 1400w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3534" class="wp-caption-text">펭귄과 고래 위험 조심해주세요.</p></div><br />
<a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html">jstat</a>가 조금 혼란스러워요. 모든 숫자가 Kilo-Byte이에요. JVM는 메모리 풀 몇 게 있고 메모리 풀이 최저 (**MN), 최고(**MX), 이제(**C) 사용한 메모리 이에요.<br />
그럼 보통 도커 컨테이너 안에 진짜 근 메모리 폴 만들었어요! 네 컴퓨터에 (16GB, Linux 4.10, Docker 17.04) OGCMX (old generation heap) 메모리 풀이 2.5GByte이에요. 그데 트리톤 컨테이너에 40MByte이에요. 그래서 2.5GByte 메모리 풀 있으면 128MByte 이상 메모리 사용하고 죽을 거예요. 지금은 도커가 그냥 너무 많이 메모리 사용하면 프로세스를 죽여요. 근데 JVM이 도커-호스트 메모리 크기 보여서 근 메모리 풀 만들어요.<br />
근데 트리톤 컨테이너 거짓말 좀 잘해서 JVM이 컨테이너의 메모리 크기를 보여서 메모리 풀 충분히 작아요.<br />
그럼 이 문제를 해결할 수 있어요. 그냥 최고 메모리 크기를 &#8216;-Xmx&#8217;로 설정해요. 그리고 난 JVM이 메모리 없으면 메모리 덤프 하고 빨리 죽기도 추천해요:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=version2.Dockerfile"></script><noscript><pre><code class="language-dockerfile dockerfile">FROM openjdk:8u121-jdk-alpine

# Assume already compiled for now
COPY target/scala-2.12/useless-demo-service.jar /app/useless-demo-service.jar

# Defaults for a tiny container
ENV MEMORY=&quot;64m&quot;

EXPOSE 8080

CMD java -Xmx$MEMORY -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError=&quot;kill -9 %p&quot; \
    -jar /app/useless-demo-service.jar</code></pre></noscript><br />
이렇게 하면 보통 도커 컨테이너도 잘 작동해요.<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=inspect-memory-fixed.sh"></script><noscript><pre><code class="language-shell shell">##
# Local docker run 
##
# Memory after limiting heap
sudo docker exec jvm-on-small-container sh -c &#039;jstat -gccapacity `pgrep java`&#039;
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC 
 21504.0  21504.0  21504.0 2560.0 2560.0  16384.0    44032.0    44032.0    44032.0    44032.0      0.0 1060864.0  12544.0      0.0 1048576.0   1536.0      4    28</code></pre></noscript></p>
<h2>스레드 아주 많아요</h2>
<p>그럼 이제는 메모리 잘 설정했어요. 근데 아마 다른 것 도 더 잘 설정할 수 있을까요? 그래서 컨테이너 작동하는 동안 `jstack`로 어느 스레드가 있는 걸 봐요!<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=inspect-threads-1st.sh"></script><noscript><pre><code class="language-shell shell">##
# Local docker run 
##
# Run second version of our container
sudo docker run -d -m 128m --cpus 0.065 --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:2
# List the threads running
sudo docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
&quot;qtp791452441-23&quot; #23 prio=5 os_prio=0 tid=0x000056473bc03800 nid=0x42 waiting on condition [0x00007fefe4931000]
&quot;Attach Listener&quot; #22 daemon prio=9 os_prio=0 tid=0x000056473bf72800 nid=0x41 waiting on condition [0x0000000000000000]
&quot;DestroyJavaVM&quot; #21 prio=5 os_prio=0 tid=0x000056473bcd1800 nid=0x8 waiting on condition [0x0000000000000000]
&quot;qtp791452441-19-acceptor-0@27b0949f-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #19 prio=3 os_prio=0 tid=0x000056473bf75000 nid=0x24 runnable [0x00007fefe4b33000]
&quot;qtp791452441-17&quot; #17 prio=5 os_prio=0 tid=0x000056473bc2d800 nid=0x22 runnable [0x00007fefe8160000]
&quot;qtp791452441-16&quot; #16 prio=5 os_prio=0 tid=0x000056473bc2b000 nid=0x21 runnable [0x00007fefe8261000]
&quot;qtp791452441-15-lowPrioritySelector&quot; #15 prio=1 os_prio=0 tid=0x000056473bc29000 nid=0x20 waiting for monitor entry [0x00007fefe8363000]
&quot;qtp791452441-14-lowPrioritySelector&quot; #14 prio=1 os_prio=0 tid=0x000056473bc8c000 nid=0x1f waiting for monitor entry [0x00007fefe8464000]
&quot;qtp791452441-13-lowPrioritySelector&quot; #13 prio=1 os_prio=0 tid=0x000056473bc8a000 nid=0x1e waiting for monitor entry [0x00007fefe8565000]
&quot;qtp791452441-12-lowPrioritySelector&quot; #12 prio=1 os_prio=0 tid=0x000056473bc86800 nid=0x1d waiting for monitor entry [0x00007fefe8666000]
&quot;qtp791452441-11&quot; #11 prio=5 os_prio=0 tid=0x000056473bd8a800 nid=0x1c runnable [0x00007fefe8766000]
&quot;qtp791452441-10&quot; #10 prio=5 os_prio=0 tid=0x000056473bd84800 nid=0x1b runnable [0x00007fefe8867000]
&quot;Service Thread&quot; #9 daemon prio=9 os_prio=0 tid=0x000056473bc63800 nid=0x19 runnable [0x0000000000000000]
&quot;C1 CompilerThread3&quot; #8 daemon prio=9 os_prio=0 tid=0x000056473bc14000 nid=0x18 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread2&quot; #7 daemon prio=9 os_prio=0 tid=0x000056473bbf9000 nid=0x17 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x000056473bbea000 nid=0x16 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x000056473bbe7000 nid=0x15 waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x000056473bbe4800 nid=0x14 runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x000056473bbb5000 nid=0x13 in Object.wait() [0x00007fefe92cb000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x000056473bbb2000 nid=0x12 in Object.wait() [0x00007fefe93cc000]
&quot;VM Thread&quot; os_prio=0 tid=0x000056473bba8000 nid=0x11 runnable 
&quot;GC task thread#0 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f0000 nid=0x9 runnable 
&quot;GC task thread#1 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f2000 nid=0xa runnable 
&quot;GC task thread#2 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f3800 nid=0xb runnable 
&quot;GC task thread#3 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f5800 nid=0xc runnable 
&quot;GC task thread#4 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f7000 nid=0xd runnable 
&quot;GC task thread#5 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9f9000 nid=0xe runnable 
&quot;GC task thread#6 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9fa800 nid=0xf runnable 
&quot;GC task thread#7 (ParallelGC)&quot; os_prio=0 tid=0x000056473b9fc800 nid=0x10 runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x000056473bc59800 nid=0x1a waiting on condition

##
# Joyent Triton run
##
# Run second version of our container
eval &quot;$(triton env)&quot;
docker run -d -m 128m --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:2
# List the threads running
docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
&quot;qtp791452441-44&quot; #44 prio=5 os_prio=0 tid=0x000000000215e000 nid=0x12de4 runnable [0x00007fffe51f7000]
&quot;qtp791452441-43&quot; #43 prio=5 os_prio=0 tid=0x0000000000262000 nid=0x12aa4 waiting for monitor entry [0x00007fffe52fa000]
&quot;qtp791452441-42&quot; #42 prio=5 os_prio=0 tid=0x000000000068a000 nid=0x11808 waiting on condition [0x00007fffe7c7a000]
&quot;Scheduler-1896277646&quot; #41 prio=5 os_prio=0 tid=0x0000000000145000 nid=0x1176f waiting on condition [0x00007fffe4e34000]
&quot;Attach Listener&quot; #39 daemon prio=9 os_prio=0 tid=0x0000000000717800 nid=0x116e2 waiting on condition [0x0000000000000000]
&quot;DestroyJavaVM&quot; #33 prio=5 os_prio=0 tid=0x0000000000716000 nid=0x10796 waiting on condition [0x0000000000000000]
&quot;qtp791452441-32-acceptor-3@6dbc83d8-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #32 prio=3 os_prio=0 tid=0x0000000000714800 nid=0x1082a runnable [0x00007fffe5cff000]
&quot;qtp791452441-31-acceptor-2@1ac08473-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #31 prio=3 os_prio=0 tid=0x0000000000713000 nid=0x10829 waiting for monitor entry [0x00007fffe6000000]
&quot;qtp791452441-30-acceptor-1@34228b2c-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #30 prio=3 os_prio=0 tid=0x000000000070d800 nid=0x10828 waiting for monitor entry [0x00007fffe67fe000]
&quot;qtp791452441-29-acceptor-0@467e71fc-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #29 prio=3 os_prio=0 tid=0x000000000070b000 nid=0x10827 waiting for monitor entry [0x00007fffe6f72000]
&quot;qtp791452441-28-lowPrioritySelector&quot; #28 prio=1 os_prio=0 tid=0x0000000000695800 nid=0x10818 runnable [0x00007fffe72b3000]
&quot;qtp791452441-27&quot; #27 prio=5 os_prio=0 tid=0x000000000068d800 nid=0x10816 waiting on condition [0x00007fffe75f6000]
&quot;qtp791452441-26-lowPrioritySelector&quot; #26 prio=1 os_prio=0 tid=0x000000000068b800 nid=0x10815 runnable [0x00007fffe7937000]
&quot;qtp791452441-24-lowPrioritySelector&quot; #24 prio=1 os_prio=0 tid=0x0000000000687800 nid=0x10812 waiting for monitor entry [0x00007fffe7fbc000]
&quot;qtp791452441-23&quot; #23 prio=5 os_prio=0 tid=0x0000000000685800 nid=0x10810 waiting for monitor entry [0x00007fffe82fe000]
&quot;qtp791452441-22-lowPrioritySelector&quot; #22 prio=1 os_prio=0 tid=0x0000000000683800 nid=0x1080f waiting for monitor entry [0x00007fffe85ff000]
&quot;qtp791452441-21&quot; #21 prio=5 os_prio=0 tid=0x000000000067d000 nid=0x1080e runnable [0x00007fffe8b1d000]
&quot;Service Thread&quot; #20 daemon prio=9 os_prio=0 tid=0x00000000001ee800 nid=0x107c5 runnable [0x0000000000000000]
&quot;C1 CompilerThread14&quot; #19 daemon prio=9 os_prio=0 tid=0x00000000001e1800 nid=0x107c3 waiting on condition [0x0000000000000000]
&quot;C1 CompilerThread13&quot; #18 daemon prio=9 os_prio=0 tid=0x00000000001d7000 nid=0x107c1 waiting on condition [0x0000000000000000]
&quot;C1 CompilerThread12&quot; #17 daemon prio=9 os_prio=0 tid=0x00000000001d4000 nid=0x107bf waiting on condition [0x0000000000000000]
&quot;C1 CompilerThread11&quot; #16 daemon prio=9 os_prio=0 tid=0x00000000001b7800 nid=0x107bd waiting on condition [0x0000000000000000]
&quot;C1 CompilerThread10&quot; #15 daemon prio=9 os_prio=0 tid=0x00000000001ad800 nid=0x107bc waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread9&quot; #14 daemon prio=9 os_prio=0 tid=0x00000000001a2000 nid=0x107bb waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread8&quot; #13 daemon prio=9 os_prio=0 tid=0x0000000000197800 nid=0x107b9 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread7&quot; #12 daemon prio=9 os_prio=0 tid=0x0000000000172000 nid=0x107b8 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread6&quot; #11 daemon prio=9 os_prio=0 tid=0x0000000000186800 nid=0x107b7 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread5&quot; #10 daemon prio=9 os_prio=0 tid=0x000000000017c000 nid=0x107b6 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread4&quot; #9 daemon prio=9 os_prio=0 tid=0x0000000000165800 nid=0x107b5 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread3&quot; #8 daemon prio=9 os_prio=0 tid=0x000000000010f000 nid=0x107b3 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread2&quot; #7 daemon prio=9 os_prio=0 tid=0x0000000000104800 nid=0x107b2 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x00000000000f5000 nid=0x107b1 waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x00000000000f2800 nid=0x107b0 waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x00000000000f0800 nid=0x107af runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x00000000000c1000 nid=0x107a3 in Object.wait() [0x00007ffffd5fe000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x00000000000be000 nid=0x107a1 in Object.wait() [0x00007ffffe9fe000]
&quot;VM Thread&quot; os_prio=0 tid=0x00000000000b4000 nid=0x1079d runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x00000000001f3800 nid=0x107c6 waiting on condition 
</code></pre></noscript><br />
어머! 30게 이상 스레드 있어요. 내 컴퓨터의 보통 도커 컨테이너 `GC task thread` 8게하고 `CompilerThread` 4개 있어요. 트리톤 컨테이너가 15개 있어요. JVM는 많은 CPU 코어 봐서 스레드 많이 만들어요. 근데 우리 컨테이너가 0.065 CPU 시간만 사용해도 돼요! 이 많은 스레드 돕지 않아요.<br />
<div id="attachment_3536" style="width: 710px" class="wp-caption aligncenter"><a href="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-edit.jpeg"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-3536" src="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-edit-1024x707.jpeg" alt="트리톤 재미 없는 놈 야!" width="700" height="483" class="size-large wp-image-3536" srcset="https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-edit-1024x707.jpeg 1024w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-edit-300x207.jpeg 300w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-edit-768x530.jpeg 768w, https://www.gamlor.info/wordpress/wp-content/uploads/2017/04/cores-edit.jpeg 1400w" sizes="(max-width: 700px) 100vw, 700px" /></a><p id="caption-attachment-3536" class="wp-caption-text">트리톤 재미 없는 놈 야!!</p></div><br />
그리고 우리는 이것도 설정할 수 있어요.<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=version3.Dockerfile"></script><noscript><pre><code class="language-dockerfile dockerfile">FROM openjdk:8u121-jdk-alpine

# Assume already compiled for now
COPY target/scala-2.12/useless-demo-service.jar /app/useless-demo-service.jar

# Defaults for a tiny container
ENV MEMORY=&quot;64m&quot; \
    CPUS=1

EXPOSE 8080

CMD java -Xmx$MEMORY -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError=&quot;kill -9 %p&quot; \
    -XX:CICompilerCount=&quot;$(($CPUS&gt;2?$CPUS:2))&quot; -XX:+UseSerialGC \
    -jar /app/useless-demo-service.jar</code></pre></noscript><br />
이 진짜 작은 컨테이너 이에서 &#8216;ParallelGC&#8217; 필요 없고 그냥 &#8216;SerialGC&#8217; 사용해요. 아니면 조금 더 근 컨테이너 안에 &#8216;ParallelGC&#8217; 사용하면 &#8216;-XX:-XX:+ParallelGCThreads=$CPU&#8217; 사용해요. 또는 &#8216;-XX:+UseG1GC&#8217; 사용하면 &#8216;-XX:G1ConcRefinementThreads=$CPU&#8217;.<br />
그리고 &#8216;-XX:CICompilerCount=$CPU&#8217; 도 설정해요. 근데 &#8216;CICompilerCount&#8217;가 2게 이상 설정해야 돼요.</p>
<h2>스레드 아직 많아요</h2>
<p>&#8216;acceptor&#8217;, &#8216;lowPrioritySelector&#8217; 스레드가 아직 많아요. 트리톤 컨테이너 안에 &#8216;acceptor&#8217; 스레드 4개, lowPrioritySelector 스레드 4개 있어요:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=inspect-threads-2nd.sh"></script><noscript><pre><code class="language-shell shell">##
# Local docker run 
##
# Run third version of our container
sudo docker run -d -m 128m --cpus 0.065 --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:3
# List the threads running
sudo docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
&quot;Attach Listener&quot; #20 daemon prio=9 os_prio=0 tid=0x0000564e7cd17000 nid=0x37 waiting on condition [0x0000000000000000]
&quot;qtp791452441-19&quot; #19 prio=5 os_prio=0 tid=0x0000564e7cd15000 nid=0x36 waiting on condition [0x00007fdcc863f000]
&quot;qtp791452441-17-acceptor-0@77fe3be4-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #17 prio=3 os_prio=0 tid=0x0000564e7cc25000 nid=0x34 runnable [0x00007fdcc8841000]
&quot;DestroyJavaVM&quot; #16 prio=5 os_prio=0 tid=0x0000564e7c922800 nid=0x8 waiting on condition [0x0000000000000000]
&quot;qtp791452441-15-lowPrioritySelector&quot; #15 prio=1 os_prio=0 tid=0x0000564e7ce14000 nid=0x31 waiting for monitor entry [0x00007fdccbd6e000]
&quot;qtp791452441-14&quot; #14 prio=5 os_prio=0 tid=0x0000564e7ce12000 nid=0x30 runnable [0x00007fdccbe6e000]
&quot;qtp791452441-13-lowPrioritySelector&quot; #13 prio=1 os_prio=0 tid=0x0000564e7ce0f800 nid=0x2f waiting for monitor entry [0x00007fdccbf70000]
&quot;qtp791452441-12&quot; #12 prio=5 os_prio=0 tid=0x0000564e7ce0e000 nid=0x2e runnable [0x00007fdccc070000]
&quot;qtp791452441-11-lowPrioritySelector&quot; #11 prio=1 os_prio=0 tid=0x0000564e7ce0c000 nid=0x2d waiting for monitor entry [0x00007fdccc172000]
&quot;qtp791452441-10-lowPrioritySelector&quot; #10 prio=1 os_prio=0 tid=0x0000564e7ce0a000 nid=0x2b waiting for monitor entry [0x00007fdccc273000]
&quot;qtp791452441-9&quot; #9 prio=5 os_prio=0 tid=0x0000564e7ce07800 nid=0x2a runnable [0x00007fdccc373000]
&quot;qtp791452441-8&quot; #8 prio=5 os_prio=0 tid=0x0000564e7ce01000 nid=0x29 runnable [0x00007fdccc474000]
&quot;Service Thread&quot; #7 daemon prio=9 os_prio=0 tid=0x0000564e7c8c2800 nid=0xf runnable [0x0000000000000000]
&quot;C1 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x0000564e7c8b7800 nid=0xe waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x0000564e7c8ac800 nid=0xd waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x0000564e7c8aa800 nid=0xc runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x0000564e7c87d800 nid=0xb in Object.wait() [0x00007fdccccd4000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x0000564e7c873000 nid=0xa in Object.wait() [0x00007fdcccdd5000]
&quot;VM Thread&quot; os_prio=0 tid=0x0000564e7c869000 nid=0x9 runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x0000564e7c8c5800 nid=0x10 waiting on condition 


##
# Joyent Triton run
##
# Run third version of our container
eval &quot;$(triton env)&quot;
docker run -d -m 128m --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:3
# List the threads running
docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
&quot;Attach Listener&quot; #23 daemon prio=9 os_prio=0 tid=0x000000000028c000 nid=0x732a waiting on condition [0x0000000000000000]
&quot;qtp791452441-22&quot; #22 prio=5 os_prio=0 tid=0x00000000006eb000 nid=0x7178 waiting on condition [0x00007fffe81fe000]
&quot;qtp791452441-21-acceptor-3@161ab1a8-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #21 prio=3 os_prio=0 tid=0x00000000006ea000 nid=0x7177 waiting for monitor entry [0x00007fffe84ff000]
&quot;DestroyJavaVM&quot; #20 prio=5 os_prio=0 tid=0x00000000001df000 nid=0x7109 waiting on condition [0x0000000000000000]
&quot;qtp791452441-19-acceptor-2@70b4bcd9-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #19 prio=3 os_prio=0 tid=0x00000000006e7000 nid=0x7175 waiting for monitor entry [0x00007fffe8800000]
&quot;qtp791452441-18-acceptor-1@57033676-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #18 prio=3 os_prio=0 tid=0x0000000000747800 nid=0x7174 waiting for monitor entry [0x00007fffe97f6000]
&quot;qtp791452441-17-acceptor-0@67e0dd84-ServerConnector@512ddf17{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}&quot; #17 prio=3 os_prio=0 tid=0x00000000006e4800 nid=0x7173 runnable [0x00007fffe8ffe000]
&quot;qtp791452441-15-lowPrioritySelector&quot; #15 prio=1 os_prio=0 tid=0x000000000066b000 nid=0x7159 waiting for monitor entry [0x00007fffe9af7000]
&quot;qtp791452441-14&quot; #14 prio=5 os_prio=0 tid=0x000000000066c800 nid=0x7157 runnable [0x00007fffe9df7000]
&quot;qtp791452441-13-lowPrioritySelector&quot; #13 prio=1 os_prio=0 tid=0x0000000000668800 nid=0x7156 waiting for monitor entry [0x00007fffea0f9000]
&quot;qtp791452441-12&quot; #12 prio=5 os_prio=0 tid=0x0000000000666800 nid=0x7155 runnable [0x00007fffea3f9000]
&quot;qtp791452441-11&quot; #11 prio=5 os_prio=0 tid=0x0000000000664800 nid=0x7154 runnable [0x00007fffea6fa000]
&quot;qtp791452441-10-lowPrioritySelector&quot; #10 prio=1 os_prio=0 tid=0x0000000000662800 nid=0x7153 waiting for monitor entry [0x00007fffea9fc000]
&quot;qtp791452441-9&quot; #9 prio=5 os_prio=0 tid=0x0000000000660800 nid=0x7152 runnable [0x00007fffeacfc000]
&quot;qtp791452441-8-lowPrioritySelector&quot; #8 prio=1 os_prio=0 tid=0x0000000000659800 nid=0x7151 waiting for monitor entry [0x00007fffeaffe000]
&quot;Service Thread&quot; #7 daemon prio=9 os_prio=0 tid=0x0000000000130800 nid=0x7120 runnable [0x0000000000000000]
&quot;C1 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x0000000000104000 nid=0x711e waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x00000000000f2800 nid=0x711d waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x00000000000f0800 nid=0x711c runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x00000000000c1000 nid=0x7115 in Object.wait() [0x00007ffffd5fe000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x00000000000be000 nid=0x7113 in Object.wait() [0x00007ffffe9fe000]
&quot;VM Thread&quot; os_prio=0 tid=0x00000000000b4000 nid=0x710f runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x0000000000128800 nid=0x7121 waiting on condition 

</code></pre></noscript><br />
그럼 웹 서버는 이 스레드를 만들어서 사용한 웹 서버 설정해야 돼요. 이 예는 임베디드 Jetty 사용하고 그냥 Java-Properties로 설정할 수 있어졌어요:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=DemoService.scala"></script><noscript><pre><code class="language-scala scala">// Version 1 did just start Jetty
// val server = new Server(8080)
// It creates many acceptors, selectors and threads on big machines, even when running in small container
// So, let&#039;s explicitly configure it.
val minThreads = System.getProperty(&quot;jetty.min-threads&quot;, &quot;8&quot;).toInt
val maxThreads = System.getProperty(&quot;jetty.max-threads&quot;, &quot;200&quot;).toInt
var threadPool = new QueuedThreadPool(minThreads, maxThreads)

val server = new Server(threadPool)
val acceptorCount = System.getProperty(&quot;jetty.acceptor-threads&quot;, &quot;-1&quot;).toInt
val selectorCount = System.getProperty(&quot;jetty.selector-threads&quot;, &quot;-1&quot;).toInt
server.setConnectors(Array(new ServerConnector(server, acceptorCount, selectorCount)))

server.setHandler(new OurHandling)
server.start()</code></pre></noscript><br />
그리고 도커 파일 도 바꿨어요:<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=version4.Dockerfile"></script><noscript><pre><code class="language-dockerfile dockerfile">FROM openjdk:8u121-jdk-alpine

# Assume already compiled for now
COPY target/scala-2.12/useless-demo-service.jar /app/useless-demo-service.jar

# Defaults for a tiny container
ENV MEMORY=&quot;64m&quot; \
    CPUS=1\
    ACCEPTORS=1 \
    SELECTORS=1\
    JETTY_MIN_THREADS=4 \
    JETTY_MAX_THREADS=20

EXPOSE 8080

CMD java -Xmx$MEMORY -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError=&quot;kill -9 %p&quot; \
    -XX:CICompilerCount=&quot;$(($CPUS&gt;2?$CPUS:2))&quot; -XX:+UseSerialGC \
    -Djetty.acceptor-threads=$ACCEPTORS \
    -Djetty.selector-threads=$SELECTORS \
    -Djetty.min-threads=$JETTY_MIN_THREADS \
    -Djetty.max-threads=$JETTY_MAX_THREADS \
    -jar /app/useless-demo-service.jar</code></pre></noscript><br />
그래서 이제 괜찮게 보여요. 아니요?<br />
<script src="https://gist.github.com/e8d7809070bae3cf07d129e1774fae1c.js?file=inspect-threads-3rd.sh"></script><noscript><pre><code class="language-shell shell">##
# Local docker run 
##
# Run forth version of our container
sudo docker run -d -m 128m --cpus 0.065 --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:4
# List the threads running
sudo docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
&quot;DestroyJavaVM&quot; #13 prio=5 os_prio=0 tid=0x000055927f487000 nid=0x8 waiting on condition [0x0000000000000000]
&quot;qtp2096171631-12-acceptor-0@38ffe3b-ServerConnector@457e2f02{HTTP/1.1,[http/1.1]}{0.0.0.0:45611}&quot; #12 prio=3 os_prio=0 tid=0x000055927f4b9800 nid=0x30 runnable [0x00007ff4bbd45000]
&quot;qtp2096171631-11-lowPrioritySelector&quot; #11 prio=1 os_prio=0 tid=0x000055927f4b4800 nid=0x2f waiting for monitor entry [0x00007ff4bbe46000]
&quot;qtp2096171631-10&quot; #10 prio=5 os_prio=0 tid=0x000055927f4b3000 nid=0x2e runnable [0x00007ff4bbf46000]
&quot;qtp2096171631-9&quot; #9 prio=5 os_prio=0 tid=0x000055927ec6d800 nid=0x2d waiting on condition [0x00007ff4bc048000]
&quot;Attach Listener&quot; #8 daemon prio=9 os_prio=0 tid=0x000055927f7f0000 nid=0x2c waiting on condition [0x0000000000000000]
&quot;Service Thread&quot; #7 daemon prio=9 os_prio=0 tid=0x000055927ea74000 nid=0xf runnable [0x0000000000000000]
&quot;C1 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x000055927ea59000 nid=0xe waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x000055927ea56800 nid=0xd waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x000055927ea54800 nid=0xc runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x000055927ea24000 nid=0xb in Object.wait() [0x00007ff4bc9a7000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x000055927ea19800 nid=0xa in Object.wait() [0x00007ff4bcaa8000]
&quot;VM Thread&quot; os_prio=0 tid=0x000055927ea0f000 nid=0x9 runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x000055927ea71800 nid=0x10 waiting on condition 


##
# Joyent Triton run
##
# Run forth version of our container
eval &quot;$(triton env)&quot;
docker run -d -m 128m --name=jvm-on-small-container -p 8080:8080 gamlerhart/blog-jvm-on-small-containers:4
# List the threads running
docker exec jvm-on-small-container sh -c &#039;jstack `pgrep java`&#039; | grep os_prio 
Attach Listener&quot; #13 daemon prio=9 os_prio=0 tid=0x0000000000a5f000 nid=0x91c2 waiting on condition [0x0000000000000000]
&quot;DestroyJavaVM&quot; #12 prio=5 os_prio=0 tid=0x0000000000f3f800 nid=0x8e75 waiting on condition [0x0000000000000000]
&quot;qtp2096171631-11-acceptor-0@5230b90f-ServerConnector@5cf74d39{HTTP/1.1,[http/1.1]}{0.0.0.0:54428}&quot; #11 prio=3 os_prio=0 tid=0x0000000001075000 nid=0x8ead runnable [0x00007fffea6fb000]
&quot;qtp2096171631-10-lowPrioritySelector&quot; #10 prio=1 os_prio=0 tid=0x0000000001073000 nid=0x8eac waiting for monitor entry [0x00007fffea9fc000]
&quot;qtp2096171631-9&quot; #9 prio=5 os_prio=0 tid=0x0000000001070800 nid=0x8eab waiting on condition [0x00007fffeacfd000]
&quot;qtp2096171631-8&quot; #8 prio=5 os_prio=0 tid=0x0000000001070000 nid=0x8eaa runnable [0x00007fffeaffd000]
&quot;Service Thread&quot; #7 daemon prio=9 os_prio=0 tid=0x0000000000179000 nid=0x8e81 runnable [0x0000000000000000]
&quot;C1 CompilerThread1&quot; #6 daemon prio=9 os_prio=0 tid=0x00000000000f5000 nid=0x8e7f waiting on condition [0x0000000000000000]
&quot;C2 CompilerThread0&quot; #5 daemon prio=9 os_prio=0 tid=0x00000000000f3000 nid=0x8e7e waiting on condition [0x0000000000000000]
&quot;Signal Dispatcher&quot; #4 daemon prio=9 os_prio=0 tid=0x00000000000f1000 nid=0x8e7d runnable [0x0000000000000000]
&quot;Finalizer&quot; #3 daemon prio=8 os_prio=0 tid=0x00000000000c4800 nid=0x8e78 in Object.wait() [0x00007ffffd5fe000]
&quot;Reference Handler&quot; #2 daemon prio=10 os_prio=0 tid=0x00000000000be800 nid=0x8e77 in Object.wait() [0x00007ffffe9fe000]
&quot;VM Thread&quot; os_prio=0 tid=0x00000000000b4000 nid=0x8e76 runnable 
&quot;VM Periodic Task Thread&quot; os_prio=0 tid=0x0000000000117800 nid=0x8e82 waiting on condition 

</code></pre></noscript></p>
<h2>스레드 많기 아직 조심하세요!</h2>
<p>우리 웹앱 예 이제 괜찮게 작동해요. 근데 스레드 개수 잘 보세요. 다른 Java/프로그래밍 언어 라이브러리도 아마 스레드 풀 만들고 스레드 너무 많이 만들어요. 근데 이 라이브러리들이 도 설정할 수 있어요.</p>
<h2>Update 21th June, 2017</h2>
<p>먼저, <a href="https://blogs.oracle.com/java-platform-group/java-se-support-for-docker-cpu-and-memory-limits">JDK 프로그래머들이 도커 지원 개선 가요.</a>. JDK 8u131부터, JVM는 CPU를 한도 해요. 그리고 `-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap&#8217; 사용하면 메모리도 한도 해요.</p>
<p>그리고 Matt Rasband는 <a href="https://medium.com/@matt_rasband/dockerizing-a-spring-boot-application-6ec9b9b41faf">좋은 블로그 글 썼어요</a>. 이 글이 어떡해 JVM의 메모리 사이즈 대략 추산하고 메모리의 명령 행 옵션 자동으로 설정하기 설명해요.   </p>
<p>작은 JVM 컨테이너 잘 사용하세요 =).</p><p>The post <a href="https://www.gamlor.info/wordpress/2017/04/deploying-jvm-in-tiny-containers-be-carefull-kor/">JVM는 작은 컨테이너 안에 배포하면 주의!</a> first appeared on <a href="https://www.gamlor.info/wordpress">Gamlor</a>.</p>]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
