<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Gregory Trubetskoy</title>
    <link>https://grisha.org/</link>
    <description>Recent content on Gregory Trubetskoy</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 23 Jan 2018 11:41:00 +0000</lastBuildDate>
    <atom:link href="https://grisha.org/atom.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Blockchain Proof-of-Work is a Decentralized Clock</title>
      <link>https://grisha.org/blog/2018/01/23/explaining-proof-of-work/</link>
      <pubDate>Tue, 23 Jan 2018 11:41:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2018/01/23/explaining-proof-of-work/</guid>
      <description>&lt;p&gt;This is an explanation of the key function on Proof-of-Work in the&#xA;Bitcoin blockchain.  It focuses on the one feature of Proof-of-Work&#xA;that is essential and shows that other features often talked about&#xA;such as security are secondary side-effects, useful, but not&#xA;essential.&lt;/p&gt;&#xA;&lt;p&gt;This explanation rests on illustrating a few interesting properties of&#xA;how Proof-of-Work is used in the blockchain that are not immediately&#xA;obvious and sometimes are rather counter-intuitive, for example how&#xA;participants collectively solve a problem without &lt;em&gt;ever&#xA;communicating&lt;/em&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Bitcoin Blockchain PostgresSQL Schema</title>
      <link>https://grisha.org/blog/2017/12/15/blockchain-and-postgres/</link>
      <pubDate>Fri, 15 Dec 2017 08:28:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/12/15/blockchain-and-postgres/</guid>
      <description>&lt;p&gt;In a &lt;a href=&#34;https://grisha.org/blog/2017/10/10/postgre-as-a-full-node/&#34;&gt;previous post&lt;/a&gt; I wrote&#xA;some initial thoughts on storing the blockchain in Postgres. It&amp;rsquo;s been&#xA;a couple of months and I&amp;rsquo;ve made some progress on the&#xA;&lt;a href=&#34;https://github.com/blkchain/blkchain&#34;&gt;import project&lt;/a&gt;. This post documents&#xA;the latest incarnation of the SQL schema used to store the&#xA;blockchain as well as thoughts on why it was decided to be this way.&lt;/p&gt;&#xA;&lt;h2 id=&#34;blockchain-data-structure-overview&#34;&gt;Blockchain Data Structure Overview&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;https://bitcoin.org/en/developer-reference#block-chain&#34;&gt;Bitcoin blockchain&lt;/a&gt;&#xA;consists of &lt;em&gt;&lt;a href=&#34;https://bitcoin.org/en/developer-reference#serialized-blocks&#34;&gt;blocks&lt;/a&gt;&lt;/em&gt;.&#xA;A block is a set of &lt;em&gt;&lt;a href=&#34;https://bitcoin.org/en/developer-reference#raw-transaction-format&#34;&gt;transactions&lt;/a&gt;&lt;/em&gt;.&#xA;A block also contains some &lt;a href=&#34;https://bitcoin.org/en/developer-reference#block-headers&#34;&gt;block-specific information&lt;/a&gt;,&#xA;such as the nonce for the &lt;a href=&#34;https://en.bitcoin.it/wiki/Proof_of_work&#34;&gt;Proof-Of-Work&lt;/a&gt; validating the block.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Blockchain in PostgreSQL Part 2</title>
      <link>https://grisha.org/blog/2017/10/20/blockchain-in-postgresql-part-2/</link>
      <pubDate>Fri, 20 Oct 2017 08:05:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/10/20/blockchain-in-postgresql-part-2/</guid>
      <description>&lt;p&gt;Update: there is now a &lt;a href=&#34;https://grisha.org/blog/2017/12/15/blockchain-and-postgres/&#34;&gt;better write up&lt;/a&gt;&#xA;of the PostgreSQL schema. This post was rather half-baked as much was&#xA;still not understood when I wrote it.&lt;/p&gt;&#xA;&lt;p&gt;In a &lt;a href=&#34;https://grisha.org/blog/2017/10/10/postgre-as-a-full-node/&#34;&gt;previous post&lt;/a&gt; I&#xA;described a simplistic schema to store the Bitcoin blockchain in&#xA;PostgreSQL. In this post I&amp;rsquo;m investigating pushing the envelope&#xA;with a bit of C programming.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-missing-functionality&#34;&gt;The Missing Functionality&lt;/h3&gt;&#xA;&lt;p&gt;Postgres cannot do certain things required to fully handle&#xA;transactions. The missing functionality is (at least):&lt;/p&gt;</description>
    </item>
    <item>
      <title>Bitcoin Transaction Hash in Pure PostgreSQL</title>
      <link>https://grisha.org/blog/2017/10/10/postgre-as-a-full-node/</link>
      <pubDate>Tue, 10 Oct 2017 17:54:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/10/10/postgre-as-a-full-node/</guid>
      <description>&lt;p&gt;Update: hacked together&#xA;&lt;a href=&#34;https://github.com/blkchain/pg_blkchain&#34;&gt;this&lt;/a&gt;, more details to&#xA;follow later&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;In theory, Postgres should be able to verify transactions and blocks,&#xA;as well as do a lot of other things that are currently only done by&#xA;full nodes. For this to be performant, it will most likely require an&#xA;extension written in C, but I&amp;rsquo;m curious how far we can get with bare&#xA;bones Postgres.&lt;/p&gt;&#xA;&lt;p&gt;More importantly, would that actually be useful? A node is really&#xA;just a database, a very efficient one for a very specific purpose, but&#xA;would leveraging the full power of Postgres be somehow more beneficial&#xA;than just running Bitcoin-Qt or btcd, for example?&lt;/p&gt;</description>
    </item>
    <item>
      <title>Electricity cost of 1 Bitcoin (Sep 2017)</title>
      <link>https://grisha.org/blog/2017/09/28/electricity-cost-of-1-bitcoin/</link>
      <pubDate>Thu, 28 Sep 2017 16:38:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/09/28/electricity-cost-of-1-bitcoin/</guid>
      <description>&lt;p&gt;How much does it cost in electricity to mine a Bitcoin?&lt;/p&gt;&#xA;&lt;p&gt;As of Sep 28, 2017, according to blockchain.info the hashrate is:&#xA;9,214,860,125 GH/s.&lt;/p&gt;&#xA;&lt;p&gt;These days it seems that the best miner available for sale is the&#xA;AntMiner S9. It is actually over a year old, and there are faster and&#xA;more energy efficient ASICs now, e.g. BitFury, but it is very hard to&#xA;get any information on those, so we will just use the S9 information.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Bitcoin: USD Value</title>
      <link>https://grisha.org/blog/2017/09/25/bitcoin-value-2/</link>
      <pubDate>Mon, 25 Sep 2017 08:50:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/09/25/bitcoin-value-2/</guid>
      <description>&lt;p&gt;In &lt;a href=&#34;https://grisha.org/blog/2017/09/22/bitcoin-value/&#34;&gt;part 1&lt;/a&gt; I explained&#xA;how money has always been a global ledger and Bitcoin is just a&#xA;different implementation of one. The million dollar question remains,&#xA;what should Bitcoin be worth in a currency we&amp;rsquo;re more familiar with,&#xA;such as USD?&lt;/p&gt;&#xA;&lt;h3 id=&#34;asset-pricing&#34;&gt;Asset Pricing&lt;/h3&gt;&#xA;&lt;p&gt;To illustrate the dilemma we&amp;rsquo;re faced with, lets look at three types&#xA;of assets and how we price them.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Stocks:&lt;/em&gt; price is determined by the present and future profits, which&#xA;is relatively straight forward.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Bitcoin: Better Ink than Gold?</title>
      <link>https://grisha.org/blog/2017/09/22/bitcoin-value/</link>
      <pubDate>Fri, 22 Sep 2017 07:52:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/09/22/bitcoin-value/</guid>
      <description>&lt;p&gt;The fundamental question about Bitcoin is not whether it is sound from&#xA;the cryptography standpoint. The question is: what is it?&lt;/p&gt;&#xA;&lt;h3 id=&#34;money-is-debt-ink&#34;&gt;Money is Debt Ink&lt;/h3&gt;&#xA;&lt;p&gt;To define Bitcoin we need to look back at the history of &lt;em&gt;money&lt;/em&gt;.  The&#xA;earliest money was in the form of things that were scarce and&#xA;impossible to falsify, something like specific kinds of sea shells.&#xA;Everyone knew that stuff could be traded for these tokens.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tgres Status - July 4th 2017</title>
      <link>https://grisha.org/blog/2017/07/04/tgres-status-july-2017/</link>
      <pubDate>Tue, 04 Jul 2017 08:28:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/07/04/tgres-status-july-2017/</guid>
      <description>&lt;p&gt;It&amp;rsquo;s been a while since I&amp;rsquo;ve written on&#xA;&lt;a href=&#34;https://github.com/tgres/tgres&#34;&gt;Tgres&lt;/a&gt;,&#xA;here&amp;rsquo;s a little update, Independence Day edition.&lt;/p&gt;&#xA;&lt;h3 id=&#34;current-status&#34;&gt;Current Status&lt;/h3&gt;&#xA;&lt;p&gt;The current status is that Tgres is looking more and more like a&#xA;finished product. It still needs time and especially user testing (the&#xA;ball is in your court, dear reader), because only time reveals the&#xA;weirdest of bugs and validates stability. I would not ditch your&#xA;current stack just yet, but at this point you&amp;rsquo;d be remiss not&#xA;having given Tgres a spin.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building a Go Web App in 2017</title>
      <link>https://grisha.org/blog/2017/04/27/simplistic-go-web-app/</link>
      <pubDate>Thu, 27 Apr 2017 15:00:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/04/27/simplistic-go-web-app/</guid>
      <description>&lt;p&gt;Update: &lt;a href=&#34;https://grisha.org/blog/2017/04/27/simplistic-go-web-app-part-2/&#34;&gt;part 2&lt;/a&gt; is&#xA;here, enjoy. And &lt;a href=&#34;https://grisha.org/blog/2017/04/27/go-web-app-part-3/&#34;&gt;part 3&lt;/a&gt;. And&#xA;&lt;a href=&#34;https://grisha.org/blog/2017/04/27/go-web-app-part-4/&#34;&gt;part 4&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;A few weeks ago I started building yet another web-based app, in&#xA;&lt;a href=&#34;https://golang.org/&#34;&gt;Go&lt;/a&gt;. Being mostly a back-end developer, I don&amp;rsquo;t&#xA;have to write web apps very often, and every time I do, it seems like a great challenge.&#xA;I often wish someone would write a guide to web development for people&#xA;who do not have all day to get into the intricacies of great design&#xA;and just need to build a functional site that works without too much&#xA;fuss.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building a Go Web App - Part 2</title>
      <link>https://grisha.org/blog/2017/04/27/simplistic-go-web-app-part-2/</link>
      <pubDate>Thu, 27 Apr 2017 14:00:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/04/27/simplistic-go-web-app-part-2/</guid>
      <description>&lt;p&gt;This is a continuation of &lt;a href=&#34;https://grisha.org/blog/2017/04/27/simplistic-go-web-app/&#34;&gt;part 1&lt;/a&gt;.&#xA;(There is also &lt;a href=&#34;https://grisha.org/blog/2017/04/27/go-web-app-part-3/&#34;&gt;part 3&lt;/a&gt;&#xA;and &lt;a href=&#34;https://grisha.org/blog/2017/04/27/go-web-app-part-4/&#34;&gt;part 4&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;p&gt;So our app is going to have two major parts to it: client and&#xA;server. (What year is this?). The server side is going to be in Go,&#xA;and the client side in JS. Let&amp;rsquo;s talk about the server side first.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-go-server-side&#34;&gt;The Go (Server) Side&lt;/h2&gt;&#xA;&lt;p&gt;The server side of our application is going to be responsible for&#xA;initially serving up all the necessary JavaScript and supporting files&#xA;if any, aka static assets and data in the form of JSON. That&amp;rsquo;s it,&#xA;just two functions: (1) static assets and (2) JSON.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building a Go Web App - Part 3</title>
      <link>https://grisha.org/blog/2017/04/27/go-web-app-part-3/</link>
      <pubDate>Thu, 27 Apr 2017 13:00:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/04/27/go-web-app-part-3/</guid>
      <description>&lt;p&gt;This is part 3. See &lt;a href=&#34;https://grisha.org/blog/2017/04/27/simplistic-go-web-app/&#34;&gt;part 1&lt;/a&gt;&#xA;and &lt;a href=&#34;https://grisha.org/blog/2017/04/27/simplistic-go-web-app-part-2/&#34;&gt;part 2&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The previous two posts got us to a point where we had a Go app which&#xA;was able to serve a tiny bit of HTML. This post will talk about the&#xA;client side, which, alas, is mostly JavaScript, not Go.&lt;/p&gt;&#xA;&lt;h3 id=&#34;javascript-in-2017&#34;&gt;JavaScript in 2017&lt;/h3&gt;&#xA;&lt;p&gt;This is what gave me the most grief. I don&amp;rsquo;t really know how to&#xA;categorize the mess that present day JavaScript is, nor do I really&#xA;know what to attribute it to, and trying to rationalize it would make&#xA;for a great, but entirely different blog post. So I&amp;rsquo;m just going to&#xA;accept this as the reality we cannot change and move on to how to best&#xA;work with it.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building a Go Web App - Part 4</title>
      <link>https://grisha.org/blog/2017/04/27/go-web-app-part-4/</link>
      <pubDate>Thu, 27 Apr 2017 09:13:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/04/27/go-web-app-part-4/</guid>
      <description>&lt;p&gt;This is part 4. See &lt;a href=&#34;https://grisha.org/blog/2017/04/27/simplistic-go-web-app/&#34;&gt;part 1&lt;/a&gt;,&#xA;&lt;a href=&#34;https://grisha.org/blog/2017/04/27/simplistic-go-web-app-part-2/&#34;&gt;part 2&lt;/a&gt; and&#xA;&lt;a href=&#34;https://grisha.org/blog/2017/04/27/go-web-app-part-3/&#34;&gt;part 3&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;In this part I will try to briefly go over the missing pieces in our&#xA;very simplistic Go Web App.&lt;/p&gt;&#xA;&lt;h3 id=&#34;http-handler-wrappers&#34;&gt;HTTP Handler Wrappers&lt;/h3&gt;&#xA;&lt;p&gt;I tiny rant: I do not like the word &amp;ldquo;middleware&amp;rdquo;. The concept of a&#xA;wrapper has been around since the dawn of computing, there is no need&#xA;to invent new words for it.&lt;/p&gt;&#xA;&lt;p&gt;Having that out of the way, let&amp;rsquo;s say we need to require&#xA;authentication for a certain URL. This is what our index handler&#xA;presently looks like:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tgres 0.10.0b - Time Series with Go and PostgreSQL</title>
      <link>https://grisha.org/blog/2017/03/22/tgres-0-dot-10-dot-0b-time-series-with-go-and-postgresql/</link>
      <pubDate>Wed, 22 Mar 2017 13:52:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/03/22/tgres-0-dot-10-dot-0b-time-series-with-go-and-postgresql/</guid>
      <description>&lt;p&gt;After nearly two years of hacking, I am tagging this version of&#xA;&lt;a href=&#34;https://github.com/tgres/tgres&#34;&gt;Tgres&lt;/a&gt;&#xA;as beta. It is functional and stable enough for people to try out and&#xA;not feel like they are wasting their time. There is still a lot that&#xA;could and should be improved, but at this point the most&#xA;important thing is to get more people to check it out.&lt;/p&gt;&#xA;&lt;h3 id=&#34;what-is-tgres&#34;&gt;What is Tgres?&lt;/h3&gt;&#xA;&lt;p&gt;Tgres is a &lt;a href=&#34;https://golang.org&#34;&gt;Go&lt;/a&gt; program which can receive time&#xA;series data via &lt;a href=&#34;https://graphiteapp.org/&#34;&gt;Graphite&lt;/a&gt;, &lt;a href=&#34;https://github.com/etsy/statsd/wiki&#34;&gt;Statsd&lt;/a&gt;&#xA;protocols or an http &lt;a href=&#34;https://godoc.org/github.com/tgres/tgres/http#PixelHandler&#34;&gt;pixel&lt;/a&gt;, store it&#xA;in &lt;a href=&#34;https://www.postgresql.org/&#34;&gt;PostgreSQL&lt;/a&gt;, and provide Graphite-like access to the data&#xA;in a way that is compatible with tools such as &lt;a href=&#34;https://grafana.com/&#34;&gt;Grafana&lt;/a&gt;. You could think of it as a&#xA;drop-in Graphite/Statsd replacement, though I&amp;rsquo;d rather avoid direct&#xA;comparison, because the key feature of Tgres is that data is stored in&#xA;PostgreSQL.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tgres Load Testing Follow Up</title>
      <link>https://grisha.org/blog/2017/02/28/tgres-load-testing-follow-up/</link>
      <pubDate>Tue, 28 Feb 2017 21:40:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/02/28/tgres-load-testing-follow-up/</guid>
      <description>&lt;p&gt;To follow up on the &lt;a href=&#34;https://grisha.org/blog/2017/02/23/can-tgres-outperform-graphite/&#34;&gt;previous post&lt;/a&gt;,&#xA;after a bunch&#xA;of tweaking, here is Tgres (&lt;a href=&#34;https://github.com/tgres/tgres/commit/90924e4afa4ac8bef61caf46c3439794983660ec&#34;&gt;commit&lt;/a&gt;) receiving over 150,000 data points per&#xA;second across 500,000 time series without any signs of the queue size&#xA;or any other resource blowing up.&lt;/p&gt;&#xA;&lt;p&gt;This is both Tgres and Postgres running on the same i2.2xlarge EC2 instance (8 cores, 64GB, SSD).&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grisha.org/images/tgres_aws1_150k.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;At this point I think there&amp;rsquo;s been enough load testing and optimization, and I am&#xA;going to get back to crossing the t&amp;rsquo;s and dotting the i&amp;rsquo;s so that we can release&#xA;the first version of Tgres.&lt;/p&gt;</description>
    </item>
    <item>
      <title>PostgreSQL vs Whisper, which is Faster?</title>
      <link>https://grisha.org/blog/2017/02/23/can-tgres-outperform-graphite/</link>
      <pubDate>Thu, 23 Feb 2017 09:49:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/02/23/can-tgres-outperform-graphite/</guid>
      <description>&lt;p&gt;Note: there is an &lt;a href=&#34;https://grisha.org/blog/2017/02/28/tgres-load-testing-follow-up/&#34;&gt;update&lt;/a&gt; to this post.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;&#xA;&lt;p&gt;On a 8 CPU / 16 GB EC2 instance,&#xA;&lt;a href=&#34;https://github.com/tgres/tgres&#34;&gt;Tgres&lt;/a&gt; can process 150,000 data&#xA;points per second across 300,000 series (Postgres running on the same&#xA;machine). With some tweaks we were able to get the number of series to&#xA;half a million, flushing ~60K data points per second.&lt;/p&gt;&#xA;&lt;h2 id=&#34;now-the-long-version&#34;&gt;Now the long version&amp;hellip;&lt;/h2&gt;&#xA;&lt;p&gt;If you were to ask me whether Tgres could outperform Graphite, just a&#xA;couple of months ago my answer would have been &amp;ldquo;No&amp;rdquo;. Tgres uses&#xA;Postgres to store time series data, while Graphite stores data by&#xA;writing to files directly, the overhead of the relational database&#xA;just seemed too great.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Storing Time Series in PostgreSQL - Optimize for Write</title>
      <link>https://grisha.org/blog/2017/01/21/storing-time-seris-in-postgresql-optimize-for-write/</link>
      <pubDate>Sat, 21 Jan 2017 09:33:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2017/01/21/storing-time-seris-in-postgresql-optimize-for-write/</guid>
      <description>&lt;p&gt;Continuing on the&#xA;&lt;a href=&#34;https://grisha.org/blog/2016/12/16/storing-time-series-in-postgresql-part-ii/&#34;&gt;previous&lt;/a&gt;&#xA;write up on how time series data can be stored in Postgres&#xA;efficiently, here is another approach, this time providing for extreme&#xA;write performance.&lt;/p&gt;&#xA;&lt;p&gt;The &amp;ldquo;horizontal&amp;rdquo; data structure in the last article requires an SQL&#xA;statement for every data point update. If you cache data points long&#xA;enough, you might be able to collect a bunch for a series and write&#xA;them out at once for a slight performance advantage. But there is no&#xA;way to update multiple series with a single statement, it&amp;rsquo;s always&#xA;at least one update per series. With a large number of series, this&#xA;can become a performance bottleneck. Can we do better?&lt;/p&gt;</description>
    </item>
    <item>
      <title>Simple Tgres Part II - A High Rate Counter</title>
      <link>https://grisha.org/blog/2016/12/28/simple-tgres-part-ii-a-high-rate-counter/</link>
      <pubDate>Wed, 28 Dec 2016 17:06:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/12/28/simple-tgres-part-ii-a-high-rate-counter/</guid>
      <description>&lt;p&gt;Continuing on the &lt;a href=&#34;https://grisha.org/blog/2016/12/21/simple-time-series-app-with-tgres/&#34;&gt;the previous&lt;/a&gt;&#xA;post on simple use of &lt;a href=&#34;https://github.com/tgres/tgres&#34;&gt;Tgres&lt;/a&gt; components, let&amp;rsquo;s&#xA;try to count something that goes by really fast.&lt;/p&gt;&#xA;&lt;p&gt;This time let&amp;rsquo;s start out with creating a memory-based SerDe. This&#xA;means that all our data is in memory and there is no database backing&#xA;our series.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/tgres/tgres/dsl&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;h&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/tgres/tgres/http&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/tgres/tgres/receiver&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/tgres/tgres/rrd&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/tgres/tgres/serde&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;step&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Second&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;// 1 second resolution&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;span&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;600&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;step&lt;/span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;// spanning 10 minutes&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// In-memory SerDe&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;ms&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;serde&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NewMemSerDe&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Create a receiver of our data points backed by the above&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// memory SerDe&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;rcvr&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;receiver&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;New&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ms&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;receiver&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SimpleDSFinder&lt;/span&gt;{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;rrd&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;DSSpec&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;Step&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;step&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;RRAs&lt;/span&gt;: []&lt;span style=&#34;color:#a6e22e&#34;&gt;rrd&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RRASpec&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;rrd&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;RRASpec&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;Function&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;rrd&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;WMEAN&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;Step&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;step&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;Span&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;span&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }}})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;rcvr&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Start&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s create a goroutine which creates data points as fast as it&#xA;can, the difference from the previous blog post is that we are using&#xA;QueueGauge(), which is a &lt;em&gt;paced metric&lt;/em&gt;, meaning that it flushes to the&#xA;time series only periodically (once per second by default) so as to&#xA;not overwhelm the I/O and or network (even though in this case it doesn&amp;rsquo;t&#xA;really matter since we&amp;rsquo;re using a memory-based SerDe anyway).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why is there no Formal Definition of Time Series?</title>
      <link>https://grisha.org/blog/2016/12/23/time-series-what-is-it/</link>
      <pubDate>Fri, 23 Dec 2016 09:13:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/12/23/time-series-what-is-it/</guid>
      <description>&lt;p&gt;If you&amp;rsquo;re reading this, chances are you may have searched for&#xA;definition of &amp;ldquo;Time Series&amp;rdquo;. And, like me, you were probably&#xA;disappointed by what you&amp;rsquo;ve found.&lt;/p&gt;&#xA;&lt;p&gt;The most popular &amp;ldquo;definition&amp;rdquo; I come across amongst our fellow&#xA;programmer folk is that it&amp;rsquo;s &amp;ldquo;data points with timestamps&amp;rdquo;. Or something&#xA;like that. And you can make charts from it. And that&amp;rsquo;s about it, alas.&lt;/p&gt;&#xA;&lt;p&gt;The word &lt;em&gt;time&lt;/em&gt; suggests that is has something to do with time. At&#xA;first it seems reasonable, I bite. The word &lt;em&gt;series&lt;/em&gt; is a little more&#xA;peculiar. A mathematician would argue that a series is a &lt;a href=&#34;https://en.wikipedia.org/wiki/Series_(mathematics)&#34;&gt;&lt;em&gt;sum&lt;/em&gt; of a sequence&lt;/a&gt;.&#xA;Most people though think &amp;ldquo;series&amp;rdquo; and &amp;ldquo;sequence&amp;rdquo; are the&#xA;same thing, and that&amp;rsquo;s fine. But it&amp;rsquo;s a clue that &lt;em&gt;time series&lt;/em&gt; is&#xA;not a scientific term, because it would have been called&#xA;&lt;em&gt;time sequence&lt;/em&gt; most likely.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Simple Time Series App with Tgres</title>
      <link>https://grisha.org/blog/2016/12/21/simple-time-series-app-with-tgres/</link>
      <pubDate>Wed, 21 Dec 2016 19:55:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/12/21/simple-time-series-app-with-tgres/</guid>
      <description>&lt;p&gt;Did you know you can use &lt;a href=&#34;https://github.com/tgres/tgres&#34;&gt;Tgres&lt;/a&gt; components&#xA;in your code without PostgreSQL, and in&#xA;just a dozen lines of code instrument your program with a time&#xA;series. This example shows a complete server emulating Graphite API&#xA;which you can use with &lt;a href=&#34;http://grafana.org/&#34;&gt;Grafana&lt;/a&gt; (or any other tool).&lt;/p&gt;&#xA;&lt;p&gt;In this example we will be using three Tgres packages like so (in addition to&#xA;a few standard ones, I&amp;rsquo;m skipping them here for brevity - complete source code &lt;a href=&#34;https://gist.github.com/grisha/9561e7837cff1340b218054f36430187&#34;&gt;gist&lt;/a&gt;):&lt;/p&gt;</description>
    </item>
    <item>
      <title>Storing Time Series in PostgreSQL (Continued)</title>
      <link>https://grisha.org/blog/2016/12/16/storing-time-series-in-postgresql-part-ii/</link>
      <pubDate>Fri, 16 Dec 2016 19:35:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/12/16/storing-time-series-in-postgresql-part-ii/</guid>
      <description>&lt;p&gt;Edit: there is now a &lt;a href=&#34;https://grisha.org/blog/2017/01/21/storing-time-seris-in-postgresql-optimize-for-write&#34;&gt;part iii&lt;/a&gt; in this series of articles.&lt;/p&gt;&#xA;&lt;p&gt;I have &lt;a href=&#34;https://grisha.org/blog/2015/09/23/storing-time-series-in-postgresql-efficiently/&#34;&gt;previously written&lt;/a&gt; how&#xA;time series can be stored in PostgreSQL efficiently using &lt;a href=&#34;https://www.postgresql.org/docs/current/static/arrays.html&#34;&gt;arrays&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;As a continuation of that article, I shall attempt to describe in detail the inner workings of an&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/View_(SQL)&#34;&gt;SQL view&lt;/a&gt; that &lt;a href=&#34;https://github.com/tgres/tgres&#34;&gt;Tgres&lt;/a&gt; uses to&#xA;make an array of numbers appear as a regular table&#xA;(&lt;a href=&#34;https://github.com/tgres/tgres/blob/bc718e3999650b7aab934517179ea47632530d28/serde/postgres.go#L235-L242&#34;&gt;link to code&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;p&gt;In short, I will explain how incomprehensible data like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; ts;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; rra_id &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; n &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;           dp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;--------+---+------------------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;67&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;70&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;71&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;72&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;69&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;67&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;65&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;60&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;58&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;59&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;62&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;68&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;70&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;71&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;72&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;77&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;70&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;71&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;73&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;75&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;79&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;82&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;90&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;69&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;75&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;81&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip; can be transformed in an SQL view to appear as so:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Parsing Table Names from SQL</title>
      <link>https://grisha.org/blog/2016/11/14/table-names-from-sql/</link>
      <pubDate>Mon, 14 Nov 2016 14:40:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/11/14/table-names-from-sql/</guid>
      <description>&lt;p&gt;Sometimes it is useful to extract table names from an SQL statement,&#xA;for example if you are trying to figure out dependencies for your Hive&#xA;or BigQuery (or whatever) tables.&lt;/p&gt;&#xA;&lt;p&gt;It is actually a lot simpler than it seems and you don&amp;rsquo;t need to write&#xA;your own SQL parser or find one out there. In SQL table names always&#xA;follow the FROM and JOIN keywords. So all you have to do is split the&#xA;statemement into tokens, and scan the list for any mention of FROM or&#xA;JOIN and grab the next token.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Load testing Tgres</title>
      <link>https://grisha.org/blog/2016/11/08/load-testing-tgres/</link>
      <pubDate>Tue, 08 Nov 2016 14:41:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/11/08/load-testing-tgres/</guid>
      <description>&lt;p&gt;Edit: There is an &lt;a href=&#34;https://grisha.org/blog/2017/02/23/can-tgres-outperform-graphite/&#34;&gt;update&lt;/a&gt; to this story.&lt;/p&gt;&#xA;&lt;p&gt;So I finally got around to some load testing of &lt;a href=&#34;https://github.com/tgres/tgres&#34;&gt;Tgres&lt;/a&gt;. Load testing is&#xA;mysterious, it never goes the way you think it would, and what you&#xA;learn is completely unexpcted.&lt;/p&gt;&#xA;&lt;p&gt;Given that I presently don&amp;rsquo;t have any spare big iron at my disposal&#xA;and my &amp;ldquo;servers&amp;rdquo; are my macbook and an old thinkpad, all I really was&#xA;after is making sure that Tgres is &amp;ldquo;good enough&amp;rdquo; whatever that&#xA;means. And I think it is.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Golang receiver vs function argument</title>
      <link>https://grisha.org/blog/2016/09/22/golang-receiver-vs-function/</link>
      <pubDate>Thu, 22 Sep 2016 08:15:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/09/22/golang-receiver-vs-function/</guid>
      <description>&lt;p&gt;What is the difference between a Go &lt;em&gt;receiver&lt;/em&gt; (as in &amp;ldquo;method receiver&amp;rdquo;)&#xA;and a function &lt;em&gt;argument&lt;/em&gt;? Consider these two bits of code:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;d&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;duck&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;quack&lt;/span&gt;() { &lt;span style=&#34;color:#75715e&#34;&gt;// receiver&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#75715e&#34;&gt;// do something&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;versus&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;quack&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;d&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;duck&lt;/span&gt;) { &lt;span style=&#34;color:#75715e&#34;&gt;// funciton argument&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// do something&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &amp;ldquo;do something&amp;rdquo; part above would work exactly the same regardless of&#xA;how you declare the function. Which begs the question, which should&#xA;you use?&lt;/p&gt;&#xA;&lt;p&gt;In the object-oriented world we were used to objects doing things, and&#xA;in that context &lt;code&gt;d.quack()&lt;/code&gt; may seem more intuitive or familiar than&#xA;&lt;code&gt;quack(d)&lt;/code&gt; because it &amp;ldquo;reads better&amp;rdquo;. After all, one could argue that&#xA;the former is a duck quacking, but the latter reads like you&amp;rsquo;re&#xA;quacking a duck, and what does that even mean? I have learned that you&#xA;should not think this way in the Go universe, and here is why.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How Data Points Build Up</title>
      <link>https://grisha.org/blog/2016/08/04/data-points/</link>
      <pubDate>Thu, 04 Aug 2016 10:35:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/08/04/data-points/</guid>
      <description>&lt;p&gt;This silly SVG animation (animation not my strong suit) demonstrates&#xA;what happens when multiple Tgres data points arrive within the same&#xA;step (i.e. smallest time interval for this series, also known as PDP,&#xA;primary data point).&lt;/p&gt;&#xA;&lt;object data=&#34;/images/data_point.svg&#34; type=&#34;image/svg+xml&#34;&gt;&#xA;  You browser does not support SVG objects?&#xA;&lt;/object&gt;&#xA;&lt;h3 id=&#34;explanation&#34;&gt;Explanation&lt;/h3&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s say we have a series with a step of 100 seconds. We receive the&#xA;following data points, all within the 100 second interval of a&#xA;single step:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Introducing Tgres - A Time Series DB on top of PostgreSQL</title>
      <link>https://grisha.org/blog/2016/07/29/state-of-tgres-2016/</link>
      <pubDate>Fri, 29 Jul 2016 10:12:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/07/29/state-of-tgres-2016/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://github.com/tgres/tgres&#34;&gt;Tgres&lt;/a&gt; is a metrics collection and storage server, aka a time series&#xA;database. I&amp;rsquo;m not very comfortable with referring to it as a&#xA;&lt;em&gt;database&lt;/em&gt;, because at least in case of Tgres, the database is&#xA;actually PostgreSQL. But also &amp;ldquo;database&amp;rdquo; to me is in the same category&#xA;as &amp;ldquo;operating system&amp;rdquo; or &amp;ldquo;compiler&amp;rdquo;, a thing so advanced that only few&#xA;can claim to be it without appearing pretentious. But for the sake of&#xA;tautology avoidance, I might occasionally refer to Tgres as a TS&#xA;database.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Deploying a Golang app to AWS ECS with Terraform</title>
      <link>https://grisha.org/blog/2016/04/19/deploying-a-golang-app-to-aws-ecs-with-terraform/</link>
      <pubDate>Tue, 19 Apr 2016 10:53:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/04/19/deploying-a-golang-app-to-aws-ecs-with-terraform/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve put together a basic example of a &amp;ldquo;Hello World&amp;rdquo; Go program which&#xA;runs in Amazon AWS Elastic Compute Service (ECS), which allows running&#xA;applications in Docker containers and has the ability to scale on&#xA;demand.&lt;/p&gt;&#xA;&lt;p&gt;I initially wanted to write about the components of this system and&#xA;the tools you use to deploy your application, but soon realized that&#xA;this would make for an extremely long post, as the number of&#xA;components required for a simple &amp;ldquo;Hello World&amp;rdquo; is mind&#xA;boggling. However problematic it may seem, it&amp;rsquo;s par for the course,&#xA;this is what takes to run an application in our cloudy times.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Holt-Winters Forecasting for Dummies - Part III</title>
      <link>https://grisha.org/blog/2016/02/17/triple-exponential-smoothing-forecasting-part-iii/</link>
      <pubDate>Wed, 17 Feb 2016 10:39:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/02/17/triple-exponential-smoothing-forecasting-part-iii/</guid>
      <description>&lt;p&gt;If you haven&amp;rsquo;t read &lt;a href=&#34;https://grisha.org/blog/2016/01/29/triple-exponential-smoothing-forecasting/&#34;&gt;Part I&lt;/a&gt; and&#xA;&lt;a href=&#34;https://grisha.org/blog/2016/02/16/triple-exponential-smoothing-forecasting-part-ii/&#34;&gt;Part II&lt;/a&gt;&#xA;you probably should, or the following will be hard to make sense of.&lt;/p&gt;&#xA;&lt;p&gt;In Part I we&amp;rsquo;ve learned how to forceast one point, in Part II we&amp;rsquo;ve&#xA;learned how to forecast two points. In this part we&amp;rsquo;ll learn how to&#xA;forecast &lt;em&gt;many&lt;/em&gt; points.&lt;/p&gt;&#xA;&lt;h2 id=&#34;more-terminology&#34;&gt;More Terminology&lt;/h2&gt;&#xA;&lt;h3 id=&#34;season&#34;&gt;&lt;em&gt;Season&lt;/em&gt;&lt;/h3&gt;&#xA;&lt;p&gt;If a series appears to be repetitive at regular intervals, such an&#xA;interval is referred to as a &lt;em&gt;season&lt;/em&gt;, and the series is said to be&#xA;&lt;em&gt;seasonal&lt;/em&gt;. &lt;a href=&#34;https://en.wikipedia.org/wiki/Seasonality&#34;&gt;Seasonality&lt;/a&gt;&#xA;is required for the Holt-Winters method to work, non-seasonal series&#xA;(e.g. stock prices) cannot be forecasted using this method (would be&#xA;nice though if they could be).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Holt-Winters Forecasting for Dummies - Part II</title>
      <link>https://grisha.org/blog/2016/02/16/triple-exponential-smoothing-forecasting-part-ii/</link>
      <pubDate>Tue, 16 Feb 2016 13:05:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/02/16/triple-exponential-smoothing-forecasting-part-ii/</guid>
      <description>&lt;p&gt;If you haven&amp;rsquo;t read &lt;a href=&#34;https://grisha.org/blog/2016/01/29/triple-exponential-smoothing-forecasting/&#34;&gt;Part I&lt;/a&gt;&#xA;you probably should, or the following will be hard to make sense of.&lt;/p&gt;&#xA;&lt;p&gt;All the forecasting methods we covered so far, including single&#xA;exponential smoothing, were only good at predicting a single&#xA;point. We can do better than that, but first we need to be introduced to&#xA;a couple of new terms.&lt;/p&gt;&#xA;&lt;h2 id=&#34;more-terminology&#34;&gt;More terminology&lt;/h2&gt;&#xA;&lt;h3 id=&#34;level&#34;&gt;&lt;em&gt;Level&lt;/em&gt;&lt;/h3&gt;&#xA;&lt;p&gt;Expected value has another name, which, again varies depending on who wrote the&#xA;text book: &lt;em&gt;baseline&lt;/em&gt;, &lt;em&gt;intercept&lt;/em&gt; (as in&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Y-intercept&#34;&gt;Y-intercept&lt;/a&gt;) or&#xA;&lt;em&gt;level&lt;/em&gt;. We will stick with &amp;ldquo;level&amp;rdquo; here.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Holt-Winters Forecasting for Dummies (or Developers) - Part I</title>
      <link>https://grisha.org/blog/2016/01/29/triple-exponential-smoothing-forecasting/</link>
      <pubDate>Fri, 29 Jan 2016 15:36:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2016/01/29/triple-exponential-smoothing-forecasting/</guid>
      <description>&lt;p&gt;This three part write up [&lt;a href=&#34;https://grisha.org/blog/2016/02/16/triple-exponential-smoothing-forecasting-part-ii/&#34;&gt;Part II&lt;/a&gt;&#xA;&lt;a href=&#34;https://grisha.org/blog/2016/02/17/triple-exponential-smoothing-forecasting-part-iii/&#34;&gt;Part III&lt;/a&gt;]&#xA;is my attempt at a down-to-earth explanation (and Python code) of the&#xA;Holt-Winters method for those of us who while hypothetically might be&#xA;quite good at math, still try to avoid it at every opportunity. I had&#xA;to dive into this subject while tinkering on&#xA;&lt;a href=&#34;https://github.com/tgres/tgres&#34;&gt;tgres&lt;/a&gt; (which features a Golang implementation). And&#xA;having found it somewhat complex (and yet so brilliantly&#xA;simple), figured that it&amp;rsquo;d be good to share this knowledge, and&#xA;in the process, to hopefully solidify it in my head as well.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Storing Time Series in PostgreSQL efficiently</title>
      <link>https://grisha.org/blog/2015/09/23/storing-time-series-in-postgresql-efficiently/</link>
      <pubDate>Wed, 23 Sep 2015 22:01:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2015/09/23/storing-time-series-in-postgresql-efficiently/</guid>
      <description>&lt;p&gt;With the latest advances in PostgreSQL (and other db&amp;rsquo;s), a relational&#xA;database begins to look like a very viable TS storage platform. In&#xA;this write up I attempt to show how to store TS in PostgreSQL. (2016-12-17 Update:&#xA;there is a &lt;a href=&#34;https://grisha.org/blog/2016/12/16/storing-time-series-in-postgresql-part-ii/&#34;&gt;part 2&lt;/a&gt; of this article.)&lt;/p&gt;&#xA;&lt;p&gt;A TS is a series of [timestamp, measurement] pairs, where measurement&#xA;is typically a floating point number. These pairs (aka &amp;ldquo;data points&amp;rdquo;)&#xA;usually arrive at a high and steady rate. As time goes on, detailed&#xA;data usually becomes less interesting and is often consolidated into&#xA;larger time intervals until ultimately it is expired.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Time Series Accuracy - Graphite vs RRDTool</title>
      <link>https://grisha.org/blog/2015/05/04/recording-time-series/</link>
      <pubDate>Mon, 04 May 2015 17:40:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2015/05/04/recording-time-series/</guid>
      <description>&lt;p&gt;Back in my ISP days, we used data stored in RRDs to bill our&#xA;customers. I wouldn&amp;rsquo;t try this with Graphite. In this write up I try&#xA;to explain why it is so by comparing the method of recording time series&#xA;used by&#xA;&lt;a href=&#34;http://graphite.readthedocs.org/en/latest/overview.html&#34;&gt;Graphite&lt;/a&gt;,&#xA;with the one used by &lt;a href=&#34;https://oss.oetiker.ch/rrdtool/&#34;&gt;RRDTool&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Graphite uses&#xA;&lt;a href=&#34;http://graphite.wikidot.com/whisper&#34;&gt;Whisper&lt;/a&gt; to store data, which in&#xA;the FAQ is portrayed as a &lt;a href=&#34;http://graphite.wikidot.com/whisper#toc1&#34;&gt;better alternative&lt;/a&gt; to RRDTool, but&#xA;this is potentially misleading, because the flexibility afforded by the&#xA;design of Whisper comes at the price of inaccuracy.&lt;/p&gt;</description>
    </item>
    <item>
      <title>On Time Series</title>
      <link>https://grisha.org/blog/2015/03/28/on-time-series/</link>
      <pubDate>Sat, 28 Mar 2015 15:40:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2015/03/28/on-time-series/</guid>
      <description>&lt;h2 id=&#34;is-it-even-a-thing&#34;&gt;Is it even a thing?&lt;/h2&gt;&#xA;&lt;p&gt;Time Series is on its way to becoming a buzzword in the Information&#xA;Technology circles. This has to do with the looming Internet of Things&#xA;which shall cause the Great Reversal of Internet whereby upstream flow&#xA;of data produced by said Things is expected to exceed the downstream&#xA;flow. Much of this data is expected to be of the Time Series kind.&lt;/p&gt;&#xA;&lt;p&gt;This, of course, is a money-making opportunity of the Big Data&#xA;proportions all over again, and I predict we&amp;rsquo;re going to see a lot of&#xA;Time Series support of various shapes and forms appearing in all&#xA;manners of (mostly commercial) software.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How InfluxDB Stores Data</title>
      <link>https://grisha.org/blog/2015/03/20/influxdb-data/</link>
      <pubDate>Fri, 20 Mar 2015 15:52:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2015/03/20/influxdb-data/</guid>
      <description>&lt;p&gt;A nice, reliable, horizontally scalable database that is designed&#xA;specifically to tackle the problem of Time Series data (and does not&#xA;require you to stand up a Hadoop cluster) is very much missing from the&#xA;Open Source Universe right now.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/influxdb/influxdb&#34;&gt;InfluxDB&lt;/a&gt; might be able to fill this gap, it certainly aims to.&lt;/p&gt;&#xA;&lt;p&gt;I was curious about how it structures and stores data and since there&#xA;wasn&amp;rsquo;t much documentation on the subject and I ended up just reading&#xA;the code, I figured I&amp;rsquo;d write this up. I only looked at the new&#xA;(currently 0.9.0 in RC stage) version, the previous versions are&#xA;significantly different.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Ruby, HiveServer2 and Kerberos</title>
      <link>https://grisha.org/blog/2014/08/19/ruby_hiveserver2_and_kerberos/</link>
      <pubDate>Tue, 19 Aug 2014 08:03:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2014/08/19/ruby_hiveserver2_and_kerberos/</guid>
      <description>&lt;p&gt;Recently I found myself needing to connect to HiveServer2 with&#xA;Kerberos authentication enabled from a Ruby app. As it turned out&#xA;&lt;a href=&#34;https://github.com/forward3d/rbhive&#34;&gt;rbhive gem&lt;/a&gt; we were using did not have&#xA;support for Kerberos authentication. So I had to&#xA;&lt;a href=&#34;https://github.com/forward3d/rbhive/pull/23&#34;&gt;roll my own&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This post is to document the experience of figuring out the details of&#xA;a SASL/GSSAPI connection before it is lost forever in my neurons and synapses.&lt;/p&gt;&#xA;&lt;p&gt;First, the terminology. The authentication system that Hadoop uses is&#xA;&lt;em&gt;Kerberos&lt;/em&gt;. Note that &lt;a href=&#34;http://www.ietf.org/rfc/rfc4120.txt&#34;&gt;Kerberos&lt;/a&gt; is not a&#xA;network protocol. It describes the method by which&#xA;authentication happens, but not the format of how to send Kerberos&#xA;tickets and what not over the wire. For that, you need &lt;em&gt;SASL&lt;/em&gt; and&#xA;&lt;em&gt;GSSAPI&lt;/em&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Graceful restart in Golang</title>
      <link>https://grisha.org/blog/2014/06/03/graceful-restart-in-golang/</link>
      <pubDate>Tue, 03 Jun 2014 12:49:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2014/06/03/graceful-restart-in-golang/</guid>
      <description>&lt;p&gt;Update (Apr 2015): &lt;a href=&#34;https://github.com/fvbock&#34;&gt;Florian von Bock&lt;/a&gt; has&#xA;turned what is described in this article into a nice Go package called&#xA;&lt;a href=&#34;https://github.com/fvbock/endless&#34;&gt;endless&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you have a Golang HTTP service, chances are, you will need to restart it&#xA;on occasion to upgrade the binary or change some configuration. And if&#xA;you (like me) have been taking graceful restart for granted because&#xA;the webserver took care of it, you may find this recipe very handy&#xA;because with Golang you need to roll your own.&lt;/p&gt;</description>
    </item>
    <item>
      <title>mod_python performance part 2: high(er) concurrency</title>
      <link>https://grisha.org/blog/2013/11/07/mod-python-performance-revisited/</link>
      <pubDate>Thu, 07 Nov 2013 17:51:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/11/07/mod-python-performance-revisited/</guid>
      <description>&lt;h3 id=&#34;tldr&#34;&gt;Tl;dr&lt;/h3&gt;&#xA;&lt;p&gt;As is evident from the table below, mod_python &lt;a href=&#34;https://github.com/grisha/mod_python/tree/3.5.x&#34;&gt;3.5&lt;/a&gt;&#xA;(in pre-release testing as of this writing) is currently the fastest tool when it&#xA;comes to running Python in your web server, and second-fastest as a&#xA;WSGI container.&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34;&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th&gt;Server&lt;/th&gt;&#xA;    &lt;th&gt;Version&lt;/th&gt;&#xA;    &lt;th&gt;Req/s&lt;/th&gt;&#xA;    &lt;th&gt;% of httpd static&lt;/th&gt;&#xA;    &lt;th&gt;Notes&lt;/th&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th&gt;&lt;a href=&#34;https://bitbucket.org/yarosla/nxweb/wiki/Benchmarks&#34;&gt;nxweb&lt;/a&gt; static file&lt;/th&gt;&#xA;    &lt;td&gt;3.2.0-dev&lt;/td&gt;&#xA;    &lt;td&gt;512,767&lt;/td&gt;&#xA;    &lt;td&gt; 347.1 % &lt;/td&gt;&#xA;    &lt;td&gt;&#34;memcache&#34;:false. (626,270 if true)&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th&gt;&lt;a href=&#34;http://nginx.com/&#34;&gt;nginx&lt;/a&gt; static file&lt;/th&gt;&#xA;    &lt;td&gt;1.0.15&lt;/td&gt;&#xA;    &lt;td&gt;430,135&lt;/td&gt;&#xA;    &lt;td&gt; 291.1 %&lt;/td&gt;&#xA;    &lt;td&gt;stock CentOS 6.3 rpm&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th&gt;&lt;a href=&#34;http://httpd.apache.org/&#34;&gt;httpd&lt;/a&gt; static file&lt;/th&gt;&#xA;    &lt;td&gt;2.4.4, mpm_event&lt;/td&gt;&#xA;    &lt;td&gt;147,746&lt;/td&gt;&#xA;    &lt;td&gt; 100.0 % &lt;/td&gt;&#xA;    &lt;td&gt;&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th&gt;mod_python &lt;a href=&#34;http://modpython.org/live/current/doc-html/pythonapi.html#overview-of-a-request-handler&#34;&gt;handler&lt;/a&gt;&lt;/th&gt;&#xA;    &lt;td&gt;3.5, Python 2.7.5&lt;/td&gt;&#xA;    &lt;td&gt;125,139&lt;/td&gt;&#xA;    &lt;td&gt; 84.7 % &lt;/td&gt;&#xA;    &lt;td&gt;&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th&gt;&lt;a href=&#34;https://uwsgi-docs.readthedocs.org/en/latest/&#34;&gt;uWSGI&lt;/a&gt;&lt;/th&gt;&#xA;    &lt;td&gt;1.9.18.2&lt;/td&gt;&#xA;    &lt;td&gt;119,175&lt;/td&gt;&#xA;    &lt;td&gt; 80.7 % &lt;/td&gt;&#xA;    &lt;td&gt;-p 16 --threads 1&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th&gt;mod_python &lt;a href=&#34;http://modpython.org/live/current/doc-html/handlers.html#wsgi-handler&#34;&gt;wsgi&lt;/a&gt;&lt;/th&gt;&#xA;    &lt;td&gt;3.5, Python 2.7.5&lt;/td&gt;&#xA;    &lt;td&gt;87,304&lt;/td&gt;&#xA;    &lt;td&gt; 59.1 % &lt;/td&gt;&#xA;    &lt;td&gt;&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th&gt;&lt;a href=&#34;http://code.google.com/p/modwsgi/&#34;&gt;mod_wsgi&lt;/a&gt;&lt;/th&gt;&#xA;    &lt;td&gt;3.4&lt;/td&gt;&#xA;    &lt;td&gt;76,251&lt;/td&gt;&#xA;    &lt;td&gt; 51.6 % &lt;/td&gt;&#xA;    &lt;td&gt;embedded mode&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th&gt;nxweb wsgi&lt;/th&gt;&#xA;    &lt;td&gt;3.2.0-dev, Python 2.7.5&lt;/td&gt;&#xA;    &lt;td&gt;15,141&lt;/td&gt;&#xA;    &lt;td&gt; 10.2 % &lt;/td&gt;&#xA;    &lt;td&gt;posibly misconfigured?&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;the-point-of-this-test&#34;&gt;The point of this test&lt;/h2&gt;&#xA;&lt;p&gt;I wanted to see how mod_python compares to other tools of similar&#xA;purpose on high-end hardware and with relatively high concurrency. As&#xA;I&amp;rsquo;ve &lt;a href=&#34;http://grisha.org/blog/2013/10/10/mod-python-performance/&#34;&gt;written before&lt;/a&gt;&#xA;you&amp;rsquo;d be foolish to base your platform decision on these numbers&#xA;because speed in this case matters very little. So the point of this&#xA;is just make sure that mod_python is in the ballpark with the rest and&#xA;that there isn&amp;rsquo;t anything seriously wrong with it. And surprisingly,&#xA;mod_python is actually pretty fast, &lt;em&gt;fastest&lt;/em&gt;, even, though in its own&#xA;category (a raw mod_python handler).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Separate Request and Response or a single Request object?</title>
      <link>https://grisha.org/blog/2013/10/30/separate-request-and-response-or-a-single-request-object/</link>
      <pubDate>Wed, 30 Oct 2013 13:18:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/10/30/separate-request-and-response-or-a-single-request-object/</guid>
      <description>&lt;p&gt;Are you in favor of a single request object, or two separate objects:&#xA;request and response?  Could it be that the two options are not&#xA;contradictory or even mutually exclusive?&lt;/p&gt;&#xA;&lt;p&gt;I thouhgt I always was in favor of a single request object which I&#xA;&lt;a href=&#34;https://mail.python.org/pipermail/web-sig/2003-October/000162.html&#34;&gt;expressed on the Web-SIG mailing list thread&lt;/a&gt;&#xA;dating back to October 2003 (ten years ago!). But it is only now that&#xA;I’ve come to realize that both proponents of a single object and two&#xA;separate objects were correct, they were just talking about different&#xA;things.&lt;/p&gt;</description>
    </item>
    <item>
      <title>My thoughts on WSGI</title>
      <link>https://grisha.org/blog/2013/10/26/my-thoughts-on-wsgi/</link>
      <pubDate>Sat, 26 Oct 2013 11:24:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/10/26/my-thoughts-on-wsgi/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m not very fond of it. Here is why.&lt;/p&gt;&#xA;&lt;h2 id=&#34;cgi-origins&#34;&gt;CGI Origins&lt;/h2&gt;&#xA;&lt;p&gt;WSGI is based on CGI, as the &amp;ldquo;GI&amp;rdquo; (Gateway Interface) suggests right&#xA;there in the name.&lt;/p&gt;&#xA;&lt;p&gt;CGI solved a very important problem using the very limited tools at&#xA;hand available at the time. Though CGI wasn&amp;rsquo;t a standard, it was&#xA;ubiquitous in the early days of the WWW, despite its inherent slowness&#xA;and other limitations. It became popular because it worked with any&#xA;language, was easy to turn on and provided such a thick wall of&#xA;isolation that admins could turn it on for their users without too much concern&#xA;for problems caused by user-generated CGI scripts.&lt;/p&gt;</description>
    </item>
    <item>
      <title>mod_python: the long story</title>
      <link>https://grisha.org/blog/2013/10/25/mod-python-the-long-story/</link>
      <pubDate>Fri, 25 Oct 2013 20:05:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/10/25/mod-python-the-long-story/</guid>
      <description>&lt;p&gt;This story started back in 1996. I was in my early twenties, working&#xA;as a programmer at a small company specializing in on-line reporting of&#xA;certain pharmaceutical data.&lt;/p&gt;&#xA;&lt;p&gt;There was a web-based application (which was extremely cool&#xA;considering how long ago this was), but unfortunately it was written&#xA;in Visual Basic by a contractor and I was determined to do something&#xA;about it. As was very fashionable at the time, I was very pro Open&#xA;Source, had Linux running on my home 386 and had recently heard&#xA;&lt;a href=&#34;http://boston-linux-unix-general-discussion-list.996279.n3.nabble.com/fwd-LOCAL-Washington-DC-Linux-User-Group-meeting-and-Python-talk-td3733.html&#34;&gt;Guido’s talk&lt;/a&gt;&#xA;at the DC Linux user group presenting his new language he called&#xA;Python. Python seemed like a perfect alternative to the VB&#xA;monstrosity.&lt;/p&gt;</description>
    </item>
    <item>
      <title>mod_python performance and why it matters not.</title>
      <link>https://grisha.org/blog/2013/10/10/mod-python-performance/</link>
      <pubDate>Thu, 10 Oct 2013 13:04:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/10/10/mod-python-performance/</guid>
      <description>&lt;p&gt;&lt;em&gt;TL;DR: mod_python is faster than you think.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;Tonight I thought I&amp;rsquo;d spend some time looking into how the new&#xA;&lt;a href=&#34;http://www.modpython.org/&#34;&gt;mod_python&lt;/a&gt;&#xA;fares against other frameworks of similar purpose. In this article I&#xA;am going to show the results of my findings, and then I will explain&#xA;&lt;em&gt;why it really does not matter&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I am particularly interested in the following:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;a pure mod_python handler, because this is as fast as mod_python gets.&lt;/li&gt;&#xA;&lt;li&gt;a mod_python wsgi app, because WSGI is so popular these days.&lt;/li&gt;&#xA;&lt;li&gt;mod_wsgi, because it too runs under Apache and is written entirely in C.&lt;/li&gt;&#xA;&lt;li&gt;uWSGI, because it claims to be super fast.&lt;/li&gt;&#xA;&lt;li&gt;Apache serving a static file (as a point of reference).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h1 id=&#34;the-test&#34;&gt;The Test&lt;/h1&gt;&#xA;&lt;p&gt;I am testing this on a CentOS instance running inside VirtualBox on an&#xA;early 2011 MacBook Pro. The VirtualBox has 2 CPU&amp;rsquo;s and 6GB of RAM&#xA;allocated to it. Granted this configuration can&amp;rsquo;t possibly be very&#xA;performant [if there is such a word], but it should be enough to&#xA;compare.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Running a WSGI app on Apache should not be this hard</title>
      <link>https://grisha.org/blog/2013/09/25/running-a-wsgi-app-on-apache-should-not-be-this-hard/</link>
      <pubDate>Wed, 25 Sep 2013 20:08:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/09/25/running-a-wsgi-app-on-apache-should-not-be-this-hard/</guid>
      <description>&lt;p&gt;If I have a Django app in &lt;code&gt;/home/grisha/mysite&lt;/code&gt;, then all I should&#xA;need to do to run it under Apache is:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ mod_python create /home/grisha/mysite_httpd &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    --listen&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;8888&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    --pythonpath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/home/grisha/mysite &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    --pythonhandler&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;mod_python.wsgi &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;    --pythonoption&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mod_python.wsgi.application mysite.wsgi::application&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ mod_python start /home/grisha/mysite_httpd/conf/httpd.conf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s all. There should be no need to become root, tweak various&#xA;configurations, place files in the right place, check permissions,&#xA;none of that.&lt;/p&gt;&#xA;&lt;p&gt;Well&amp;hellip; With &lt;a href=&#34;http://www.modpython.org/&#34;&gt;mod_python&lt;/a&gt; 3.4.0 (alpha)&#xA;that&amp;rsquo;s exactly how it is&amp;hellip;&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Next Smallest Step Problem</title>
      <link>https://grisha.org/blog/2013/08/10/the-next-smallest-step-problem/</link>
      <pubDate>Sat, 10 Aug 2013 15:10:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/08/10/the-next-smallest-step-problem/</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href=&#34;http://en.wiktionary.org/wiki/a_journey_of_a_thousand_miles_begins_with_a_single_step&#34;&gt;&amp;ldquo;A journey of a thousand miles begins with a single step&amp;rdquo;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;Most of my journeys never begin, or cannot continue because of that one&#xA;single step, be it first or next. Because it is hard, at times&#xA;excruciatingly so.&lt;/p&gt;&#xA;&lt;p&gt;Here I speak of software, but this applies to many other aspects of my&#xA;life just as well.&lt;/p&gt;&#xA;&lt;p&gt;I recon it&amp;rsquo;s because I do not think in steps. I think of a&#xA;destination.  I imagine the end-result. I can picture it with clarity&#xA;and in great detail. I know where I need to be. But what is the next&#xA;step to get there? And it doesn&amp;rsquo;t help that where I travel, there are&#xA;no signs.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hacking on mod_python (again)</title>
      <link>https://grisha.org/blog/2013/08/02/hacking-on-mod-python-again/</link>
      <pubDate>Fri, 02 Aug 2013 16:19:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/08/02/hacking-on-mod-python-again/</guid>
      <description>&lt;p&gt;Nearly eight years after my last &lt;a href=&#34;https://github.com/grisha/mod_python/commit/726e2697c0547dbbb4b09ce3348f76118bb911c4&#34;&gt;commit&lt;/a&gt;&#xA;to &lt;a href=&#34;http://www.modpython.org/&#34;&gt;Mod_python&lt;/a&gt; I&amp;rsquo;ve decided to spend some time hacking on it again.&lt;/p&gt;&#xA;&lt;p&gt;Five years without active development and thirteen since its first&#xA;release, it still seems to me an entirely useful and viable tool. The&#xA;code is exceptionally clean, the documentation is amazing, and the&#xA;test suite is awesome.  Which is a real testament to the noble efforts&#xA;of all the people who contributed to its development.&lt;/p&gt;</description>
    </item>
    <item>
      <title>json2avro</title>
      <link>https://grisha.org/blog/2013/06/21/on-converting-json-to-avro/</link>
      <pubDate>Fri, 21 Jun 2013 14:17:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/06/21/on-converting-json-to-avro/</guid>
      <description>&lt;p&gt;As you embark on converting vast quantities of JSON to Avro, you soon&#xA;discover that things are not as simple as they seem. Here is how it might happen.&lt;/p&gt;&#xA;&lt;p&gt;A quick Google&#xA;search eventually leads you to the&#xA;&lt;a href=&#34;http://www.us.apache.org/dist/avro/avro-1.7.4/java/avro-tools-1.7.4.jar&#34;&gt;avro-tools&lt;/a&gt;&#xA;jar, and you find yourself attempting to convert some JSON, such as:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;first&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;John&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;middle&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;X&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;last&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Doe&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;first&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Jane&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;last&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Doe&amp;#34;&lt;/span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Having read Avro documentation and being the clever being that you are, you start out with:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;java -jar ~/src/avro/java/avro-tools-1.7.4.jar fromjson input.json --schema &lt;span style=&#34;color:#ae81ff&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{&amp;#34;type&amp;#34;:&amp;#34;record&amp;#34;,&amp;#34;name&amp;#34;:&amp;#34;whatever&amp;#34;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;   &amp;#34;fields&amp;#34;:[{&amp;#34;name&amp;#34;:&amp;#34;first&amp;#34;, &amp;#34;type&amp;#34;:&amp;#34;string&amp;#34;},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             {&amp;#34;name&amp;#34;:&amp;#34;middle&amp;#34;,&amp;#34;type&amp;#34;:&amp;#34;string&amp;#34;},&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             {&amp;#34;name&amp;#34;:&amp;#34;last&amp;#34;,&amp;#34;type&amp;#34;:&amp;#34;string&amp;#34;}]}&amp;#39;&lt;/span&gt; &amp;gt; output.avro&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Exception in thread &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;main&amp;#34;&lt;/span&gt; org.apache.avro.AvroTypeException: Expected field name not found: middle&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        at org.apache.avro.io.JsonDecoder.doAction&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;JsonDecoder.java:477&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        at org.apache.avro.io.parsing.Parser.advance&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;Parser.java:88&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A brief moment of disappointment is followed by the bliss of&#xA;enlightment: Duh, the &amp;ldquo;middle&amp;rdquo; element needs a default! And so you try&#xA;again, this time having tacked on a default to the definition of &amp;ldquo;middle&amp;rdquo;, so it looks like &lt;code&gt;{&amp;quot;name&amp;quot;:&amp;quot;middle&amp;quot;,&amp;quot;type&amp;quot;:&amp;quot;string&amp;quot;,&amp;quot;default&amp;quot;:&amp;quot;&amp;quot;}&lt;/code&gt;:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Avro performance</title>
      <link>https://grisha.org/blog/2013/06/11/avro-performance/</link>
      <pubDate>Tue, 11 Jun 2013 00:17:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/06/11/avro-performance/</guid>
      <description>&lt;p&gt;Here are some un-scientific results on how Avro performs with various&#xA;codecs, as well as vs JSON-lzo files in Hive and Impala. This testing&#xA;was done using a 100 million row table that was generated using random&#xA;two strings and an integer.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| Format    | Codec          | Data Size     | Hive count(1) time | Impala count(1) time&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|-----------|----------------|---------------|--------------------|----------------------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| JSON      | null           | 686,769,821   | not tested         | N/A                  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| JSON      | LZO            | 285,558,314   | 79s                | N/A                  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| JSON      | Deflate (gzip) | 175,878,038   | not tested         | N/A                  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| Avro      | null           | 301,710,126   | 40s                | .4s                  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| Avro      | Snappy         | 260,450,980   | 38s                | .9s                  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| Avro      | Deflate (gzip) | 156,550,144   | 64s                | 2.8s                 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So the winner appears to be Avro/Snappy or uncompressed Avro.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Apache Avro</title>
      <link>https://grisha.org/blog/2013/06/06/avro/</link>
      <pubDate>Thu, 06 Jun 2013 22:53:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/06/06/avro/</guid>
      <description>&lt;h2 id=&#34;short-version&#34;&gt;Short version&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Avro is better than Json for storing table data&lt;/li&gt;&#xA;&lt;li&gt;Avro supports schema resolution so that the schema can evolve over time&lt;/li&gt;&#xA;&lt;li&gt;Hive supports Avro and schema resolution nicely&lt;/li&gt;&#xA;&lt;li&gt;Impala (1.0) can read Avro tables, but does &lt;em&gt;not&lt;/em&gt; support schema resolution&lt;/li&gt;&#xA;&lt;li&gt;Mixing compression codecs in the same table works in both Hive and Impala&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;the-tldr-version&#34;&gt;The TL;DR version&lt;/h2&gt;&#xA;&lt;h3 id=&#34;introduction&#34;&gt;Introduction&lt;/h3&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re logging data into Hadoop to be analyzed, chances are you&amp;rsquo;re&#xA;using JSON. JSON is great because it&amp;rsquo;s easy to generate in most any&#xA;language, it&amp;rsquo;s human-readable, it&amp;rsquo;s universally supported and&#xA;infinitely flexible.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Simple Solution to Password Reuse</title>
      <link>https://grisha.org/blog/2013/05/31/simple-solution-to-password-reuse/</link>
      <pubDate>Fri, 31 May 2013 17:12:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/05/31/simple-solution-to-password-reuse/</guid>
      <description>&lt;p&gt;&#xA;Here&#39;s a &lt;a href=&#34;http://en.wikipedia.org/wiki/KISS_principle&#34;&gt;KISS&lt;/a&gt; solution to all your password reuse&#xA;problems. It requires remembering only *one* strong password, lets you&#xA;have a virtually limitless number of passwords, and, most importantly,&#xA;does NOT store anything anywhere or transfer anything over the&#xA;network (100% browser-side Javascript).&#xA;&lt;/p&gt;&#xA;&lt;script type=&#34;text/javascript&#34; src=&#34;https://grisha.org/javascripts/sha.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script type=&#34;text/javascript&#34; src=&#34;https://grisha.org/javascripts/zxcvbn-async.js&#34;&gt;&lt;/script&gt;&#xA;&lt;script type=&#34;text/javascript&#34;&gt;&#xA;function calc_pw(n) {&#xA;  try {&#xA;    var pw_phrase = document.getElementById(&#34;pw_phrase&#34;);&#xA;    var keyword = document.getElementById(&#34;keyword&#34;+n);&#xA;    var pw = document.getElementById(&#34;pw&#34;+n);&#xA;    var strength = document.getElementById(&#34;strength&#34;);&#xA;    var hmacObj = new jsSHA(pw_phrase.value, &#34;TEXT&#34;);&#xA;    pw.value = hmacObj.getHMAC(keyword.value, &#34;TEXT&#34;, &#34;SHA-512&#34;, &#34;B64&#34;).substring(5,15);&#xA;    if (pw.value.search(&#39;!&#39;) === -1) pw.value = pw.value + &#39;!&#39;&#xA;    if (pw.value.search(/[0-9]/) === -1) pw.value = pw.value + &#39;0&#39;&#xA;  } catch(e) {&#xA;    pw.value = &#34;ERROR: &#34; + e;&#xA;  }&#xA;}&#xA;function pw_strength() {&#xA;    var pw_phrase = document.getElementById(&#34;pw_phrase&#34;);&#xA;    var score = zxcvbn(pw_phrase.value).score;&#xA;    if (score == &#39;0&#39;) {strength.value = &#39;Very Weak&#39;; strength.style.color = &#39;red&#39;; }&#xA;    else if (score == &#39;1&#39;) {strength.value = &#39;Weak&#39;; strength.style.color = &#39;red&#39;; }&#xA;    else if (score == &#39;2&#39;) {strength.value = &#39;So so&#39;; strength.style.color = &#39;orange&#39;; }&#xA;    else if (score == &#39;3&#39;) {strength.value = &#39;Okay&#39;; strength.style.color = &#39;blue&#39;; }&#xA;    else if (score == &#39;4&#39;) {strength.value = &#39;Strong&#39;; strength.style.color = &#39;green&#39;; }&#xA;    else strength.value = &#39;&#39;;&#xA;}&#xA;function check_pw2_same() {&#xA;  var pw_phrase = document.getElementById(&#34;pw_phrase&#34;);&#xA;  var pw_phrase2 = document.getElementById(&#34;pw_phrase2&#34;);&#xA;  var pw_same = document.getElementById(&#34;pw_same&#34;);&#xA;  if (pw_phrase.value === pw_phrase2.value)&#xA;    pw_same.value = &#39;Correct&#39;;&#xA;  else&#xA;    pw_same.value = &#39;Incorrect&#39;;&#xA;}&#xA;function clear_all() {&#xA;  document.getElementById(&#34;pw_phrase&#34;).value = &#39;&#39;;&#xA;  document.getElementById(&#34;pw_phrase2&#34;).value = &#39;&#39;;&#xA;  document.getElementById(&#34;strength&#34;).value = &#39;&#39;;&#xA;  document.getElementById(&#34;pw_same&#34;).value = &#39;&#39;;&#xA;  document.getElementById(&#34;keyword1&#34;).value = &#39;amazon&#39;;&#xA;  document.getElementById(&#34;keyword2&#34;).value = &#39;gmail&#39;;&#xA;  document.getElementById(&#34;keyword3&#34;).value = &#39;yahoo&#39;;&#xA;  document.getElementById(&#34;keyword4&#34;).value = &#39;foo&#39;;&#xA;  document.getElementById(&#34;keyword5&#34;).value = &#39;bar&#39;;&#xA;  document.getElementById(&#34;pw1&#34;).value = &#39;&#39;;&#xA;  document.getElementById(&#34;pw2&#34;).value = &#39;&#39;;&#xA;  document.getElementById(&#34;pw3&#34;).value = &#39;&#39;;&#xA;  document.getElementById(&#34;pw4&#34;).value = &#39;&#39;;&#xA;  document.getElementById(&#34;pw5&#34;).value = &#39;&#39;;&#xA;}&#xA;&lt;/script&gt;&#xA;&lt;form action=&#34;#&#34; method=&#34;get&#34;&gt;&#xA;&lt;fieldset style=&#34;margin: 3px 0px; border: 1px solid #000000; padding: 10px;&#34;&gt;&#xA;&lt;legend&gt;Stupid Simple Password Generator&lt;/legend&gt;&#xA;&lt;h3&gt;Step 1:&lt;/h3&gt;&#xA;&lt;p&gt;&#xA;Think of a phrase you will always remember. Keep typing until the text&#xA;on the right says &#34;strong&#34;. Punctuation, spaces, unusual words and&#xA;mixed case while not required, are generally a good idea. The most&#xA;important thing is that the script considers it &lt;span style=&#34;color: green; font-weight: bold;&#34;&gt;strong&lt;/span&gt;.&#xA;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Compiling Impala from Github</title>
      <link>https://grisha.org/blog/2013/05/31/compiling-impala-from-github/</link>
      <pubDate>Fri, 31 May 2013 10:48:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/05/31/compiling-impala-from-github/</guid>
      <description>&lt;p&gt;Apparently Impala has two versions of source code, one internal to&#xA;Cloudera, the other available on Github. I&amp;rsquo;m presuming that code gets&#xA;released to Github once undergone some level of internal scrutiny, but&#xA;I&amp;rsquo;ve not seen any documentation on how one could tie publically&#xA;available code to the official Impala (binary) release, currently 1.0.&lt;/p&gt;&#xA;&lt;p&gt;Anyway, I tried compiling the github code last night, and here are the&#xA;steps that worked for me.&lt;/p&gt;</description>
    </item>
    <item>
      <title>SQLite DB stored in a Redis hash</title>
      <link>https://grisha.org/blog/2013/05/29/sqlite-db-stored-in-a-redis-hash/</link>
      <pubDate>Wed, 29 May 2013 17:08:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/05/29/sqlite-db-stored-in-a-redis-hash/</guid>
      <description>&lt;p&gt;In a &lt;a href=&#34;https://grisha.org/blog/2013/05/11/relational-database-on-top-of-key-value-store-explained/&#34;&gt;recent post&lt;/a&gt;&#xA;I explained how a relational database could be backed by a key-value&#xA;store by virtue of B-Trees. This sounded great in theory, but I wanted&#xA;to see that it actually works. And so last night I wrote a&#xA;&lt;a href=&#34;https://github.com/grisha/thredis/commit/2beaee3a13f0dbe0c161470da04ef8af21d78fc9&#34;&gt;commit&lt;/a&gt; to&#xA;&lt;a href=&#34;http://thredis.org/&#34;&gt;Thredis&lt;/a&gt;, which does exactly that.&lt;/p&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re not familiar with Thredis - it&amp;rsquo;s something I hacked together&#xA;last Christmas. Thredis started out as threaded Redis, but eventually&#xA;evolved into SQLite + Redis. Thredis uses a separate file to save&#xA;SQLite data. But with this patch it&amp;rsquo;s no longer necessary - a SQLite&#xA;DB is entirely stored in a Redis Hash object.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Checking out Cloudera Impala</title>
      <link>https://grisha.org/blog/2013/05/23/checking-out-cloudera-impala/</link>
      <pubDate>Thu, 23 May 2013 12:43:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/05/23/checking-out-cloudera-impala/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve decided to check out&#xA;&lt;a href=&#34;http://blog.cloudera.com/blog/2012/10/cloudera-impala-real-time-queries-in-apache-hadoop-for-real/&#34;&gt;Impala&lt;/a&gt;&#xA;last week and here&amp;rsquo;s some notes on how that went.&lt;/p&gt;&#xA;&lt;h2 id=&#34;first-thoughts&#34;&gt;First thoughts&lt;/h2&gt;&#xA;&lt;p&gt;I was very impressed with how easy it was to install, even considering&#xA;our unusual set up (see below). In my simple ad-hoc tests Impala&#xA;performed orders of magnitude faster than Hive. So far it seems solid&#xA;down to the little details, like the shell prompt with a fully&#xA;functional libreadline and column headers nicely formatted.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Relational database on top of key-value store explained (or why B-trees are cool)</title>
      <link>https://grisha.org/blog/2013/05/11/relational-database-on-top-of-key-value-store-explained/</link>
      <pubDate>Sat, 11 May 2013 11:36:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/05/11/relational-database-on-top-of-key-value-store-explained/</guid>
      <description>&lt;p&gt;This post attempts to explain how a relational database can be&#xA;implemented atop a key/value store, a subject that I&amp;rsquo;ve long found&#xA;rather mysterious.&lt;/p&gt;&#xA;&lt;p&gt;Every once in a while I would come across a mention that a relational&#xA;database can be implemented using a key/value store (aka dictionary,&#xA;hash table or hash map - for brevity I&amp;rsquo;ll be using &lt;em&gt;map&lt;/em&gt; from here on).&lt;/p&gt;&#xA;&lt;p&gt;Whenever I thought about it, it just didn&amp;rsquo;t make sense. A relational&#xA;database needs to store rows &lt;em&gt;in order&lt;/em&gt;, and that&amp;rsquo;s one feature that&#xA;maps do not provide. Imagine we have a table keyed by employee id&#xA;stored in a map and we need to traverse it by id in ascending order. A&#xA;hypothetical keys() method would return us a list of ids ordered&#xA;randomly. It&amp;rsquo;s impossible to iterate over a hash map &lt;em&gt;in&#xA;order&lt;/em&gt;. So how would a relational database work then?&lt;/p&gt;</description>
    </item>
    <item>
      <title>MapJoin: a simple way to speed up your Hive queries</title>
      <link>https://grisha.org/blog/2013/04/19/mapjoin-a-simple-way-to-speed-up-your-hive-queries/</link>
      <pubDate>Fri, 19 Apr 2013 11:15:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/04/19/mapjoin-a-simple-way-to-speed-up-your-hive-queries/</guid>
      <description>&lt;p&gt;Mapjoin is a little-known feature of Hive. It allows a table to be&#xA;loaded into memory so that a (very fast) join could be performed&#xA;entirely within a mapper without having to use a Map/Reduce step. If&#xA;your queries frequently rely on small table joins (e.g. cities or&#xA;countries, etc.)  you might see a very substantial speed-up from using&#xA;mapjoins.&lt;/p&gt;&#xA;&lt;p&gt;There are two ways to enable it. First is by using a hint, which looks&#xA;like &lt;code&gt;/*+ MAPJOIN(aliasname), MAPJOIN(anothertable) */&lt;/code&gt;. This C-style comment&#xA;should be placed immediately following the &lt;code&gt;SELECT&lt;/code&gt;. It directs Hive&#xA;to load &lt;code&gt;aliasname&lt;/code&gt; (which is a table or alias of the query) into&#xA;memory.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linus on understanding pointers</title>
      <link>https://grisha.org/blog/2013/04/02/linus-on-understanding-pointers/</link>
      <pubDate>Tue, 02 Apr 2013 10:52:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/04/02/linus-on-understanding-pointers/</guid>
      <description>&lt;p&gt;A while back &lt;a href=&#34;http://en.wikipedia.org/wiki/Linus_Torvalds&#34;&gt;Linus Torvalds&lt;/a&gt; &lt;a href=&#34;http://meta.slashdot.org/story/12/10/11/0030249/linus-torvalds-answers-your-questions&#34;&gt;answered questions on Slashdot&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;One of the answers was on the subject of understanding of pointers:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;small&gt;At the opposite end of the spectrum, I actually wish more people&#xA;understood the really core low-level kind of coding. Not big, complex&#xA;stuff like the lockless name lookup, but simply good use of&#xA;pointers-to-pointers etc. For example, I&amp;rsquo;ve seen too many people who&#xA;delete a singly-linked list entry by keeping track of the &amp;ldquo;prev&amp;rdquo;&#xA;entry, and then to delete the entry, doing something like&lt;/small&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Storm Notes</title>
      <link>https://grisha.org/blog/2013/04/01/storm-notes/</link>
      <pubDate>Mon, 01 Apr 2013 17:05:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/04/01/storm-notes/</guid>
      <description>&lt;p&gt;Some random thoughts on having tinkered with&#xA;&lt;a href=&#34;http://storm-project.net/&#34;&gt;Storm&lt;/a&gt; over the past few weeks.&lt;/p&gt;&#xA;&lt;p&gt;It took me some time to understand what Storm is, and I am still not&#xA;clear I have found a perfect use for it. (This is not&#xA;a criticism of Storm, the point is that the concepts it introduces are&#xA;new, somewhat diffuclt and will need some time so sync in). The best way to get the basic&#xA;understanding of Storm concepts is to watch Nathan Marz&amp;rsquo;s &lt;a href=&#34;https://www.youtube.com/watch?v=bdps8tE0gYo&#34;&gt;excellent presentation&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>on prioritization - important vs urgent</title>
      <link>https://grisha.org/blog/2013/03/27/on-prioritization/</link>
      <pubDate>Wed, 27 Mar 2013 10:13:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/03/27/on-prioritization/</guid>
      <description>&lt;p&gt;Every item on a TODO list can be classified as &lt;em&gt;urgent&lt;/em&gt;, &lt;em&gt;important&lt;/em&gt;&#xA;or &lt;em&gt;neither&lt;/em&gt;. We should act on important items first, urgent second and&#xA;ignore the rest.&lt;/p&gt;&#xA;&lt;p&gt;Sometimes an item lands on our TODO list described as extremely urgent&#xA;without any explanation of importance. In this case the important item&#xA;(and thus to be done &lt;em&gt;first&lt;/em&gt;) becomes &lt;em&gt;determining the importance of the&#xA;extremely urgent item in question&lt;/em&gt;, even if it means delaying it.&lt;/p&gt;</description>
    </item>
    <item>
      <title>On keeping lots of integers in memory</title>
      <link>https://grisha.org/blog/2013/03/25/on-keeping-lots-of-integers-in-memory/</link>
      <pubDate>Mon, 25 Mar 2013 22:09:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/03/25/on-keeping-lots-of-integers-in-memory/</guid>
      <description>&lt;p&gt;Once upon a time (over a year ago) I found myself needing to store large numbers of&#xA;integers in memory. The goal was to store a graph of all our&#xA;purchasers and items purchased, so that we could quickly identify&#xA;like-minded purchasers based on common purchases and make real-time&#xA;recommendations of the form &amp;ldquo;people like you also bought&amp;rdquo;. This&#xA;approach is commonly known as &lt;a href=&#34;http://en.wikipedia.org/wiki/Collaborative_filtering&#34;&gt;collaborative filtering&lt;/a&gt;,&#xA;and exactly how we did it would be a subject of some future post&#xA;(perhaps).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Testing out Octopress</title>
      <link>https://grisha.org/blog/2013/03/25/how-does-this-work/</link>
      <pubDate>Mon, 25 Mar 2013 11:46:00 +0000</pubDate>
      <guid>https://grisha.org/blog/2013/03/25/how-does-this-work/</guid>
      <description>&lt;p&gt;Thanks to &lt;a href=&#34;http://octopress.org&#34;&gt;Octopress&lt;/a&gt; and &lt;a href=&#34;http://github.com&#34;&gt;Github&lt;/a&gt; I blog&amp;hellip;.&lt;/p&gt;&#xA;&lt;p&gt;And I Tweet, too?&lt;/p&gt;&#xA;&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p&gt;Thanks to Octopress and Github pages I now have a blog: &lt;a href=&#34;http://t.co/yKm0TVRMMu&#34; title=&#34;http://grisha.org/&#34;&gt;grisha.org&lt;/a&gt;&lt;/p&gt;&amp;mdash; Grisha Trubetskoy (@humblehack) &lt;a href=&#34;https://twitter.com/humblehack/status/316339220371349508&#34;&gt;March 26, 2013&lt;/a&gt;&lt;/blockquote&gt;&#xA;&lt;script async src=&#34;//platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;&#xA;&lt;p&gt;&#xA;&lt;a href=&#34;https://www.youtube.com/channel/UCPL5zsiUm0Psny8xD3mK1pg&#34;&gt;A link to Gregory Trubetskoy videos&lt;/a&gt;&#xA;or &lt;a href=&#34;https://youtu.be/qFi8j3ebTng&#34;&gt;a particular video&lt;/a&gt;&#xA;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Archives</title>
      <link>https://grisha.org/archives/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://grisha.org/archives/</guid>
      <description></description>
    </item>
  </channel>
</rss>
