<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Betable Engineering on Medium]]></title>
        <description><![CDATA[Stories by Betable Engineering on Medium]]></description>
        <link>https://medium.com/@betable?source=rss-5d16cef0c1af------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*KCYw5_j4aeG3f0yd8glw1w.jpeg</url>
            <title>Stories by Betable Engineering on Medium</title>
            <link>https://medium.com/@betable?source=rss-5d16cef0c1af------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 20:12:19 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@betable/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Getting started with mdb_v8]]></title>
            <link>https://medium.com/@betable/getting-started-with-mdb-v8-5401c9c0e98f?source=rss-5d16cef0c1af------2</link>
            <guid isPermaLink="false">https://medium.com/p/5401c9c0e98f</guid>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[linux]]></category>
            <dc:creator><![CDATA[Betable Engineering]]></dc:creator>
            <pubDate>Sat, 06 Feb 2016 00:00:00 GMT</pubDate>
            <atom:updated>2016-02-11T20:31:11.241Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/724/0*edWKZUPHnGadvHGc.png" /></figure><p>Did you know you can inspect your node application’s memory without instrumenting your code ? It’s possible using a tool called mdb_v8. With mdb_v8 we can produce a core dump of a running node process, and then later inspect the memory at the time the core dump was generated. This leads to some powerful postmortem debugging capabilities.</p><p>In this post I’m going to walk you through setting up mdb_v8 locally so that you can inspect your node application’s memory. Recently I went through this exercise myself and realized there was no good guide to do so. I decided to document the process and post it here.</p><p>The steps were going work through are as follows:</p><ol><li>Generate a core dump of our running node application</li><li>Install a Solaris derivative in a VM</li><li>Install mdb_v8, and run it against the core dump</li></ol><p>Be aware that this guide assumes a couple things about your workflow. First, that you are using a version of node at 0.10 or greater. At the time of this writing, all previous versions are no longer supported. Second, that your node service is running on a system where gcore is available, such as linux.</p><p>A Solaris derivative is required to run mdb_v8. There are two post mortem debuggers that don’t require Solaris, but they aren’t as fully featured. These are <a href="https://github.com/indutny/llnode">llnode</a> and <a href="https://github.com/tjfontaine/lldb-v8">lldb_v8</a>. Alternatively, if instrumenting your code isn’t an issue you may want to look into <a href="https://github.com/bnoordhuis/node-heapdump">node-heapdump</a>.</p><h4>What is mdb_v8 anyways ?</h4><p>We can’t talk about mdb_v8 without first talking about mdb. mdb is a low-level debugger developed by Sun for the Solaris operating system. What makes it unique is that is extremely extensible. It is possible to extend the tool with custom modules (“dmods”) for different contexts. This is exactly what Joyent has done with their mdb_v8 module. The mdb_v8 module adds a new set of commands instrumented specifically for the v8 javascript engine and node.js. It includes commands that allow you to inspect the application state, javascript frames, and javascript objects on the heap at the time the core dump was generated.</p><p>It’s worth emphasizing here that mdb <em>only</em> works on Solaris derivatives. That is — it won’t run OS X, Windows, or Linux. More on this in a moment.</p><h3>Generating a core dump</h3><p>A core dump is a file which consists of the working memory of an application. It also typically contains some other metadata such as process registers. In linux generating a core dump of our node.js application manually is pretty straight forward. We just run the following command:</p><pre>gcore -o filename </pre><p>This will produce a core dump file.</p><p>You can also set up your node service to save a core dump when it crashes by using the — abort_on_uncaught_exception flag.</p><h3>Installing mdb_v8</h3><p>So mdb_v8 sounds great, right ? You will be able to inspect your application state, and find out where all of your sneaky memory leaks are hiding. Well, that’s true, but as I mentioned above mdb_v8 only works on Solaris.</p><p>Therefore, we will use VirtualBox to install a Solaris derivative (OmniOS).</p><h4>Setting up VirtualBox with OmniOS</h4><p>If you don’t already have VirtualBox installed, you can proceed to the downloads page to download the correct binary for your system and install it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/64/0*NRBAtx8oteo7Hd1A.png" /><figcaption><a href="https://www.virtualbox.org/wiki/Downloads">Download VirtualBox</a></figcaption></figure><p>After you’ve installed VirtualBox you will download a Solaris derivative. Here we will use OmniOS. Download the current/stable release under “From CD/iso”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/64/0*-Eut0699ry5OVLKH.png" /><figcaption><a href="http://omnios.omniti.com/wiki.php/Installation">Download OmniOS</a></figcaption></figure><p>Once you’ve downloaded the image you can move back over to VirtualBox.</p><p>Select “Oracle Solaris 11”, and continue with everything else as the default.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/441/0*ilPvDM34VyWBExOH.png" /></figure><p>Once the VM is running, start it up and choose the OmniOS image that you downloaded above.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/376/0*XOcjFZf0ChS0WfMQ.png" /></figure><p>Proceed through the installation process choosing your language, timezone, etc. Keep in mind that VirtualBox has a sandbox auto-resizing hard drive. It’s fine to install the image on the “whole disk”. You can also ignore any warnings about kvm: No hardware support.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/416/0*grBMbkL_CPo5DEvj.png" /></figure><p>After you’ve installed OmniOS, proceed to “Devices -&gt; Optical drives -&gt; Remove disk from virtual drive” in VirtualBox to unmount the disk. Finally, reboot the VM. You will be prompted to login once OmniOS starts up. The default login in OmniOS is root with no password.</p><h3>Utilizing mdb_v8</h3><p>If you’ve made it this far you should be staring at an empty shell. There are still a few remaining steps before we can begin using mdb_v8. Those steps are as follows:</p><ol><li>We need to be able to SSH into our VM from our local machine</li><li>We need to install the mdb_v8.so module for mdb</li><li>We need to SCP our core dump, and node.js binary to the virtual machine</li></ol><h4>SSHing into our VM</h4><p>The first issue is that our VM doesn’t have access to the local network. We need to enable this option in VirtualBox. We want to give our VM an internal IP that we can reach via SSH. We can do this by right clicking our VM in VirtualBox, and heading to the settings page. Here we will change our networking adapter from NAT to Bridged Adapter.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/386/0*H7DAK21-So6Xcwxg.png" /></figure><p>The next step is that we need to enable DHCP in OmniOS. This way our VM can be assigned an IP address on the network. We do that by using a tool called ipadm to create an IP interface.</p><pre># ipadm create-if e1000g0 # ipadm create-addr -T dhcp e1000g0/v4</pre><p>Now that we have created our IP interface we can configure our DNS resolution. Run these commands to add a nameserver.</p><pre># echo &#39;nameserver 8.8.8.8&#39; &gt;&gt; /etc/resolv.conf # cp /etc/nsswitch.dns /etc/nsswitch.conf</pre><p>Hurray. Now we have network connectivity. Now let’s get our new local IP on the network by running ifconfig.</p><pre># ifconfig e1000g0</pre><p>This will show us our local network IP address (directly after the inet).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/719/0*aTav6tYkAQKcJIal.png" /></figure><p>Even though we have the network IP address, we still won’t be able to SSH into the machine. Why ? Well because by default OmniOS (and many distributions) don’t allow you to SSH in as the root user. This is typically a security precaution. However, because we are just doing this to run mdb_v8 locally, we can enable this functionality.</p><p>To allow us to SSH in as root we can edit the sshd_config</p><pre># vim /etc/ssh/sshd_config</pre><p>and scroll down to the line that says PermitRootLogin no and change it to PermitRootLogin yes. After this we want to restart the SSH daemon.</p><pre># sudo svcadm restart SSH</pre><p>Now we should be able to SSH into our VM. Nice! On to the next step.</p><h3>Installing mdb_v8</h3><p>Luckily, OmniOS comes with mdb installed by default, but it does not come with the mdb_v8 module. We need to manually install this. To do this we can simply use curl to download the binary.</p><p>Let’s first create a working directory.</p><pre># mkdir ~/mdbv8 # cd ~/mdbv8</pre><p>You can first curl Joyent’s manta service to find the latest version of mdb_v8.</p><pre># curl <a href="https://us-east.manta.joyent.com/Joyent_Dev/public/mdb_v8/latest">https://us-east.manta.joyent.com/Joyent_Dev/public/mdb_v8/latest</a> | cut -c 27-</pre><p>Run the following command below (replace {version} below with version you got from the above curl i.e. “v1.1.2”)</p><pre># curl -O https://us-east.manta.joyent.com/Joyent_Dev/public/mdb_v8/{version}/mdb_v8_amd64.so</pre><p>Great. Now we have everything we need to run mdb_v8.</p><h3>Putting it all together</h3><p>The last and final step is to move over both our core dump file(s), and our node binary. (Don’t have a core dump file ? See the beginning of this post for a snippet of how to use gcore.)</p><p>What’s all this about a node binary ? Well, mdb_v8 will only work against the node binary that was running your node application at the time that the core dump was generated. You can download it directly from the node.js website provided you know the <em>exact</em> version and build. The easiest way is to simply grab the node binary off of the machine where you generated the core dump. Typically you can find the node binary by running which node, but if you’re using something like nvm it may require a little bit more digging.</p><p>Provided you have downloaded the node binary and your core dump on your local machine, you can now SCP these files onto your VM.</p><pre># scp ./node root@192.168.1.82:~/mdbv8 # scp ./my-dump.gcore root@192.168.1.82:~/mdbv8</pre><p>Now we can start the mdb_v8 debugger against our core dump and node binary.</p><pre># mdb ./node ./my-dump.gcore</pre><p>This will drop us into the mdb shell. All we need to do now is to load the mdb_v8 module by executing:</p><pre>::load /root/mdbv8/mdb_v8_amd64.so</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/64/0*K4B9QewB2t0k-mpf.png" /></figure><p>Now we can proceed to run any of the mdb_v8 commands against our core dump.</p><p>I like to start my mdb_v8 search by listing all js objects in memory. Try it yourself by typing.</p><pre>::findjsobjects</pre><p>For a list of useful mdb_v8 commands I recommend the official <a href="https://github.com/joyent/mdb_v8/blob/master/docs/usage.md">mdb_v8 usage guide</a>.</p><p>I also found <a href="https://gist.github.com/tjfontaine/9244374">this</a> gist by tjfontaine to be pretty helpful.</p><p>In this guide I’ve walked you through generating core dumps, installing solaris locally, and setting up mdb_v8. Hopefully you will find that mdb_v8 is a very useful node.js debugging tool to have in your back pocket for postmortem debugging. Good luck plugging all your leaks!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/64/0*J0iARccMGRbJp7B0.png" /></figure><p><em>Originally published at </em><a href="http://bryce.is/writing/code/mdb_v8/vm/virtualbox/omnios/2016/02/06/mdbv8-getting-started.html"><em>bryce.is</em></a><em> on February 6, 2016.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5401c9c0e98f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[TIFU by using Math.random()]]></title>
            <link>https://medium.com/@betable/tifu-by-using-math-random-f1c308c4fd9d?source=rss-5d16cef0c1af------2</link>
            <guid isPermaLink="false">https://medium.com/p/f1c308c4fd9d</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[computer-science]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Betable Engineering]]></dc:creator>
            <pubDate>Thu, 19 Nov 2015 18:38:00 GMT</pubDate>
            <atom:updated>2015-11-20T18:00:53.039Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<h4>By Betable CTO, Mike Malone</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*G2aXFFqqUane0d1Maw-fPw.png" /></figure><p><strong>Like most good TIFUs</strong> this didn’t happen today. It actually happened about two years ago. It is, however, still relevant. More significantly, it’s not just me who screwed up. <em>Math.random()</em> in the V8 Javascript engine is screwed up, too.</p><blockquote>“Many random number generators in use today are not very good. There is a tendency for people to avoid learning anything about such subroutines; quite often we find that some old method that is comparatively unsatisfactory has blindly been passed down from one programmer to another, and today’s users have no understanding of its limitations.”</blockquote><blockquote><em>— Donald Knuth; </em><a href="https://en.wikipedia.org/wiki/The_Art_of_Computer_Programming"><em>The Art of Computer Programming</em></a><em>, Volume 2.</em></blockquote><p>By the end of this post I’m hoping we’ll all agree on two things, one of which may be slightly more controversial than the other:</p><ul><li>We were stupid not to understand the limitations of V8’s PRNG before using it, and CSPRNGs are a safer option if you’re feeling lazy.</li><li>The implementation of <em>Math.random()</em> in V8 should be replaced. The current algorithm, which appears to have been passed down from one programmer to another, is comparatively unsatisfactory (and arguably completely broken) due to subtle, non-intuitive degenerate behavior that is likely to be encountered under realistic circumstances.</li></ul><p>For the record, I do want to say that I think V8 is a very impressive piece of software and the people who work on it are clearly very talented. This isn’t an indictment of any of them. Rather, it’s an illustration of how subtle some aspects of software development can be.</p><p>Now that we all know where we’re headed, let’s begin at the beginning.</p><p><a href="https://eng.betable.com/"><strong>Betable</strong></a><strong> is built on random numbers.</strong> Aside from other more obvious uses we like using randomly generated identifiers. Our architecture is distributed and microservice-y, and random identifiers are easier to implement than sequential identifiers in this sort of system.</p><p>For example, we generate random <em>request identifiers</em> whenever we receive an API request. We thread these identifiers through to sub-requests in headers, log them, and use them to collate and correlate all of the things that happened, across all of our services, as a result of a single request.</p><p>Generating random identifiers isn’t rocket science. There’s only one requirement —</p><blockquote>It must be really, really unlikely that the same identifier will ever be generated twice, causing a <strong><em>collision</em></strong>.</blockquote><p>And there are just two factors that impact the likelihood of a collision —</p><ol><li>The size of the <em>identifier space — </em>the number of unique identifiers that are possible</li><li>The method of <em>identifier generation — </em>how an identifier is selected from the space of all possible identifiers</li></ol><p>Ideally we want a big identifier space from which identifiers are selected at random from a uniform distribution (henceforth, we’ll assume that anything done “<em>at random” </em>uses a <em>uniform distribution</em>).</p><p>We did the <a href="https://en.wikipedia.org/wiki/Birthday_problem">birthday paradox</a> math and settled on making our request identifiers 22 character words with each character drawn from a 64 character alphabet. They look like <em>EB5iGydiUL0h4bRu1ZyRIi</em> or <em>HV2ZKGVJJklN0eH35IgNaB</em>. Each character in the word has 64 possible values, there are 22 characters, so there are 64²² such words. That makes the size of our identifier space 64²² or ~2¹³².</p><blockquote>With 2¹³² possible values, if identifiers were randomly generated at the rate of <strong><em>one million per second</em></strong> for the next <strong><em>300 years</em></strong> the chance of a collision would be roughly <strong><em>1 in six billion</em></strong>.</blockquote><p>So we’ve got a big enough identifier space, but how do we generate identifiers at random? The answer is a decent pseudo-random number generator (PRNG), a common feature of many standard libraries. The top of our API stack is a Node.js service (we also use a lot of <a href="https://golang.org/">Go</a>, but <a href="https://github.com/golang/go/blob/master/src/math/rand/rng.go">that’s</a> another blog post). Node.js, in turn, uses the V8 Javascript engine that Google built for its Chrome web browser. All compliant ECMAScript (Javascript) implementations must implement <em>Math.random()</em>,<em> </em>which<em> </em>takes no arguments and returns a random number between 0 and 1. Good start.</p><p>So, given a sequence of pseudo-random numbers between 0 and 1 we need to generate a random <em>word</em> with characters from our 64 character <em>alphabet</em>. This is a pretty common problem, here’s the pretty standard solution we chose —</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/05b05983875f053c4548f7dde7ddfe4d/href">https://medium.com/media/05b05983875f053c4548f7dde7ddfe4d/href</a></iframe><p>Before you start picking it apart, there’s nothing wrong with this code — it does exactly what it’s supposed to do.</p><p>We’re in business. A procedure for producing random identifiers that is <strong>extremely unlikely</strong> to produce a collision, even if we’re producing a million a second for 300 years. Test, commit, push, test, deploy.</p><p>The above code hit production and we forgot about it until a rather alarming email came through from a colleague, <a href="https://twitter.com/forte_nick">Nick Forte</a>, telling us that the impossible had happened —</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*urW__HeiLoVmMS1hlIrc_Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*02xH3GhW9l5zUfXLAqGaHQ.png" /></figure><p><strong>“Anyone who considers </strong>arithmetical methods of producing random digits is, of course, in a state of sin.” John von Neumann was stating the obvious here — it’s a simple tautology that <em>deterministic</em> methods, like arithmetic, cannot produce <em>random </em>bits. It’s a contradiction in terms. So <em>what is a PRNG?</em></p><h4>What is a PRNG?</h4><p>Let’s ground our discussion by looking at a <a href="https://gist.github.com/mmalone/6ef9fabe1a7540ae89e8">simple PRNG</a> and the “random numbers” it produces —</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_rpSUn6ekuZvXJnT5bWUbw.png" /></figure><p>This should make von Neumann’s point clear — the sequence of numbers generated by this algorithm is obviously not random. For most purposes, this non-randomness doesn’t really matter. What we <em>really </em>need is an algorithm that can generate a sequence of numbers that <em>appear</em> to be random (technically, they should appear to be independent and identically distributed random variables having a uniform distribution over the generator’s range). In layman’s terms, we should be able to <em>safely</em> <em>pretend</em> that the <em>pseudo</em>-random numbers are <em>truly </em>random numbers.</p><blockquote>If it’s hard to distinguish a generator’s output from truly random sequences we call it a <strong><em>high quality</em></strong> generator. If it’s easy, we call it a <strong><em>low quality</em></strong> generator.</blockquote><p>For the most part, quality is determined empirically by pulling a bunch of numbers from the generator and running some statistical tests for randomness (e.g., by checking that there are an equal number of 0 bits and 1 bits, figuring out how many collisions there are, doing a Monte-Carlo estimation of pi, etc). Another, more pragmatic measure of PRNG quality is how well the algorithm actually works in practice as a stand-in for truly random numbers.</p><p>Apart from its non-randomness, our simple algorithm demonstrates another important characteristic of all PRNGs. If you keep pulling numbers, it will eventually start repeating the same sequence over again. This is called periodicity, and all PRNGs are periodic.</p><blockquote>The <strong><em>period</em> </strong>or <strong><em>cycle length</em> </strong>of a PRNG is the length of the sequence of numbers that the PRNG generates before repeating.</blockquote><p>You can think of a PRNG as a highly compressed codebook containing a sequence of numbers. The kind a spy might use as a one-time pad. The <em>seed</em> is the starting position in the book. Eventually, you’ll loop around the end of the book and get back to where you started. That’s a cycle.</p><p>A long cycle length doesn’t guarantee high quality, but it helps. Often, cycle length can be guaranteed by mathematical proof. Even when we can’t calculate cycle length exactly, we can determine an upper bound. Since a PRNG’s next state and output are both deterministic functions of its current state, the cycle length cannot be larger than the number of possible states. To achieve this maximum cycle length the generator must enter every possible state before returning, again, to its current state.</p><blockquote>If a PRNG’s state has a <strong><em>k-bit</em></strong> representation, the cycle length is less than or equal to <strong><em>2ᵏ</em></strong>. A PRNG that actually achieves this maximum cycle length is called a <strong><em>full-cycle generator</em></strong><em>.</em></blockquote><p>Good PRNGs are designed so that their cycle length is close to this upper bound. Otherwise you’re wasting memory.</p><p>Let’s go one step further and analyze the number of <em>distinct random values </em>that a PRNG can produce through some deterministic transformation on its output. For instance, consider the problem of generating triples of random values between 0 and 15, like (2, 13, 4) or (5, 12, 15). There are 16³ or 4096 such triples, but our simple PRNG can only produce 16 of them.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W507OgBmWUfT-oqRAUuzQQ.png" /></figure><p>It turns out that this is another general characteristic of PRNGs —</p><blockquote>The number of <strong><em>distinct values</em></strong> that can be generated from a pseudo-random sequence is <strong><em>bounded by the sequence’s cycle length</em></strong>.</blockquote><p>The same holds regardless of the sort of value we’re producing — we can only produce 16 distinct tuples of four values (or any other length), 16 distinct array shuffles, 16 random fuzz test values, etc. We will always only be able to generate 16 distinct values of any type. Ever.</p><p>Remember our algorithm for producing random identifiers? We randomly generated words consisting of 22 characters drawn from a 64 character alphabet. In other words, we generated tuples of 22 numbers between 0 and 63. It’s the same problem, and the number of distinct identifiers we can produce is bounded by the size of the PRNG’s internal state, and its cycle length, in the same way.</p><h4>Math.random()</h4><p>Back to our problem. In response to Nick’s email about identifier collisions we quickly reviewed our birthday paradox math and checked our scaling code. We couldn’t find anything wrong, so the problem had to be deeper. Armed with our general knowledge of PRNGs, let’s start digging.</p><p>The <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-math.random">ECMAScript standard</a> says the following about <em>Math.random() —</em></p><blockquote>Returns a Number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly or pseudo randomly with approximately uniform distribution over that range, using an implementation-dependent algorithm or strategy.</blockquote><p>The specification leaves a lot to be desired. First, it doesn’t mention anything about precision. Since ECMAScript Numbers are IEEE 754 binary64 double-precision floats, we might expect 53-bit precision (i.e., random values taking the form <em>x/2⁵³ </em>for all<em> x </em>in<em> 0..2⁵³-1</em>). Mozilla’s SpiderMonkey engine <a href="http://mxr.mozilla.org/mozilla-central/source/js/src/jsmath.h#133">seems to agree</a> but, as we’ll soon find out, V8’s <em>Math.random()</em> only has 32-bit precision (i.e., values taking the form <em>x/2³² </em>for all<em> x </em>in<em> 0..2³²-1</em>). Good to know, but no matter, we only need six bits to produce a random letter from our 64 character alphabet.</p><p>What <em>does </em>matter for us is that the specification leaves the actual algorithm up to implementors. It has no minimum cycle length requirement, and is hand-wavy about the PRNG’s quality — the distribution just needs to be “approximately uniform.” To do our analysis we need to know what algorithm V8 uses. It’s nowhere to be found in any documentation, so let’s go to the source.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dpaeqFkE-kqW9SR6UOTZBw.png" /></figure><h3>The V8 PRNG</h3><p><strong>“Iwould have gone with mersenne twister </strong>since it is what everyone else uses (python, ruby, etc).” This short critique, left by <a href="http://www.deanmcnamee.com/about">Dean McNamee</a>, is the only substantive feedback on the <a href="https://codereview.chromium.org/126113">code review</a> of V8’s PRNG when it was <a href="https://github.com/v8/v8/commit/aa176ce815355f5c7e9d4b91e8f5627f12e7109b">first committed</a> on June 15, 2009. Dean’s recommendation is the same one I’ll eventually get around to making in this post.</p><p>V8’s PRNG code has been tweaked and moved around over the past six years. It <a href="https://github.com/v8/v8/blob/e40cde49b52ad795212699ac167db467993af0e0/src/v8.cc#L148-L159">used to be native code</a>, now it’s <a href="https://github.com/v8/v8/blob/b0e4dce6091a8777bda80d962df76525dc6c5ea9/src/js/math.js#L135-L144">in user-space</a>, but the algorithm has remained essentially the same. The actual implementation uses internal API and is a bit obfuscated, so let’s look at a more readable implementation of the same algorithm —</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4cd21891a4e407883f55da2022e486ff/href">https://medium.com/media/4cd21891a4e407883f55da2022e486ff/href</a></iframe><p>Well, that’s still pretty opaque, but let’s slog through.</p><p>There is one more clue. A comment in older versions of the V8 source stated simply: “random number generator using George Marsaglia’s MWC algorithm.” A few minutes with Google teaches the following —</p><ul><li><a href="https://en.wikipedia.org/wiki/George_Marsaglia">George Marsaglia</a> was a mathematician who spent much of his career studying PRNGs. He also created the original <a href="https://en.wikipedia.org/wiki/Diehard_tests">Diehard battery of statistical tests</a> for measuring the quality of a random number generator.</li><li>MWC stands for <a href="https://en.wikipedia.org/wiki/Multiply-with-carry">multiply-with-carry</a>, a class of PRNGs that <a href="http://digitalcommons.wayne.edu/cgi/viewcontent.cgi?article=1725&amp;context=jmasm">Marsaglia invented</a>. MWC generators are very similar to classic <a href="https://en.wikipedia.org/wiki/Linear_congruential_generator">linear congruential generators</a> (LCGs) like our simple example from earlier (in fact, there is a one-to-one correspondence between MWCs and LCGs, see section 3.6 of <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/handstat.pdf">this paper</a> for details). Their advantage over standard LCGs is that they can produce sequences with longer cycle lengths with about the same number of CPU cycles.</li></ul><p>So if you’re going to crib a PRNG off of someone, Marsaglia seems like a good choice, and MWC seems like a reasonable algorithm.</p><p>The V8 algorithm doesn’t look like a typical MWC generator though. It turns out that’s because the V8 algorithm is <em>not</em> an MWC generator. It’s <em>two</em> MWC sub-generators — one on line 5, the other on line 6 — combined to produce <em>one</em> random number on line 9. I’ll spare you the math, but each of the sub-generators have prime cycle lengths of about 2³⁰, making the combined cycle length of the generated sequence about 2⁶⁰.</p><p>If you’ll recall, we have 2¹³² possible identifiers, but now we know that V8’s <em>Math.random() </em>can only produce 2⁶⁰ of them. Still, assuming a uniform distribution, the probability of collision after randomly generating 100,000,000 identifiers should be less than 0.4%. We started seeing collisions after generating far fewer identifiers than that. Something must be wrong with our analysis. The cycle length estimate is provably correct, so we must not have a uniform distribution — there must be some <em>additional structure</em> to the sequence being generated.</p><h4>A Tale of Two Generators</h4><p>Before returning to the V8 PRNG, let’s look one more time at our random identifier generation code —</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/05b05983875f053c4548f7dde7ddfe4d/href">https://medium.com/media/05b05983875f053c4548f7dde7ddfe4d/href</a></iframe><p>The scaling method on line 6 is important. This is the method that <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random">MDN recommends</a> for scaling a random number, and it’s <a href="https://github.com/google/closure-library/blob/master/closure/goog/math/math.js#L25-L32">in</a> <a href="https://github.com/jashkenas/underscore/blob/98d3b2199c1e3b1853aa22e62188638e67f30d2f/underscore.js#L1398">widespread</a> <a href="https://github.com/mbostock/d3/wiki/Math">use</a> <a href="http://stackoverflow.com/questions/4959975/generate-random-value-between-two-numbers-in-javascript">in</a> <a href="http://www.w3schools.com/jsref/jsref_random.asp">the</a> <a href="http://blog.tompawlak.org/how-to-generate-random-values-nodejs-javascript">wild</a>. It’s called the <em>multiply-and-floor</em> method, because that’s what it does. It’s also called the <em>take-from-top </em>method, because the lower bits of the random number are truncated, leaving the left-most<em> </em>or <em>top </em>bits as our scaled integer result. (Quick note: it’s subtle, but in general this method is slightly <em>biased </em>if your scaled range doesn’t evenly divide your PRNG’s output range. A general solution should use rejection sampling <a href="https://gist.github.com/mmalone/d710793137ed0d6b8cb4">like this</a>, which is part of the standard library in <a href="https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/Random.java#L298-L311">other</a> <a href="https://github.com/python/cpython/blob/3.5/Lib/random.py#L241-L246">languages</a>.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eVfLsCK_TjmsAsX6tSYNSQ.png" /></figure><p>Do you see the problem yet? What’s weird about the V8 algorithm is how the two generators are mixed. It doesn’t <em>xor</em> the numbers from the two streams together. Instead, it simply concatenates the lower 16 bits of output from the two sub-generators. This turns out to be a critical flaw. When we multiply <em>Math.random() </em>by 64 and floor it we end up with the left-most, or top 6 bits of the number. <strong>These top 6 bits come exclusively from the first of the two MWC sub-generators.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nYpIwQOTZS83Lk2U1q9yAQ.png" /><figcaption>Bits from PRNG #1 are red, from PRNG #2 are blue.</figcaption></figure><p>If we analyze the first sub-generator independently we see that it has 32 bits of internal state. It’s not a full-cycle generator — its actual cycle length is about 590 million (18,030*2¹⁵-1, the math is tricky but it’s explained <a href="http://digitalcommons.wayne.edu/cgi/viewcontent.cgi?article=1725&amp;context=jmasm">here</a> and <a href="https://en.wikipedia.org/wiki/Multiply-with-carry#General_theory">here</a>, or you can just trust me). So we can only produce a <em>maximum </em>of 590 million distinct request identifiers with this generator. If they were randomly selected there would be a <strong>50% chance of collision</strong> after generating just <strong>30,000 identifiers</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W507OgBmWUfT-oqRAUuzQQ.png" /></figure><p>If that were true, we should have started seeing collisions almost immediately. To understand why we didn’t, recall our simple example where we pulled triples from a 4 bit LCG. Birthday paradox math doesn’t apply — for this application the sequence is nowhere near random, so we can’t <em>pretend</em> it is. It’s clear that we won’t produce a duplicate until the 17th triple. The same thing is happening with the V8 PRNG and our random identifiers — under certain conditions, the PRNG’s <em>lack of randomness </em>is making it <em>less likely </em>that we’ll see a collision.</p><p>In this case the generator’s determinism worked in our favor, but that’s not always true. The general lesson here is that, even for a high quality PRNG, you can’t assume a random distribution unless the generator’s cycle length is <em>much larger</em> than the number of random values you’re generating. A good general heuristic is —</p><blockquote>If you need to use <strong><em>n</em></strong> random values you need a PRNG with a cycle length of at least <strong><em>n²</em></strong>.</blockquote><p>The reason is that, within a PRNGs period, excessive regularity can cause poor performance on some important statistical tests (in particular, collision tests). To perform well, the sample size <em>n</em> must be proportional to the square root of the period length. Page 22 of <a href="http://www.iro.umontreal.ca/~lecuyer/papers.html">Pierre L’Ecuyer’s</a> excellent <a href="http://www.iro.umontreal.ca/~lecuyer/myftp/papers/handstat.pdf">chapter on random number generation</a> has more detail.</p><p>For a use case like ours, where we’re trying to generate unique values using multiple independent sequences from the same generator, we’re less concerned about statistical randomness and more concerned that the sequences not overlap. If we have <em>n</em> sequences of length <em>l </em>from a generator with period <em>p</em>, the probability of an overlap is <em>[1-(nl)/(p-1)]ⁿ⁻ ¹</em>, or approximately <em>ln²/p</em> for a big enough <em>p </em>(see <a href="http://xorshift.di.unimi.it/">here</a> and <a href="http://www.mathpages.com/home/kmath580/kmath580.htm">here</a> for details). The point is we need a long cycle length. Otherwise we’re making a mistake pretending our sequence is random.</p><p>Long story short, if you’re using <em>Math.random() </em>in V8 and you need a sequence of random numbers that’s reasonably high quality, you shouldn’t use more than about 24,000 numbers. If you’re generating multiple streams of any substantial size and don’t want any overlap, you shouldn’t use <em>Math.random()</em> at all.</p><p>If the algorithm that V8’s <em>Math.random()</em> uses is poor quality, you might be wondering how it was chosen at all. Let’s see if we can find out.</p><h4>A Brief History of MWC1616</h4><p><strong>“The MWC generator concatenates</strong> two 16-bit multiply-with-carry generators […] has period about 2⁶⁰ and seems to pass all tests of randomness. A favorite stand-alone generator — faster than KISS, which contains it.” That’s the extent of Marsaglia’s analysis of MWC1616, which is the name of the algorithm that powers V8’s <em>Math.random()</em>. If you take him at his word, the algorithm ticks the box for most of the important criteria you’d consider in choosing a PRNG.</p><p>MWC1616 was <a href="https://groups.google.com/forum/#!searchin/sci.stat.math/A$20random$20number$20generator$20for$20C./sci.stat.math/1kNyF8ixyqc/RHeuadKl0ocJ">first introduced</a> by Marsaglia in 1997 as a simple general purpose generator that, in his words, “seems to pass all tests of randomness put to it,” a comment that betrays Marsaglia’s largely empirical methodology. He seems to have trusted an algorithm if it passed his Diehard tests. Unfortunately, the Diehard tests he was using in the late 1990s weren’t that good, at least by today’s standards. If you run MWC1616 through a more modern empirical testing framework like <a href="http://simul.iro.umontreal.ca/testu01/tu01.html">TestU01&#39;s</a> SmallCrush it <a href="https://gist.github.com/mmalone/8b43c628c39cc39aa205">fails catastrophically</a> (it does even worse than the <a href="https://en.wikipedia.org/wiki/Lehmer_random_number_generator#Parameters_in_common_use">MINSTD generator</a>, which was outdated even in the 1990s, but Marsaglia’s Diehard tests probably didn’t have the granularity to tell him that).</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0945e05643cae1c2bad7c7db7d4ef9bd/href">https://medium.com/media/0945e05643cae1c2bad7c7db7d4ef9bd/href</a></iframe><p>As far as I know, there’s no mathematical basis for combining sub-generators the way MWC1616 does — concatenating subsets of the generated bits. It’s more typical to see bits from sub-generators <em>mixed</em> using some form of modulo arithmetic (e.g., addition modulo 2³², or <em>xor</em>). It appears that Marsaglia, himself, became aware of this deficiency shortly after posting MWC1616 on Usenet as a component of one version of his <a href="https://eprint.iacr.org/2011/007.pdf">KISS generator</a>. On January 12, 1999, Marsaglia posted <a href="https://groups.google.com/forum/#!msg/sci.stat.math/5yb0jwf1stw/ApaXM3IRy-0J">the version</a> of MWC1616 used in V8. Eight days later, on January 20, he posted a <a href="https://groups.google.com/forum/#!msg/sci.math.num-analysis/yoaCpGWKEk0/UXCxgufdTesJ">different version</a> of the algorithm. It’s subtle, but in the updated version, the upper bits of the second generator are not masked away, mixing bits from the two sequences more thoroughly.</p><p>Both versions of the algorithm appear in other places, adding to the confusion. The January 20 version of MWC1616 (i.e., the better version) is in <a href="http://numerical.recipes/">Numerical Recipes</a>, labeled <em>MWC with Base b = 2¹⁶</em>, under the heading <em>When You Have Only 32-Bit Arithmetic</em>, and only after first advising that, rather than implementing one of the algorithms listed, you should “get a better compiler!” Pretty discouraging words for an algorithm that’s <em>better</em> than what V8 has powering <em>Math.random()</em>. Rather inexplicably (because it’s so obscure) the January 20 version of MWC1616 is also given as an example computational method in Wikipedia’s <a href="https://en.wikipedia.org/wiki/Random_number_generation#Computational_methods">article on random number generation</a>. Implementations of the older January 12 version are included <a href="http://simul.iro.umontreal.ca/testu01/guideshorttestu01.pdf">in TestU01 twice</a>, once labeled MWC1616 and a second time labeled MWC97R. It’s also one of the generators available <a href="https://github.com/wch/r-source/blob/66e40c3ba1d7ebb78c84694fbd5780b452b52071/src/main/RNG.c#L118-L121">in R</a> (apparently it used to be the default).</p><p>So there are lots of places the algorithm can be found. It was obscure to me, but given the bona fides listed above I guess it’s not surprising it was chosen. Hopefully this article will serve as a warning, strengthening and confirming Knuth’s observation that kicked off this post —</p><ul><li>In general, PRNGs are subtle and you should do your own analysis and understand the limitations of any algorithm you’re implementing or using</li><li>Specifically, <strong>don’t use MWC1616</strong>, it’s not very good</li></ul><p>There are lots of better options. Let’s look at a couple of them.</p><h4>The CSPRNG Workaround</h4><p>To fix our identifier code we needed a replacement for <em>Math.random()</em> and we needed it fast. Lots of alternative PRNG implementations exist for Javascript, but we were looking for something that —</p><ul><li>Has a long enough period to generate all of our 2¹³² identifiers</li><li>Is well supported and battle tested</li></ul><p>Luckily, the Node.js standard library has another PRNG that meets both requirements: <a href="https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback"><em>crypto.randomBytes()</em></a><em>, </em>a <em>cryptographically secure </em>PRNG (CSPRNG) that calls OpenSSL’s <a href="https://github.com/nodejs/node/blob/7eee37257fe708ec23e8be292047320491ac8361/src/node_crypto.cc#L5107-L5108">RAND_bytes</a> (which, according to <a href="https://wiki.openssl.org/index.php/Manual:Rand%283%29">the docs</a>, produces a random number by generating the SHA-1 hash of 8184 bits of internal state, which it regularly reseeds from various entropy sources). If you’re in a web browser <a href="https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues"><em>crypto.getRandomValues()</em></a> should do the same job.</p><p>This isn’t a perfect general solution for three reasons —</p><ul><li>CSPRNGs almost always use non-linear transformations and are generally slower than non-cryptographic alternatives</li><li>Many CSPRNG systems are not seed-able, which makes it impossible to create a reproducible sequence of values (e.g., for testing)</li><li>CSPRNGs emphasize unpredictability over all other measures of quality, some of which might be more important for your use case</li></ul><p>However —</p><ul><li>Speed is relative, and CSPRNGs are fast enough for most use cases (I can get about 100MB/s of random data from <em>crypto.getRandomValues()</em> in Chrome on my machine)</li><li>In the limit, unpredictability implies an inability to distinguish the generator’s output from true randomness, which implies everything else we want out of a pseudo-random sequence</li><li>It’s likely that a generator advertised as “cryptographically secure” has been carefully code reviewed and subjected to many empirical tests of randomness</li></ul><p>We’re still making some assumptions, but they are evidence-based and pragmatic. If you’re unsure about the quality of your non-cryptographic alternatives, and unless you need deterministic seeding or require rigorous proofs of quality measures, <strong>using a CSPRNG is your best option.</strong> If you don’t trust your standard library’s CSPRNG (and you shouldn’t for cryptographic purposes) the right solution is to <a href="http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/"><strong>use urandom</strong></a>,<strong> </strong>which is managed by the kernel (Linux uses a scheme similar to OpenSSL’s, OS X uses Bruce Schneier’s <a href="https://www.schneier.com/yarrow.html">Yarrow</a> generator).</p><p>I can’t tell you the exact cycle length of <em>crypto.randomBytes()</em> because as far as I know there’s no closed form solution to that problem (i.e., no one knows). All I can say is that with a large state space and a continuous stream of new entropy coming in, it should be safe. If you trust OpenSSL to generate your public/private key pairs then it doesn’t make much sense not to trust it here. Empirically, once we swapped our call to <em>Math.random() </em>with a call to <em>crypto.randomBytes()</em> our collision problem went away.</p><p>In fact, Chrome could just have <em>Math.random()</em> call the same CSPRNG they’re using for <em>crypto.randomBytes()</em>, which appears to be <a href="http://trac.webkit.org/browser/trunk/Source/WTF/wtf/RandomNumber.cpp#L41">what Webkit is doing</a>. That said, there are lots of fast, high quality non-cryptographic alternatives, too. Let’s put a final nail in the MWC1616 coffin and take a look at some other options.</p><h4>V8’s PRNG is Comparatively Unsatisfactory</h4><p>My goal was to convince you that V8’s <em>Math.random()</em> is broken, and should be replaced. So far we’ve found obvious structural patterns in its output bits, catastrophic failure on empirical tests, and poor performance in the real world. If you still want more evidence, here are some pretty pictures that might sway you —</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*G2aXFFqqUane0d1Maw-fPw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dpaeqFkE-kqW9SR6UOTZBw.png" /><figcaption>Random noise from Safari (left) and V8 (right) generated in browser with <a href="http://bl.ocks.org/mmalone/bf59aa2e44c44dde78ac">this code.</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_TDu7UuDPZZWnT_Da2fm5w.png" /><figcaption>Monte-Carlo Estimate of PI after 10¹⁰ iterations using <a href="https://gist.github.com/mmalone/796d959dcf5b780106f4">this code</a>.</figcaption></figure><p>Hopefully you’ll agree at this point that V8’s <em>Math.random() </em>is<em> comparatively unsatisfactory </em>and should be fixed. The question is <em>how</em> should it be fixed? A one line patch would improve the bit-mixing, but I can’t see any reason to keep MWC1616 at all. There are better options.</p><p>A detailed comparison of the myriad existing methods for producing pseudo-random bits is going to have to wait for another post. Roughly, though, the requirements we’re looking for are —</p><ul><li>A large state space, and a large seed — ideally at least 1024 bits, since this will be an upper bound on other qualities of the generator. A state space of 2¹⁰²⁴ is enough for 99.9% of use cases, with a significant safety factor.</li><li>Speed, let’s make it at least as fast as the current implementation which produces around 25 million numbers per second on my machine.</li><li>Memory efficiency — we’ll probably need at least 256 bytes for a generator with 1024 bits of state in user-space Javascript (we can only use 32 bits per 64 bit Number), if that’s infeasible there are workarounds, but I’m going to assume we can afford this.</li><li>A very long period, a full cycle generator is great but anything over 2⁵⁰ should be sufficient to avoid cycling. Anything over 2¹⁰⁰ should let us safely pull 2⁵⁰ values while continuing to pretend we’ve got a random sequence.</li><li>At a minimum, passing marks on empirical tests of randomness like <a href="http://simul.iro.umontreal.ca/testu01/tu01.html">TestU01&#39;s</a> SmallCrush — extra credit for passing marks on BigCrush and good equidistribution (which, unfortunately, I don’t have room to explain). TestU01 is more rigorous than <a href="https://www.phy.duke.edu/~rgb/General/dieharder.php">Dieharder</a>, and I don’t know much about the <a href="http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html">NIST tests</a> or <a href="https://www.gnu.org/software/hurd/user/tlecarrour/rng-tools.html">rngtest</a>, but those might work too.</li></ul><p>There are many PRNG algorithms that meet or exceed these requirements. <a href="https://en.wikipedia.org/wiki/Xorshift">Xorshift</a> generators (also discovered by Marsaglia) are fast and do very well on statistical tests (much better than MWC1616). An xorshift variant called xorgens4096 has been <a href="https://github.com/davidbau/seedrandom/blob/released/lib/xor4096.js">implemented in Javascript</a> by <a href="http://davidbau.com/">David Bau</a>. It has a 4096-bit state space, a cycle length of ~2⁴⁰⁹⁶, and it <a href="http://jsperf.com/prng-performance/2">runs <em>faster</em></a> than MWC1616 in Chrome on my machine. Moreover, it has <em>no systematic failures</em> on BigCrush.</p><p>Recently it’s <a href="http://vigna.di.unimi.it/ftp/papers/xorshift.pdf">been shown</a> that taking the output of an xorshift generator and multiplying by a constant is a sufficient non-linear transformation for the generator to pass BigCrush. This class of generators, called xorshift*, is very fast, <a href="https://gist.github.com/mmalone/173e20becc755ebb2658">easy to implement</a>, and memory efficient. The xorshift1024* generator meets or exceeds all of our requirements. If the memory premium turns out to be a real problem, the xorshift64* generator has the same memory footprint, a longer cycle length, and is faster than MWC1616, beating it on all counts. Another new family of linear/non-linear hybrid generator called <a href="http://www.pcg-random.org/">PCG</a> claims similar performance and quality characteristics.</p><p>So there are lots of good algorithms to chose from. That said, the safest choice is probably a standard Mersenne Twister. The most popular variant, MT19937, was <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf">introduced</a> in the late 90s. Since then it’s become the <a href="https://en.wikipedia.org/wiki/Mersenne_Twister#Adoption_in_software_systems">standard generator in dozens of software packages</a>. It’s not perfect, but it has been battle tested and thoroughly analyzed. Its properties are well understood, and it does well on empirical tests. With an ostentatiously long cycle length of 2¹⁹⁹³⁷-1 it’s hard to misuse, but it does have an imposing 2KB state space and is criticized for its memory footprint and relatively poor performance. A quick search uncovered an existing <a href="https://gist.github.com/banksean/300494">Javascript implementation</a>, by <a href="http://www.dashdashverbose.com/">Sean McCullough</a>. Inexplicably, it’s as fast as the existing <em>Math.random() </em>implementation in Chrome on my machine.</p><p>So my advice is that V8 reconsider Dean McNamee’s comment from six years ago and use the Mersenne Twister algorithm. It’s fast enough, and robust enough to be safely used by developers who don’t have a deep understanding of how PRNGs work. A more exotic alternative is fine too. Just get rid of MWC1616, please!</p><h3>In Summary</h3><p>This was a long post, so let me re-cap the important bits —</p><ul><li>The PRNG algorithm behind V8’s <em>Math.random()</em> is called MWC1616. If you’re only using the most significant 16 bits it has a very short effective cycle length (less than 2³⁰). In general, it does poorly on empirical tests of quality. For most non-trivial use cases it’s not safe to pretend that it’s output is truly random. Be careful using it for anything you care about.</li><li>Cryptographically secure PRNGs are a better option if you don’t have time to do proper diligence on non-cryptographic alternatives. The safest option (and the right solution for crypto) is to <a href="http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/">use urandom</a>. In browser you can use <a href="https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues"><em>crypto.getRandomValues()</em></a><em>.</em></li><li>There are options for non-cryptographic PRNG algorithms that are faster and higher quality than MWC1616. V8 should replace its <em>Math.random()</em> implementation with one of them. There are no losers. Mersenne Twister (MT19937) is the most popular, and probably the safest choice.</li></ul><p>I’ll note, in passing, that <a href="http://mxr.mozilla.org/mozilla-central/source/js/src/jsmath.cpp#816">Mozilla’s use of the LCG</a> from Java’s util.Random package isn’t much better than MWC1616. So SpiderMonkey should probably go ahead and upgrade too.</p><p>In the meantime, the browser continues to be a confusing and dangerous place<em>. </em>Be safe out there!</p><p><em>Special thanks to </em><a href="https://twitter.com/forte_nick"><em>Nick Forte</em></a><em>, who discovered the collision bug in our production code, </em><a href="https://twitter.com/wadey"><em>Wade Simmons</em></a><em>, who originally tracked the problem down to V8’s </em>Math.random() <em>implementation, and the entire </em><a href="https://eng.betable.com/"><em>Betable Engineering team</em></a><em>, who put up with me ranting about random numbers for two weeks while I wrote this post.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f1c308c4fd9d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[3 Go Gotchas]]></title>
            <link>https://medium.com/@betable/3-go-gotchas-590b8c014e0a?source=rss-5d16cef0c1af------2</link>
            <guid isPermaLink="false">https://medium.com/p/590b8c014e0a</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[best-practices]]></category>
            <dc:creator><![CDATA[Betable Engineering]]></dc:creator>
            <pubDate>Thu, 05 Nov 2015 21:37:46 GMT</pubDate>
            <atom:updated>2015-11-05T21:37:46.376Z</atom:updated>
            <content:encoded><![CDATA[<p><em>Originally published by </em><a href="https://twitter.com/prettymuchbryce"><em>Bryce Neal</em></a><em> at </em><a href="http://bryce.is/writing/code/jekyll/update/2015/11/01/3-go-gotchas.html"><em>bryce.is</em></a><em> on November 1, 2015 and featured in the</em><a href="http://golangweekly.com/issues/83"><em> GoLang Newsletter issue 83</em></a><em> (with proper syntax highlighting).</em></p><p>Lately I’ve been doing more work in the <a href="https://golang.org/">Go</a> programming language. Today I thought I would share three “gotchas” that caught me off guard, or otherwise produced results that I would not have expected in my work with Go.</p><h4><strong>1. The range clause</strong></h4><p>The range clause is very convenient. It allows you to iterate over a slice or map while giving you a reference to the index and the value of each item. For example:</p><pre><strong>for</strong> index, value <strong>:=</strong> <strong>range</strong> mySlice {<br>    fmt<strong>.</strong>Println(&quot;index: &quot; <strong>+</strong> index)<br>    fmt<strong>.</strong>Println(&quot;value: &quot; <strong>+</strong> value)<br>}</pre><p>However, something notable is happening under the hood. Let’s see a more complex example:</p><pre><strong>type</strong> Foo <strong>struct</strong> {<br>    bar <strong>string</strong><br>}<br><br><strong>func</strong> main() {<br>    list <strong>:=</strong> []Foo{<br>        {&quot;A&quot;},<br>        {&quot;B&quot;},<br>        {&quot;C&quot;},<br>    }<br><br>    list2 <strong>:=</strong> make([]<strong>*</strong>Foo, len(list))<br>    <strong>for</strong> i, value <strong>:=</strong> <strong>range</strong> list {<br>        list2[i] <strong>=</strong> <strong>&amp;</strong>value<br>    }<br><br>    fmt<strong>.</strong>Println(list[0], list[1], list[2])<br>    fmt<strong>.</strong>Println(list2[0], list2[1], list2[2])<br>}</pre><p>In this example we are doing a few things.</p><ol><li>We are creating a slice of <strong>Foo</strong> structs called <em>list</em>.</li><li>We are defining a second slice of pointers to Foo structs called <em>list2</em>.</li><li>We iterate through each struct in <em>list</em> in order to assign its pointer to the corresponding index in <em>list2</em>.</li></ol><p>So therefore you might expect the output of the above code to be the following:</p><pre>{A} {B} {C}<br><strong>&amp;</strong>{A} <strong>&amp;</strong>{B} <strong>&amp;</strong>{C}</pre><p>However, this is not what is happening. Let’s take a look at the output of this code:</p><pre>{A} {B} {C}<br><strong>&amp;</strong>{C} <strong>&amp;</strong>{C} <strong>&amp;</strong>{C}</pre><p>The first line is as expected. These are the structs we initially created in <em>list</em>, but the second line is unexpected. It looks like we are printing out a pointer to the last struct in the list three times. But why is this happening ?</p><p>The culprit is the range clause.</p><pre><strong>for</strong> i, value <strong>:=</strong> <strong>range</strong> list {<br>    list2[i] <strong>=</strong> <strong>&amp;</strong>value<br>}</pre><p>Here’s the problem: <em>Go uses a copy of the value instead of the value itself within a range clause.</em> So when we take the pointer of <strong><em>value</em></strong>, we’re actually taking the pointer of a <strong>copy</strong> of the value. This copy gets reused throughout the range clause, which leaves our <em>list2</em> slice full of three references to the same pointer (the copy pointer).</p><p>According to the Go reference manual, “The iteration values are assigned to the respective iteration variables as in an assignment statement.” So effectively you can imagine the above range clause to be the same as writing:</p><pre><strong>var</strong> value Foo<br><strong>for</strong> <strong>var</strong> i <strong>:=</strong> 0; i <strong>&lt;</strong> len(list); i<strong>++</strong> {<br>    value <strong>=</strong> list[i]<br>    list2[i] <strong>=</strong> <strong>&amp;</strong>value<br>}</pre><p>In order to produce the output we expect, we should use the index to take a pointer to the actual value, instead of the copy.</p><pre><strong>for</strong> i, _ <strong>:=</strong> <strong>range</strong> list {<br>    list2[i] <strong>=</strong> <strong>&amp;</strong>list[i]<br>}</pre><h4>2. The append built-in function</h4><p>Slices are primitive types in Go. In other languages you might reach for an Array where in Go you would reach for a Slice. Here’s an example of how we might add a value to the end of an integer slice.</p><pre>list <strong>:=</strong> []<strong>int</strong>{0,1,2}<br>list <strong>=</strong> append(list, 3)<br>fmt<strong>.</strong>Println(list) <em>// [0 1 2 3]</em></pre><p>On the surface it seems to be similar to a <strong>push()</strong> array method, but slices are not quite arrays, and the built-in append function surprised me with its behavior under the hood. Have a look at the example below:</p><pre><strong>func</strong> main() {<br>    a <strong>:=</strong> []<strong>byte</strong>(&quot;foo&quot;)<br>    b <strong>:=</strong> append(a, []<strong>byte</strong>(&quot;bar&quot;)<strong>...</strong>)<br>    c <strong>:=</strong> append(a, []<strong>byte</strong>(&quot;baz&quot;)<strong>...</strong>)<br>        <br>    fmt<strong>.</strong>Println(<strong>string</strong>(a), <strong>string</strong>(b), <strong>string</strong>(c))<br>}</pre><p>In this example we define a slice a of bytes with an initial value of <strong>[“foo”]</strong>. Next we append another slice <strong>[“bar”]</strong> to our initial slice <strong>a</strong>, and again we append another slice <strong>[“baz”]</strong> to our initial slice <strong>a</strong>. The output of the above snippet is:</p><pre>foofoobazfoobaz</pre><p>Whaaat? :) Shouldn’t it be <strong>foo foobar foobaz</strong> ?</p><p>In order to understand what’s going on here we have to understand what a slice really is. A slice is a descriptor which consists of three components:</p><ol><li>A pointer to an underlying array — that is, one allocated by Go which you don’t have direct access to.</li><li>The capacity of said underlying array.</li><li>The effective length of the slice.</li></ol><blockquote>So what’s really happening ? Go will reuse the same underlying array in <strong><em>append()</em></strong> if it can do so without resizing the underlying array.</blockquote><p>So all three of these structs are referencing the exact same array in memory. The only practical difference is their length value which in the case of <strong>a</strong> is <strong>3</strong>, and in the case of <strong>b</strong> and <strong>c</strong> is <strong>6</strong>.</p><p>Keep in mind, Go will only reuse the same underlying array if the length of the newly created slice is less than or equal to the capacity of the initial slice.</p><p>It’s important to understand what is happening under the hood when using some of the built-in slice functions. For more info, Robe Pike wrote a very helpful <a href="https://blog.golang.org/slices">blog post</a> which goes into a lot of useful details around slices.</p><h4>3. Variable shadowing</h4><p>When people first look at Go code for the first time, one of the first things they ask is <em>“What is that := operator for?”</em>. Well, as you know, it’s a shorthand variable declaration operator. It’s used for both declaring and setting the value of a variable. The type is implicitly declared. This is very convenient, but can lead to some problems if you aren’t careful. Specifically I’m talking about variable shadowing. This is something that has bitten me in particular, because I have been programming almost exclusively in es5 javascript for the last two years where there is no block-level scoping.</p><p>Check this out:</p><pre><strong>func</strong> main() {<br>    list <strong>:=</strong> []<strong>string</strong>{&quot;a&quot;, &quot;b&quot;, &quot;c&quot;}<br>    <strong>for</strong> {<br>        list, err <strong>:=</strong> repeat(list)<br>        <strong>if</strong> err <strong>!=</strong> nil {<br>            panic(err)<br>        }<br>        fmt<strong>.</strong>Println(list)<br>        <strong>break</strong><br>    }<br>    fmt<strong>.</strong>Println(list)<br>}<br><br><strong>func</strong> repeat(list []<strong>string</strong>) ([]<strong>string</strong>, <strong>error</strong>) {<br>    <strong>if</strong> len(list) <strong>==</strong> 0 {<br>        <strong>return</strong> nil, errors<strong>.</strong>New(&quot;Nothing to repeat!&quot;)<br>    }<br>    list <strong>=</strong> append(list, list<strong>...</strong>)<br>    <strong>return</strong> list, nil<br>}</pre><p>This is somewhat of a contrived example, so bear with me because I think it illustrates the point well. The run down of this snippet is as follows:</p><ol><li>We create a slice of strings, <strong>list</strong>.</li><li>We enter a for loop.</li><li>The for loop calls a function <strong>repeat()</strong> which returns a new slice, and an error.</li><li>We break out of the for loop, and we print the value of <strong>list</strong>.</li></ol><p>You might expect the output here to be:</p><pre>[a b c a b c]<br>[a b c a b c]</pre><p>but in fact, it is:</p><pre>[a b c a b c]<br>[a b c]</pre><p>Because we use the shorthand variable declaration operator, we are actually redeclaring the <strong>list</strong> variable inside of the scope of the for loop. This is awkward, because the second variable <strong>err</strong> <em>is</em> a new variable which we want to declare. We can fix this by changing the first few lines within the for block to:</p><pre><strong>var</strong> err <strong>error</strong><br>list, err <strong>=</strong> duplicate(list)</pre><p>One way to catch these problems early is by taking advantage of the <strong>go vet</strong> tool. It has an option <strong>-shadow</strong> which can help to detect issues with variable shadowing.</p><p>There is a good blog post called <a href="http://www.qureet.com/blog/golang-beartrap/">The Golang Beartrap</a> that talks more in detail about variable shadowing.</p><h4>Summary</h4><p>Go is a great language, and once you understand its quirks it can be a real pleasure to work in. I really appreciate the fantastic tooling, and readablity of the language. Good luck, and happy gophering! :)</p><p><em>Again, originally published at </em><a href="http://bryce.is/writing/code/jekyll/update/2015/11/01/3-go-gotchas.html"><em>bryce.is</em></a><em> on November 1, 2015.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=590b8c014e0a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Hello, World!]]></title>
            <link>https://medium.com/@betable/hello-world-f3aaff865f15?source=rss-5d16cef0c1af------2</link>
            <guid isPermaLink="false">https://medium.com/p/f3aaff865f15</guid>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[microservices]]></category>
            <category><![CDATA[devops]]></category>
            <dc:creator><![CDATA[Betable Engineering]]></dc:creator>
            <pubDate>Thu, 29 Oct 2015 00:59:22 GMT</pubDate>
            <atom:updated>2015-10-29T01:00:40.795Z</atom:updated>
            <content:encoded><![CDATA[<p>The state of Betable and our Technology by CTO, Mike Malone.</p><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*4YTOqSXARI2C7C-1DDcevQ.jpeg" /><figcaption>Photo Credit: <a href="https://www.flickr.com/photos/johnkay/8174372435/">Killer Whales in Monterey Bay</a> by <a href="https://www.flickr.com/photos/johnkay/">John ‘K’</a></figcaption></figure><p>My name is Mike Malone and I’m CTO at <a href="https://corp.betable.com/">Betable</a>, a venture backed <a href="https://eng.betable.com/">technology</a> startup based out of San Francisco. In the past I’ve been fairly active writer of things, <a href="http://lanyrd.com/profile/mjmalone/">speaker at conferences</a>, and contributor to <a href="https://www.djangoproject.com/">open</a> <a href="http://cassandra.apache.org/">source</a> and <a href="http://oembed.com/">open</a> <a href="http://oauth.net/">standards</a> <a href="http://openid.net/">projects</a>. That stopped pretty abruptly about four years ago when I joined Betable, a tiny company with the ambitious goal of reinventing and safely opening up the <strong>$500 billion</strong> gambling industry to developers who can’t afford their own licenses.</p><p>When I joined, Betable was just an idea. We immediately started documenting a basic system architecture (on a white board in <a href="https://twitter.com/chgriffin">the founder’s</a> garage, of course). Six months later we launched a payments flow and our first games. Fast forward about three years… last quarter we shuffled over <strong>$150 million</strong> through our accounting system. Lots of interesting stuff happened between then and now. To focus on that stuff, I took some time off from sharing my thoughts online. Now that the dust is settling a bit I’m back, and I’m excited to start documenting and sharing that journey here.</p><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*xMu7ofVywnzliaD1zL1llA.jpeg" /><figcaption>MVP (Early 2012)</figcaption></figure><p>As an online gambling operator Betable is a special kind of e-commerce business that, legally, is treated something like a multinational bank that also sells liquor. Our regulatory requirements are as onerous as many publicly traded companies. There are a lot of things we need to get right the first time (e.g., security, payments, random number generation). As a platform, we’re built for scale and developer ease of use. We’ve also got all the normal non-functionals that you’d expect at a startup (move fast, keep it simple, be agile, avoid complacency, yada yada yada). The point is we’re an interesting hybrid of an organization. We need mature processes and technologies to manage risk. At the same time, we’ve got to stay agile, move fast, and attract startup talent to be successful. Balancing these requirements is not easy.</p><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*FbDnqBuI7RtsQP9oNBDNZg.jpeg" /><figcaption>Legal Bills (Seriously)</figcaption></figure><p>For the most part, we’re not managing this stuff the “normal” way you’d see in an enterprise. Rather, we’ve been pushing the boundaries of agile processes and modern technologies. The accounting system mentioned above uses <a href="http://cassandra.apache.org/">Apache Cassandra</a>. Our servers? 100% cloud-based and under <a href="https://puppetlabs.com/">config management</a>. Overall architectural style? Chatty RESTish microservices speaking HTTPS and/or communicating over an event bus. QA and Deployments? Automated and on demand with a <a href="https://github.com/">code-review</a> and <a href="https://jenkins-ci.org/">CI pipeline</a>, and a whole lot of tests. Languages? We know <a href="https://www.python.org/">a</a> <a href="https://golang.org/">bunch</a> <a href="https://nodejs.org/">of</a> <a href="https://www.java.com/">them</a>. Pretty normal stuff for a startup (that does things right). Not so normal for a bank/liquor store. So, heads up to anyone who says this won’t work for their organization because <em>insert stupid regulatory requirement here</em> — you’re wrong. The only reason this stuff won’t work is organizational apathy.</p><p>That’s not to say there aren’t gotchas… there are lots. For example, it’s not easy getting regulatory waivers so you don’t have to implement password reset questions (because they’re <a href="https://www.schneier.com/essays/archives/2005/02/the_curse_of_the_sec.html">stupid</a> and <a href="http://www.guanotronic.com/~serge/papers/oakland09.pdf">insecure</a>), or explaining how deploying a system via git + configuration management is a safe alternative to signed gold-masters like JARs or ISOs. We’ve also had our fair share of screw ups. Have you ever run into <a href="https://twitter.com/wadey/status/385475359350603776">this Go language quirk</a>? Combined with a bit of test failure fatigue, that little quirk ended up costing us more than $50,000. Stories like this make us all better. On this blog we fully intend to share the bad along with the good.</p><p>Oh yea, we also have lots of normal distributed systems, microservice, operational, and general computing problems too. Want to know how to manage more than forty microservices with thirteen engineers and a two person ops team? We do that. Need a high availability durable state machine? We built our own distributed database for that. Need simple security measures to keep all of your microservices safe? Got ’em. Want to keep track of tons of micro-transactions? We’ve got some ideas. Need to support ad-hoc queries, but your online database is a NoSQL distributed key-value store? We’ve got that problem too (spoiler alert: don’t use Hadoop). Anyways, we’ve got some stories to tell!</p><p>In the interest of intrigue I’ll save further discussion for future posts. I’m very excited to finally be sharing more about <a href="https://eng.betable.com/">Betable engineering</a> publicly. Follow us here and <a href="https://twitter.com/BetableEng">on twitter</a> to stay up to date, and leave a comment if there’s anything you’re particularly excited to hear more about.</p><p><em>Originally published at </em><a href="https://medium.com/@mjmalone/80eea876d174"><em>medium.com</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f3aaff865f15" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Things I learned at JSConf.eu 2015]]></title>
            <link>https://medium.com/@betable/things-i-learned-at-jsconf-eu-2015-cb218fa054fe?source=rss-5d16cef0c1af------2</link>
            <guid isPermaLink="false">https://medium.com/p/cb218fa054fe</guid>
            <category><![CDATA[conference]]></category>
            <category><![CDATA[berlin]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Betable Engineering]]></dc:creator>
            <pubDate>Sat, 10 Oct 2015 07:29:02 GMT</pubDate>
            <atom:updated>2015-10-10T07:29:02.734Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>tl;dr:</strong> JavaScript is pretty cool once you accept and embrace its quirks. The community around it is even better. There are some fucking smart people working on really cool shit.</p><p>First off, let me start by saying that this was my first conference ever, and also that I am not actually a front-end JavaScript developer. Day to day, I spend my time building back-end micro-services in GO for <a href="https://corp.betable.com/">Betable</a>, an online gambling platform. I only dabble in JavaScript when I need to work on our externally facing API, which is written in Node.js. Needless to say, I was a little intimidated going to an all-JavaScript conference where every single person there was probably a much better JavaScript developer than I currently am.</p><p>Luckily, it all went much better than I expected. I learned a ton from the amazing talks I saw (more on that a bit later) and met some really cool people: the organizers (<a href="http://twitter.com/theophani">@theophani</a>, <a href="http://twitter.com/hblank">@hblank</a>, <a href="http://twitter.com/janl">@janl</a>), the speakers (<a href="http://twitter.com/razvancaliman">@razvancaliman</a>, <a href="http://twitter.com/whitneyhacks">@whitneyhacks</a>) and the attendees (too many to call out, sorry!). I also really enjoyed exploring Berlin — one of my favorite cities in my home country — with my friend from undergrad and fellow engineer <a href="http://twitter.com/tdeekens">@tdeekens</a>.</p><p>I flew into Frankfurt a few days early to visit my family and then blasted up the Autobahn on Thursday afternoon to get a good night of sleep before heading over to Radialsystem V at 9am for breakfast and mingling. The opening by the curators blew everyone away (or so it appeared) and landed some serious applause. It was a sweet light show and a fun mashup music performance of samples from previous talks at JSConf by <a href="http://twitter.com/thedeftone">@thedeftone</a>, <a href="http://twitter.com/kahliltweets">@kahliltweets</a> and <a href="http://twitter.com/bonotes">@bonotes</a>. Check it out here: <a href="https://t.co/6suUDWkF1x">https://youtu.be/lJ1kY-CSpBk</a></p><p>Talk slots were about 30 minutes and there was a coffee or food break after each block of three talks which made things very easy to follow without being overwhelmed with information. I did get a small hint of being back in school every now and then but unlike how I remember school, none of the talks at this conference disappointed or made me fall asleep. Every single one was interesting and engaging.</p><p>In broad terms they all centered around:</p><ol><li>community and the people that write code</li><li>performance and how to write code correctly</li><li>cool shit and how to push the cutting edge</li></ol><p>The breaks were filled with coffee by “The Barn,” arguably one of the best coffees in Berlin; ClubMate, a caffeine drink apparently very <a href="http://motherboard.vice.com/blog/how-a-german-soda-became-hackers-fuel-of-choice">popular</a> in Germany that I had never heard of before and fantastic food by a catering company that I didn’t get the name of but it was way better than I would have expected from such a large event.</p><p>Friday concluded with a party open to all JS conference attendees that weekend (RejectJS, JSConf, CSSConf) and plus-ones. <a href="http://twitter.com/usefulthink">@usefulthink</a> kicked it off with a demo in which he used JavaScript and CSS to showcase a light cube he built himself, as well as taking control of the room’s lighting systems and making it go crazy. Needless to say, the crowd went wild. For the rest of the night the Red Bull DJ Champion of 2014 spun the decks in impressive fashion and played a really fun set.</p><p>Saturday was a gap day on which CSSConf happened and I took the time to explore Berlin, which was a nice change of pace in between two full days of talks.</p><p>Sunday was much like Friday, except with a venue change for the closing party. We took over a small “club” on board of the Hoppetosse with open bar until the money ran out. You can imagine how that went.</p><p>Let’s go into a bit more detail on the talks. As I said earlier, they were all great but I am going to pick a few of them out that I liked in particular.</p><p><a href="http://2015.jsconf.eu/speakers/sam-richard-domo-arigato-mr-roboto.html"><strong>Domo Arigato Mr. Roboto</strong></a></p><p>Sam Richard from the IBM Watson project demonstrated a bunch of cool APIs that IBM recently made publicly available for processing human natural language (like speech). He put together a live speech-to-speech babelfish-like (hello Hitchhiker’s Guide to the Galaxy fans) translator as well as a GitHub commit tone extension that disables the “Submit” button if you’re using negative language in your commit. Interestingly, this was not the only talk on speech processing but I liked it the best.</p><p><strong>(</strong><a href="http://2015.jsconf.eu/speakers/stephan-boennemann-dependency-hell-just-froze-over.html"><strong>Dependency Hell Just Froze Over</strong></a><strong>)</strong></p><p>I completely missed this talk but it turned out to be all-the-hype that weekend so it deserves a mention here. If you are struggling with dependency version control in your JavaScript applications, go check out <a href="http://greenkeeper.io/">greenkeeper.io</a> by Stephan Bönnemann.</p><p><a href="http://2015.jsconf.eu/speakers/denys-mishunov-illusion-of-time-when-60-seconds-is-not-1-minute.html"><strong>Illusion of Time. When 60 seconds is not 1 minute.</strong></a></p><p>Denys Mishunov took us on a tour of user deception. People absolutely HATE passive wait time aka waiting for something without anything else to do. How does this help us as developers? Build websites that deceive the user by showing something very quickly and doing the heavy processing in the background while the user is distracted. For example amazon.com takes 7 seconds to fully load! But we don’t care because we see it and interact with it much earlier.</p><p><a href="http://2015.jsconf.eu/speakers/dmitry-baranovskiy-zen-of-javascript.html"><strong>Zen of JavaScript</strong></a></p><p>I came into this talk thinking: Hey, maybe someone will explain to me how to write JavaScript the right way. Aaaaaand was immediately disappointed when Dmitry Baranoskiy said that he didn’t know either. However, he pointed out a lot of fun quirks of JavaScript and concluded that we all just need to start accepting and embracing how JavaScript works instead of hating on it. For example .charAt() will give you a result no matter what it is called on or what it is passed. Strings, numbers, objects, undefined. Anything. Point taken.</p><p><a href="http://2015.jsconf.eu/speakers/thomas-gorissen-the-year-of-the-peertopeer-web.html"><strong>The year of the peer-to-peer web</strong></a></p><p>Thomas Gorissen took the stage, put on a black turtleneck sweater and proceeded to pitch P2P in a manner similar to the former head of a weird fruit company (Forrest Gump, anyone?). Why is this the year of peer-to-peer web? Because it is seriously one of the coolest things I’ve seen. WebRTC is an open web standard to enable real-time communication and P2P is by the default of IP the shortest connection between two computers, which means sending audio or video that route can’t get any more performant. He demoed a webpage that enabled videocalling between multiple people with a one-line embedded script tag. Gone are the days of Skype and Google Hangouts if you can just do that in your web apps! Check out <a href="http://skylink.io/">skylink.io</a> and <a href="https://webtorrent.io/">webtorrent.io</a> for demos and more information.</p><p><a href="http://2015.jsconf.eu/speakers/whitney-williams-if-walter-gropius-was-a-javascripter.html"><strong>If Walter Gropius was a JavaScripter</strong></a></p><p>Whitney Williams, who I had met the day before over coffee, talked about the history of the Bauhaus, an art school that operated in Germany in the 1920s and early 1930s and fostered the connection of manufacturing with design. Her point was that we should inspire more collaboration between developers and designers and stop separating the two.</p><p><a href="http://2015.jsconf.eu/speakers/2015-09-16-christoph-pojer-evolving-complex-systems-Incrementally.html"><strong>Evolving Complex Systems Incrementally</strong></a></p><p>Christoph Pojer from Facebook demonstrated an impressive AST-based tool that helps them refactor massive amounts of code in seconds. It is called <a href="https://github.com/facebook/jscodeshift">JScodeshift</a> and is now an open-source project! Codemod tools give anyone the ability to align certain coding patterns over entire code bases without having to edit potentially thousands of files manually.</p><p><a href="http://2015.jsconf.eu/speakers/thomas-watson-airplay-protocol-hacking.html"><strong>AirPlay protocol hacking</strong></a></p><p>Thomas Watson was visibly nervous because he had worked on his demos until 3am the night before. He started off with a theory lesson on how AirPlay works and broke it down as essentially being multicast DNS plus some fancy encryption. As usual, Apple just took existing technology, put a little twist on it to confuse everyone and is selling it as innovative and amazing. Luckily, there are people like Thomas out there that put a lot of effort into reverse-engineering this stuff and then giving us open-source tools to use that technology. You can even use it to live stream audio over torrents with <a href="https://github.com/mafintosh/peervision">peervision</a>.</p><p><a href="http://2015.jsconf.eu/speakers/razvan-caliman-disconnected-networking.html"><strong>Disconnected Networking</strong></a></p><p>Razvan Caliman, another speaker that I had met on Friday, demonstrated some alternative methods of communication. Have you ever tried to transmit data using supersonic sound or via ambient light sensors? No? Well he built demos for both an more. Apparently this technology already exists to track movement through stores with visual light communication. Really impressive stuff and interesting alternative ideas. Supposedly you can even infect the BIOS with viruses just by sending sound waves that get picked up by your sound card …</p><p><a href="http://2015.jsconf.eu/speakers/ola-adedoyin-applying-3d-engineering-drawing-techniques.html"><strong>Applying 3D Engineering Drawing Techniques To Web App Diagrams</strong></a></p><p>Here is a new concept: Ever get tired of navigating your codebase and trying to keep the entire folder and file structure in your head until somebody comes and distracts you and that carefully crafted model in your head just shatters? Ola Adedoyin might have a solution for you by creating 3D models of your codebase. The idea sounds awesome and very promising but unfortunately there are hardly any tools available for this now. It’s something to watch for the future though!</p><p><a href="https://docs.google.com/a/betable.com/spreadsheets/d/1NHM-pwTepPabknf0LlTXfZh9s4x3hbl5GNyDmXDomZI/pub?output=html"><strong>The Rest…</strong></a></p><p>There were of course many more talks that were technically interesting, thought provoking and mentally stimulating but sadly I can not call out all of them.</p><p>JSConf.eu was my first conference and I could not have asked for a better experience. By the end of it I was left with a ton of new ideas to bring back to our engineering team and with an overwhelming sense of wanting to be part of this community of awesome people. I am very thankful for the opportunity that <a href="http://twitter.com/betable">@betable</a> and especially our new VP of engineering, <a href="http://twitter.com/admc">@admc</a>, gave me and I hope to see everyone again next year!</p><p><em>Originally published at </em><a href="https://medium.com/@coffee4tw/things-i-learned-at-jsconf-eu-2015-8610b34b0600"><em>medium.com</em></a><em> on October 9, 2015.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cb218fa054fe" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>