<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Christian Köberl</title>
    <description>The latest articles on DEV Community by Christian Köberl (@derkoe).</description>
    <link>https://dev.to/derkoe</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F139565%2Fbea9f038-76c8-4aec-8665-e22bb55c3227.jpg</url>
      <title>DEV Community: Christian Köberl</title>
      <link>https://dev.to/derkoe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/derkoe"/>
    <language>en</language>
    <item>
      <title>Beating C with 33 Lines of Java</title>
      <dc:creator>Christian Köberl</dc:creator>
      <pubDate>Mon, 29 Jun 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/derkoe/beating-c-with-33-lines-of-java-1473</link>
      <guid>https://dev.to/derkoe/beating-c-with-33-lines-of-java-1473</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was published originally on &lt;a href="https://derkoe.dev/blog/beating-c-with-java/"&gt;derkoe.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After reading the "Beating C with X lines of Y" &lt;sup id="fnref1"&gt;1&lt;/sup&gt; last year I immediately thought about trying this in my go-to language: Java. Now you might ask: "Java? Isn't Java known to have a slow startup and heavy memory footprint?" But let's see how Java performs - especially with its latest incarnation &lt;a href="https://www.graalvm.org/"&gt;GraalVM&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmarking
&lt;/h2&gt;

&lt;p&gt;I will be using &lt;a href="https://www.gnu.org/software/time/"&gt;GNU time&lt;/a&gt; for the time and memory comparison (same as the &lt;a href="https://ajeetdsouza.github.io/blog/posts/beating-c-with-70-lines-of-go/"&gt;Go version&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;/usr/bin/time &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"%es %MKB"&lt;/span&gt; &lt;span class="nb"&gt;wc &lt;/span&gt;lorem_ipsum.txt
  17023  782992 4830478 lorem_ipsum.txt
0.05s 2064KB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All results are from runs on my Laptop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intel Core i7-8550U (4 cores, 8 threads)&lt;/li&gt;
&lt;li&gt;16 GB RAM&lt;/li&gt;
&lt;li&gt;WSL2 running Arch Linux on Windows 10 (2004)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The "standard" approach
&lt;/h2&gt;

&lt;p&gt;The initial version I came up with used the obvious way in Java - reading the file using a &lt;code&gt;BufferedReader&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;InputStream&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Files&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Paths&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BufferedReader&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BufferedReader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InputStreamReader&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(&lt;a href="https://github.com/derkoe/wc-java/blob/master/wc_br.java"&gt;full code on GitHub&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Running some first tests with this code shows that it can't compete with the native &lt;code&gt;wc&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;th&gt;Input file&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Max memory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;wc&lt;/td&gt;
&lt;td&gt;4.6MB&lt;/td&gt;
&lt;td&gt;0.05s&lt;/td&gt;
&lt;td&gt;2,064KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wc-br.java&lt;/td&gt;
&lt;td&gt;4.6MB&lt;/td&gt;
&lt;td&gt;0.24s&lt;/td&gt;
&lt;td&gt;40,188KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wc&lt;/td&gt;
&lt;td&gt;100MB&lt;/td&gt;
&lt;td&gt;0.43s&lt;/td&gt;
&lt;td&gt;2,188KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wc-br.java&lt;/td&gt;
&lt;td&gt;100MB&lt;/td&gt;
&lt;td&gt;1.21s&lt;/td&gt;
&lt;td&gt;45,036KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Manual buffering
&lt;/h2&gt;

&lt;p&gt;So let's try a more direct approach with manual buffering (inspired by the &lt;a href="https://ajeetdsouza.github.io/blog/posts/beating-c-with-70-lines-of-go/"&gt;Go version&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;wc&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;lineCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wordCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;charCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;cbuf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
    &lt;span class="nc"&gt;InputStream&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;in&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Files&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Paths&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]));&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Reader&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InputStreamReader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;prevWhitespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cbuf&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;charVal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cbuf&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
          &lt;span class="n"&gt;charCount&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;charVal&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;lineCount&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
            &lt;span class="n"&gt;prevWhitespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
          &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isWhitespace&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;charVal&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;prevWhitespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
          &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prevWhitespace&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;wordCount&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
            &lt;span class="n"&gt;prevWhitespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
          &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// printing&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(&lt;a href="https://github.com/derkoe/wc-java/blob/master/wc.java"&gt;full code on GitHub&lt;/a&gt; - 33 lines of code according to &lt;a href="https://github.com/XAMPPRocky/tokei"&gt;tokei&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Let's try this version:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;th&gt;Input file&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Max memory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;wc&lt;/td&gt;
&lt;td&gt;4.6MB&lt;/td&gt;
&lt;td&gt;0.05s&lt;/td&gt;
&lt;td&gt;2,064KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wc.java&lt;/td&gt;
&lt;td&gt;4.6MB&lt;/td&gt;
&lt;td&gt;0.18s&lt;/td&gt;
&lt;td&gt;39,844KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wc&lt;/td&gt;
&lt;td&gt;100MB&lt;/td&gt;
&lt;td&gt;0.43s&lt;/td&gt;
&lt;td&gt;2,188KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wc.java&lt;/td&gt;
&lt;td&gt;100MB&lt;/td&gt;
&lt;td&gt;0.46s&lt;/td&gt;
&lt;td&gt;42,840KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Looking a lot better for big files (almost the same time) but still not that good for small ones. And the used memory is more than an order of magnitude higher: ~40MB vs 2MB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter GraalVM
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.graalvm.org/"&gt;GraalVM&lt;/a&gt; is a new ecosystem and platform for running Java and other programming languages (like JavaScript, Ruby or Python). One of main benefits for Java programs is to compile them to a native executable which reduces startup-time and memory usage.&lt;/p&gt;

&lt;p&gt;Let's give it a try - after installing GraalVM and &lt;a href="https://www.graalvm.org/docs/reference-manual/native-image/"&gt;native-image&lt;/a&gt; simply compile the Java class to a native binary with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;javac wc.java &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; native-image &lt;span class="nb"&gt;wc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;which results in a native binary &lt;code&gt;wc&lt;/code&gt; (or &lt;code&gt;wc.exe&lt;/code&gt;) for your platform (currently cross-compilation is not supported).&lt;/p&gt;

&lt;p&gt;When running the same code above with the native binary there are major improvements - here are the results plus a test with a 1GB file:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;th&gt;Input file&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Max memory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;wc&lt;/td&gt;
&lt;td&gt;4.6MB&lt;/td&gt;
&lt;td&gt;0.05s&lt;/td&gt;
&lt;td&gt;2,064KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wc.java (native)&lt;/td&gt;
&lt;td&gt;4.6MB&lt;/td&gt;
&lt;td&gt;0.03s&lt;/td&gt;
&lt;td&gt;7,172KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wc&lt;/td&gt;
&lt;td&gt;100MB&lt;/td&gt;
&lt;td&gt;0.43s&lt;/td&gt;
&lt;td&gt;2,188KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wc.java (native)&lt;/td&gt;
&lt;td&gt;100MB&lt;/td&gt;
&lt;td&gt;0.39s&lt;/td&gt;
&lt;td&gt;7,524KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wc&lt;/td&gt;
&lt;td&gt;1GB&lt;/td&gt;
&lt;td&gt;4.20s&lt;/td&gt;
&lt;td&gt;2,120KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wc.java (native)&lt;/td&gt;
&lt;td&gt;1GB&lt;/td&gt;
&lt;td&gt;3.57s&lt;/td&gt;
&lt;td&gt;10,968KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Memory usage is down to 7MB for file up to 100 MB and we now easily beat the time of the C implementation. Still, the memory consumption is 3-5 time higher than the "real" native program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Java has come a long way - from Applets to enterprise server application and now microservices. Because of the J2EE/enterprise era it is known for heavy memory usage and slow startup times but in recent years Java has changed and adapted to the cloud native boom. With GraalVM and native images Java can now even compete with system languages like C, Go or Rust. With native image Java is now also a viable solution for building CLIs.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="http://verisimilitudes.net/2019-11-11"&gt;Ada&lt;/a&gt;, &lt;a href="https://ajeetdsouza.github.io/blog/posts/beating-c-with-70-lines-of-go/"&gt;Go&lt;/a&gt;, &lt;a href="https://chrispenner.ca/posts/wc"&gt;Haskell&lt;/a&gt;, &lt;a href="https://medium.com/@martinmroz/beating-c-with-120-lines-of-rust-wc-a0db679fe920"&gt;Rust&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>java</category>
      <category>linux</category>
      <category>graalvm</category>
    </item>
    <item>
      <title>Development Environment in WSL2</title>
      <dc:creator>Christian Köberl</dc:creator>
      <pubDate>Mon, 25 May 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/derkoe/development-environment-in-wsl2-137l</link>
      <guid>https://dev.to/derkoe/development-environment-in-wsl2-137l</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was published originally on &lt;a href="https://derkoe.dev/blog/development-environment-in-wsl2/"&gt;derkoe.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This guide shows how to setup a full development environment including UI apps (X11) in WSL2 on Windows 10. WSL2 enables a "full" Linux development environment in Windows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;The first thing you might ask is: why? First, we have to run Windows on our machines - so the all-in Linux does not work. Second, Linux is a lot faster for building software than Windows - our biggest app compiles in 13 minutes under Windows and in just 2 minutes under WSL on my machine which is a massive improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable WSL2 and Install Ubuntu
&lt;/h2&gt;

&lt;p&gt;For WSL2 to work you will need a Windows 10 build 19041 (aka 20H1) or higher (any edition will work, even Home). Then simply follow the &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/wsl2-install"&gt;guide from Microsoft&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enable the features WSL and VM-Platform in Powershell as Admin:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
   dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Restart Windows&lt;/li&gt;
&lt;li&gt;Set WSL2 as default:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   wsl --set-default-version 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Go to the Microsoft Store and install "Ubuntu"&lt;/li&gt;
&lt;li&gt;Launch Ubuntu from Start menu (this will ask you for a user account)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can now re-launch a shell in your Ubuntu instance with "Ubuntu" from the Start menu or execute &lt;code&gt;wsl&lt;/code&gt; from the command line. The WSL command line tool has many options which you can find with &lt;code&gt;wsl --help&lt;/code&gt; or in the &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/reference"&gt;Command Reference&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update and Install Software
&lt;/h2&gt;

&lt;p&gt;Inside your Ubuntu Linux update all packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then install packages you need for your development - in my case it is Java 11, Maven, Node.js/NPM and git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;openjdk-11-jdk openjdk-11-source maven nodejs npm git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Do not install Docker CLI or Docker Compose because these are provided by Docker Desktop (see next section).&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Docker (optional)
&lt;/h2&gt;

&lt;p&gt;Most developers need Docker for their local setup - the newest Docker Desktop version supports WSL2 out of the box (even on Windows Home).&lt;/p&gt;

&lt;h2&gt;
  
  
  GUI Apps
&lt;/h2&gt;

&lt;p&gt;Currently there is no support for GUI apps for WSL - Microsoft has &lt;a href="https://devblogs.microsoft.com/commandline/the-windows-subsystem-for-linux-build-2020-summary/#wsl-gui"&gt;announced that they are working on GUI support using Wayland&lt;/a&gt; and that it should ship in 2020. So you have to use X11 forwarding or other tricks to enable this - I have tried all of them and there are some issues with any of the solutions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;X11 server on Windows (&lt;a href="https://sourceforge.net/projects/vcxsrv/"&gt;VcXsrv&lt;/a&gt; or &lt;a href="https://x410.dev/"&gt;X410&lt;/a&gt;) and setting the DISPLAY variable in Linux (&lt;code&gt;export DISPLAY=&lt;/code&gt;&lt;code&gt;ip route show | grep 'default via' | awk '{print $3}'&lt;/code&gt;&lt;code&gt;:0.0&lt;/code&gt; in your &lt;code&gt;.bashrc&lt;/code&gt;).

&lt;ul&gt;
&lt;li&gt;Works quite well - good performance, shortcuts work, even mouse back/forward buttons work as expected&lt;/li&gt;
&lt;li&gt;The main problem is that when you go to standby or hibernate the &lt;a href="https://superuser.com/questions/1474559/wsl2-x11-programs-disappear"&gt;connection between Windows and WSL breaks&lt;/a&gt; and all your apps stop. If you can live with that  go with this solution!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Running &lt;a href="http://xrdp.org/"&gt;xrdp&lt;/a&gt; on Linux and using Remote Desktop to connect

&lt;ul&gt;
&lt;li&gt;In this case you are running a full desktop - that means you have to install Xfce (Gnome does not seem to work).&lt;/li&gt;
&lt;li&gt;With this solution the whole UI feels a bit laggy and slow - I tried to tune the xrdp params without success.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://xpra.org/"&gt;Xpra&lt;/a&gt; - a virtual X11 server to connect via a client on Windows (or other platforms)

&lt;ul&gt;
&lt;li&gt;The solution works but there are many issues like crashes, window positions are completely wrong, extra mouse buttons do not work, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wiki.x2go.org/"&gt;X2Go&lt;/a&gt; - also a virtual X11 server with an Windows client

&lt;ul&gt;
&lt;li&gt;This seems to be the most promising solution&lt;/li&gt;
&lt;li&gt;As with plain X11: good performance, shortcuts work, even mouse back/forward buttons work as expected, plus the reconnect feature&lt;/li&gt;
&lt;li&gt;The only drawback is the quirky Windows client (but I got used to it)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  X2Go
&lt;/h3&gt;

&lt;p&gt;Here is the X2Go setup in more details (since it worked best for me).&lt;/p&gt;

&lt;h4&gt;
  
  
  Initial setup
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Fix SSH host keys
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get remove &lt;span class="nt"&gt;--purge&lt;/span&gt; openssh-server
   &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;openssh-server
   &lt;span class="nb"&gt;sudo &lt;/span&gt;service ssh &lt;span class="nt"&gt;--full-restart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install X2Go on your Linux distribution
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;   apt &lt;span class="nb"&gt;install &lt;/span&gt;x2goserver
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://code.x2go.org/releases/X2GoClient_latest_mswin32-setup.exe"&gt;Download&lt;/a&gt; and install the client for Windows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Configure the &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Host: &lt;code&gt;localhost&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Login: &lt;code&gt;&amp;lt;your user&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Session type: Published Applications&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  After each WSL/Windows restart
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Launch ssh in Linux (if not started yet): &lt;code&gt;sudo service ssh start&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Launch "X2Go Client" on Windows ad connect to the server with user/password&lt;/li&gt;
&lt;li&gt;Now you can launch X11 apps via the tray icon (see &lt;a href="https://wiki.x2go.org/doku.php/wiki:advanced:published-applications"&gt;X2Go Published Applications&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Editors/IDEs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Visual Studio Code
&lt;/h3&gt;

&lt;p&gt;Simply install VSCode and then you can open it from the Linux shell with &lt;code&gt;code&lt;/code&gt; or &lt;code&gt;code &amp;lt;path&amp;gt;&lt;/code&gt; - most of the time it will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  IntelliJ IDEA
&lt;/h3&gt;

&lt;p&gt;On a normal Ubuntu you could install &lt;a href="https://snapcraft.io/search?q=intellij"&gt;IntelliJ IDEA via Snap&lt;/a&gt; but Snap does not work on WSL2 (there is &lt;a href="https://discourse.ubuntu.com/t/using-snapd-in-wsl2/12113"&gt;a hacky workaround&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;So, the easiest way is to install it manually:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the latest tar.gz from &lt;a href="https://www.jetbrains.com/idea/download/index.html#section=linux"&gt;the downloads page&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Extract it an create a symlink (so you can easily switch versions):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;cd&lt;/span&gt; /opt
   &lt;span class="nb"&gt;sudo tar &lt;/span&gt;xzf /mnt/c/Users/&lt;span class="nv"&gt;$USER&lt;/span&gt;/Downloads/idea-&lt;span class="o"&gt;{&lt;/span&gt;edition-version&lt;span class="o"&gt;}&lt;/span&gt;.tar.gz
   &lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /opt/idea-&lt;span class="o"&gt;{&lt;/span&gt;edition-version&lt;span class="o"&gt;}&lt;/span&gt; /opt/idea
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;To easily launch the app via the X2Go context menu create an app desktop entry &lt;code&gt;/usr/share/applications/intellij-idea.desktop&lt;/code&gt; with the following contents:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ini"&gt;&lt;code&gt;   &lt;span class="nn"&gt;[Desktop Entry]&lt;/span&gt;
   &lt;span class="py"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Intellij IDEA&lt;/span&gt;
   &lt;span class="py"&gt;Comment&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;JetBrains Intellij IDEA Java IDE&lt;/span&gt;
   &lt;span class="py"&gt;Categories&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Development&lt;/span&gt;
   &lt;span class="py"&gt;Keywords&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;java;ide&lt;/span&gt;
   &lt;span class="py"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/opt/idea/bin/idea.sh&lt;/span&gt;
   &lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Application&lt;/span&gt;
   &lt;span class="py"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/opt/idea/bin/idea.png&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Open Issues
&lt;/h2&gt;

&lt;p&gt;There are still many issues with WSL2 - the biggest problems are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Systemd is not running - the official issue is &lt;a href="https://github.com/microsoft/WSL/issues/994"&gt;Blockers for systemd?&lt;/a&gt;. Seems like Microsoft is working with the Systemd team on this problem. Anyway withoud Systemd you cannot run any services and things like Snap packages do not work. There are some workarounds like &lt;a href="https://github.com/arkane-systems/genie"&gt;genie&lt;/a&gt; or &lt;a href="https://forum.snapcraft.io/t/running-snaps-on-wsl2-insiders-only-for-now/13033"&gt;this instructions&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GUI apps are a pain (in the a..) - like alrady mentioned above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are many troubles with VPN solutions: &lt;a href="https://github.com/microsoft/WSL/issues/4277"&gt;CISCO AnyConnect&lt;/a&gt;, &lt;a href="https://github.com/microsoft/WSL/issues/4246"&gt;Checkpoint VPN&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://adamtheautomator.com/windows-subsystem-for-linux/"&gt;Windows Subsystem for Linux (WSL): The Ultimate Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/darksmile92/linux-on-windows-wsl-with-desktop-environment-via-rdp-522g"&gt;Linux on Windows: WSL with Desktop Environment via RDP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://eising.wordpress.com/2018/11/05/howto-functional-ubuntu-desktop-on-windows-10-wsl/"&gt;HOWTO: Functional Ubuntu desktop on Windows 10/WSL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>windows</category>
      <category>wsl</category>
    </item>
  </channel>
</rss>
