<?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>Forem: Diogo Souza da Silva</title>
    <description>The latest articles on Forem by Diogo Souza da Silva (@diogok).</description>
    <link>https://forem.com/diogok</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%2F125218%2F20727db8-07b2-4114-84c4-7cce6999d73e.jpeg</url>
      <title>Forem: Diogo Souza da Silva</title>
      <link>https://forem.com/diogok</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/diogok"/>
    <language>en</language>
    <item>
      <title>Technologies I learned and that I do not use</title>
      <dc:creator>Diogo Souza da Silva</dc:creator>
      <pubDate>Wed, 01 Apr 2020 12:07:01 +0000</pubDate>
      <link>https://forem.com/diogok/technologies-i-learned-and-that-i-do-not-use-3k3</link>
      <guid>https://forem.com/diogok/technologies-i-learned-and-that-i-do-not-use-3k3</guid>
      <description>&lt;h1&gt;
  
  
  Context
&lt;/h1&gt;

&lt;p&gt;I was reflecting the other day on the tools I know and, specially, the ones I do not know. That led me to think “why do I not know these tools by now?”.&lt;/p&gt;

&lt;p&gt;One of the reasons is that I learnt other things, and is what lead to this text.&lt;/p&gt;

&lt;p&gt;That might sound obvious, but I actually have to choose what to invest my time, and make trade offs.&lt;/p&gt;

&lt;p&gt;Here I share some technologies I learned and invested and that did not really pay off, that I abandoned or that just made me take a long run.&lt;/p&gt;

&lt;p&gt;These are not the most recent or older, most bad or good, these are just the ones I remember better and find most interesting to share.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaFX
&lt;/h2&gt;

&lt;p&gt;Now, this was a bet. For those for do not know, JavaFX was a new UI toolkit for java. For desktop, that is.&lt;/p&gt;

&lt;p&gt;Back when JavaFX came out it was already time for “rich web apps”, so people had already moved on from desktop apps, so it this was a risky shot at least.&lt;/p&gt;

&lt;p&gt;What I found interesting about it was that it had a functional programing style (or, at least, function as first class elements), two-way binding of properties and the UI and heavy focus on components and composability. You could even style components with what resembled CSS.&lt;/p&gt;

&lt;p&gt;That said, it was still java on desktop, it looked slow at that time, and people were already on the web. Apart from that, I had no desktop app to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker before v1.0
&lt;/h2&gt;

&lt;p&gt;There was actually a turning point in docker where it became stable, sometime after v1.0.&lt;/p&gt;

&lt;p&gt;I began investing in docker around v0.5 or something. At that time a lot of functions were missing, and docker-compose was either not existent or very limited.&lt;/p&gt;

&lt;p&gt;Due to being so new and lacking functionality, I have written and adopted several wrappers around docker for that year to provided much needed resources.&lt;/p&gt;

&lt;p&gt;It was interesting that at each release of docker or docker-compose I could remove one extra tool or remove on more script from my custom setup in favor of the official docker way.&lt;/p&gt;

&lt;p&gt;Still this one payed off in the end, as docker is the industry standard, but being an early adopter was a long and hard run.&lt;/p&gt;

&lt;h2&gt;
  
  
  CouchDB
&lt;/h2&gt;

&lt;p&gt;My favorite DB. CouchDB offered a schemaless, HTTP and Map-reduce enabled database that was very resilient and easy to use. It even included replication over http and a feed endpoint. It was really awesome.&lt;/p&gt;

&lt;p&gt;I actually got to build a major system in my career on top of it, paired with Elasticsearch. But after that, it did no gain enough traction.&lt;/p&gt;

&lt;p&gt;MongoDB basically killed it, becoming the go to nosql at that time. And the fact that CouchDB was slow, view building specially, did not help.&lt;/p&gt;

&lt;p&gt;CouchDB is still improving, now includes search, clustering is easier and other goodies.&lt;/p&gt;

&lt;p&gt;Now a days I mostly use PostgreSQL and Elasticsearch, paired with something from the cloud my system might be using (dynamodb, firestore…).&lt;/p&gt;

&lt;h2&gt;
  
  
  JS Games and Augmented Reality
&lt;/h2&gt;

&lt;p&gt;Now this was just for fun, but I always go back and forth in learning something related to games in the browser. I find it really fascinating and I really liked to work with the Canvas on HTML5. &lt;/p&gt;

&lt;p&gt;One of the experiments that I spent most time with was building AR experiences for mobile browser. That was hard, limited experience and very much fun.&lt;/p&gt;

&lt;p&gt;This was obviously just a hobby, and it did take time away from learning tools that I would actually use on a daily basis. But it was worth it nevertheless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lua
&lt;/h2&gt;

&lt;p&gt;My favorite language that I never used.&lt;/p&gt;

&lt;p&gt;Lua is an easy, simple and small language that you can embed anywhere and that have implementation on every platform. Used a lot in games, in nginx by resty (and Kong, based on that) and who knows where else.&lt;/p&gt;

&lt;p&gt;I do know it well enough to safely use it in production. Even right now I am testing Fennel, a lisp in lua. But I have never used it for anything serious. Maybe a kong plugin soon?&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;I do not regret learning any of those, they all added something interesting, I had fun playing with as hobby and some were really useful for some time.&lt;/p&gt;

&lt;p&gt;Now, time to learn something new that might or might not stick.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Efficient Clojure multistage docker images, with java and native-image</title>
      <dc:creator>Diogo Souza da Silva</dc:creator>
      <pubDate>Wed, 15 Jan 2020 17:47:55 +0000</pubDate>
      <link>https://forem.com/diogok/efficient-clojure-multistage-docker-images-with-java-and-native-image-1e9i</link>
      <guid>https://forem.com/diogok/efficient-clojure-multistage-docker-images-with-java-and-native-image-1e9i</guid>
      <description>&lt;p&gt;Here I explore a few optimization when building docker images for your clojure apps.&lt;/p&gt;

&lt;h1&gt;
  
  
  Image versions
&lt;/h1&gt;

&lt;p&gt;One easy way to make it faster for you local development and for CI/CD is to just use smaller images, and to reuse images. &lt;/p&gt;

&lt;p&gt;Using common public images make it more likely that you will use the same image over and over again, also pinning to the most specific version help assure the base image have not changed between builds. Choosing alpine or slim images can reduce the image size. &lt;/p&gt;

&lt;p&gt;For the base image I use &lt;code&gt;clojure:openjdk-13-tools-deps-slim-buster&lt;/code&gt; and &lt;code&gt;openjdk:13-slim-buster&lt;/code&gt;. I prefer &lt;code&gt;buster&lt;/code&gt; images over &lt;code&gt;alpine&lt;/code&gt; due to compatibility with most native libs, and rumor has it that due to libc versions it can be faster.&lt;/p&gt;

&lt;h1&gt;
  
  
  Build cache
&lt;/h1&gt;

&lt;p&gt;The next step is to leverage the docker image build cache, so the order of the steps you use for building the image matter.&lt;/p&gt;

&lt;p&gt;You generally want to set non-changing configurations like ENV, WORKING_DIR and EXPOSE first.&lt;/p&gt;

&lt;p&gt;To decouple installing the deps from actually building the artifact, the next thing you add is your deps files and install it.&lt;/p&gt;

&lt;p&gt;The code is what changes most, so it goes last, right before actually building the uberjar.&lt;/p&gt;

&lt;h1&gt;
  
  
  Garbage collector and heap size
&lt;/h1&gt;

&lt;p&gt;Not optimization of images but a tip.&lt;/p&gt;

&lt;p&gt;Current versions of openjdk support running in containers, so it is best to use relative memory limits and container support with &lt;code&gt;-XX:+UseContainerSupport&lt;/code&gt; and &lt;code&gt;-XX:MaxRAMPercentage=85&lt;/code&gt; just we don`t have to mess with Xmx or Xms at runtime anymore. &lt;/p&gt;

&lt;p&gt;Remember that the JVM uses a little more memory than the heap, so give it some extra space.&lt;/p&gt;

&lt;h1&gt;
  
  
  Multistage
&lt;/h1&gt;

&lt;p&gt;To further reduce the image size and remove clutter from base image, we can start with a JVM only image and copy the generated jar over. This will remove clojure specific tools, sources-code, intermediate artifacts and others.&lt;/p&gt;

&lt;h1&gt;
  
  
  Resulting Dockerfile
&lt;/h1&gt;

&lt;p&gt;After applying these tips, here is the resulting Dockerfile:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h1&gt;
  
  
  Native image
&lt;/h1&gt;

&lt;p&gt;Now, for bonus, we can also setup a native image using graalvm tools. This will reduce image size by a lot, as it does not depend on the JVM, and potentially reduce memory usage.&lt;/p&gt;

&lt;p&gt;Note that native-image is only compatible with linux x86-64, and is new tech, so a lot o frameworks can break it. It also does not give better performance (latency, throughput, gc times…) comparing to JVM version.&lt;br&gt;
Some flags may change depending on your tools of choice.&lt;/p&gt;

&lt;p&gt;The native image will build upon the previous tips, but has to be based of java 11 instead of latest.&lt;/p&gt;

&lt;p&gt;Here is the dockerfile:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Note that there is a lot of netty specific config there, as I use aleph for HTTP.&lt;/p&gt;

&lt;h1&gt;
  
  
  Opensource full example
&lt;/h1&gt;

&lt;p&gt;All this experiments and other framework choices are available at my &lt;a href="https://github.com/diogok/klj-api/"&gt;github klj-api&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;Hope it helped.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>clojure</category>
      <category>graalvm</category>
    </item>
    <item>
      <title>An incomplete comparison of geospatial file formats</title>
      <dc:creator>Diogo Souza da Silva</dc:creator>
      <pubDate>Wed, 17 Oct 2018 11:46:01 +0000</pubDate>
      <link>https://forem.com/diogok/an-incomplete-comparison-of-geospatial-file-formats-1b06</link>
      <guid>https://forem.com/diogok/an-incomplete-comparison-of-geospatial-file-formats-1b06</guid>
      <description>&lt;p&gt;A few years ago I was working with geospatial analysis and got to study and compare a few alternative file formats for storing and, especially, transferring such data.&lt;/p&gt;

&lt;p&gt;I worked mainly with vector data (polygons and points) and served that for the web. The motivation of this work was to test the gains and cost of TopoJSON, and how it fared in size (important for transfer time) and encoding time (important for server resource usage).&lt;/p&gt;

&lt;p&gt;A more complete description of advantages of the available formats can be found at &lt;a href="http://switchfromshapefile.org/"&gt;Shapefile must die!&lt;/a&gt; , a good resource even if a bit strong on words (FYI: As a developer, I really dislike working with shapefile).&lt;/p&gt;

&lt;p&gt;Even if I never got to finish it, I guess I can share the results anyway.&lt;/p&gt;

&lt;h3&gt;
  
  
  The contender file formats
&lt;/h3&gt;

&lt;p&gt;First, let`s make some groups. Here we will compare three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data structure&lt;/li&gt;
&lt;li&gt;Format encoding&lt;/li&gt;
&lt;li&gt;Compression&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;strong&gt;data structure&lt;/strong&gt;, I am are comparing how data is organized inside the file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shape&lt;/li&gt;
&lt;li&gt;GeoJSON structure&lt;/li&gt;
&lt;li&gt;TopoJSON structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;strong&gt;format encoding&lt;/strong&gt; , I am comparing how this structure is serialized:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Binary (shapefile)&lt;/li&gt;
&lt;li&gt;JSON&lt;/li&gt;
&lt;li&gt;MessagePack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;strong&gt;compression&lt;/strong&gt; , I am comparing compression algorithms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;None&lt;/li&gt;
&lt;li&gt;Deflate/GZIP&lt;/li&gt;
&lt;li&gt;XZ/LZMA&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The choices of what to test were made based on tooling availability on programing language(Java/Clojure) and ease of use from the web(Javascript).&lt;/p&gt;

&lt;p&gt;A few notes of formats not tested:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSV&lt;/strong&gt; was not tested cause it is not as standard as it looks with several combinations of separators, enclosing and record separator. And also would have to compare WKT and WKB and other geometry encodings. But it would probably fare well as it can be streamed and well compressed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spatialite&lt;/strong&gt; is a bit more complex to handle, as you will not only need an SQLite library but with extensions for Spatialite. Also would have to define table structure and such.&lt;/p&gt;

&lt;p&gt;Given more time I would include more tests on both.&lt;/p&gt;

&lt;p&gt;Shapefile was only tested as a baseline.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overall results
&lt;/h3&gt;

&lt;p&gt;The code and results can be found at &lt;a href="https://github.com/diogok/geof"&gt;my github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
| Structure | Format | Compress | Size | Time |&lt;br&gt;
|-----------|---------|----------|-------|------|&lt;br&gt;
| Shapefile | - | - | 5MB | - |&lt;br&gt;
| Shapefile | - | zip | 3.2MB | - |&lt;br&gt;
| Geo | JSON | - | 9MB | 10s |&lt;br&gt;
| Geo | JSON | gz | 2.5MB | 11s |&lt;br&gt;
| Geo | JSON | xz | 1.4MB | 21s |&lt;br&gt;
| Geo | MsgPack | - | 5.2MB | 9s |&lt;br&gt;
| Geo | MsgPack | gz | 3.5MB | 11s |&lt;br&gt;
| Geo | MsgPack | xz | 1.7MB | 15s |&lt;br&gt;
| Topo | JSON | - | 524KB | 22s |&lt;br&gt;
| Topo | JSON | gz | 84KB | 20s |&lt;br&gt;
| Topo | JSON | xz | 64KB | 22s |&lt;br&gt;
| Topo | MsgPack | - | 256KB | 21s |&lt;br&gt;
| Topo | MsgPack | gz | 76KB | 20s |&lt;br&gt;
| Topo | MsgPack | xz | 60KB | 22s |&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Shapefiles are the baseline, they do not compress very well.&lt;/p&gt;

&lt;p&gt;As expected raw GeoJSON files are huge, but as text files, they compress very well, and are reasonably fast to encode.&lt;/p&gt;

&lt;p&gt;TopoJSON files are minimal in size but take a long time to encode. Also not included in this test is the fact that topology encoding takes a lot of memory, as it has to hold the whole collection to iterate over it.&lt;/p&gt;

&lt;p&gt;MessagePack as a format offers reasonable space efficiency being a binary format and encode faster. They add more complexity to the web and lose most gains after compression. They are faster to read/write on the server but slower on the browser.&lt;/p&gt;

&lt;p&gt;Deflate/GZ offer expected compression results. They are standard on the web which makes it an easy choice, you server already have them, and so does the browser.&lt;/p&gt;

&lt;p&gt;LZMA/XZ is a bit harder to use on the browser, but it is able to deliver even more.&lt;/p&gt;

&lt;h3&gt;
  
  
  A few conclusions
&lt;/h3&gt;

&lt;p&gt;This test is incomplete and you should run your own on your set of data to get more practical results to your reality.&lt;/p&gt;

&lt;p&gt;But here is my take on it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shapefiles sucks cause they are a lot of files and with several limitations&lt;/li&gt;
&lt;li&gt;If nothing else, at least enable DEFLATE on your geojson serving&lt;/li&gt;
&lt;li&gt;TopoJSON is complex to deal with and expensive to encode&lt;/li&gt;
&lt;li&gt;TopoJSON offers insane compaction, specially on polygons with a lot of shared lines&lt;/li&gt;
&lt;li&gt;MsgPack offers nice compaction over text, but most of that is lost over compression&lt;/li&gt;
&lt;li&gt;LZMA/XZ adds a little complexity but it gave good gains on bigger files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, if you can afford to encode only once with resources to spare: TopoJSON with XZ gives the most value. If you have to encode/decode on the fly: GeoJSON with XZ. If you can spare disk, offer both: TopoJSON and GeoJSON with XZ and GZ.&lt;/p&gt;

</description>
      <category>gis</category>
      <category>geojson</category>
      <category>geospatial</category>
      <category>maps</category>
    </item>
    <item>
      <title>Terraform workspaces and locals for environment separation</title>
      <dc:creator>Diogo Souza da Silva</dc:creator>
      <pubDate>Mon, 11 Sep 2017 12:01:01 +0000</pubDate>
      <link>https://forem.com/diogok/terraform-workspaces-and-locals-for-environment-separation-2cgd</link>
      <guid>https://forem.com/diogok/terraform-workspaces-and-locals-for-environment-separation-2cgd</guid>
      <description>&lt;p&gt;&lt;a href="https://terraform.io"&gt;Terraform&lt;/a&gt; is this amazing tool to provision and manage changes on your cloud infrastructure while following the great practice of keeping your infrastructure-as-code.&lt;/p&gt;

&lt;p&gt;One common need on infrastructure management is to build multiple environments, such as testing and production, with mostly the same setup but keeping a few variables different, like networking and sizing.&lt;/p&gt;

&lt;p&gt;The first tool help us with that is &lt;a href="https://www.terraform.io/docs/state/workspaces.html"&gt;terraform workspaces&lt;/a&gt;. Previously called environments, it allows you to create different and independent states on the same configuration. And as it’s compatible with remote backend this workspaces are shared with your team.&lt;/p&gt;

&lt;p&gt;As an example, let’s work with the following simple infrastructure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
 region= "us-east-1"
}

resource "aws\_instance" "my\_service" {
 ami="ami-7b4d7900"
 instance\_type="t2.micro"
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we have defined a single aws ec2 instance andterraform apply will have your testing server up.&lt;/p&gt;

&lt;p&gt;But that is only one environment, in this simple example one might think that it would be ok to simple replicate and call one service “testing_my_service” and the other “prod_my_server”, but this approach will quickly lead to confusion as your setup grows in complexity and more resources are added.&lt;/p&gt;

&lt;p&gt;What you can do instead is use workspaces to separate them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform workspace new production
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this, you are now in production workspace. This one will have the same configuration, since we are in the same folder and module of terraform, but nothing created. Thus, if you terraform apply it will create another server with the same configuration but not changing the previous workspace.&lt;/p&gt;

&lt;p&gt;To go back to testing you can terraform workspace select default , since we are using default as the testing environment to make sure we are not working on production by mistake.&lt;/p&gt;

&lt;p&gt;But, obviously, there are differences between testing and production, and the first approach would be to use variables and an if switch on the resources. Instead a better approach would be to use the recently introduced &lt;a href="https://www.terraform.io/docs/configuration/locals.html"&gt;terraform locals&lt;/a&gt; to keep resources lean of logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
 region= "us-east-1"
}

locals {
 env="${terraform.workspace}"

counts = {
 "default"=1
 "production"=3
 }

instances = {
 "default"="t2.micro"
 "production"="t4.large"
 }

instance\_type="${lookup(local.instances,local.env)}"
 count="${lookup(local.counts,local.env)}"
}

resource "aws\_instance" "my\_service" {
 ami="[ami-7b4d7900](https://console.aws.amazon.com/ec2/home?region=us-east-1#launchAmi=ami-7b4d7900)"
 instance\_type="${local.instance\_type}"
 count="${local.count}"
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The main difference from variables is that locals can have logic in them instead of in the resources, while variables allow only values and pushed the logic into the resources.&lt;/p&gt;

&lt;p&gt;One thing to keep in mind is that terraform is rapidly evolving and is worth to keep an eye on it’s changes to make sure you making the most of it.&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
