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

<channel>
	<title>MemSQL Developer Blog</title>
	<atom:link href="http://developers.memsql.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://developers.memsql.com/blog</link>
	<description>Discussing the latest in database technologies</description>
	<lastBuildDate>Tue, 23 Apr 2013 10:13:52 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4</generator>
		<item>
		<title>MemSQL ships 2.0. Scales in-memory database across hundreds of nodes, thousands of cores.</title>
		<link>http://developers.memsql.com/blog/real-time-analytics-platform/</link>
		<comments>http://developers.memsql.com/blog/real-time-analytics-platform/#comments</comments>
		<pubDate>Tue, 23 Apr 2013 09:17:24 +0000</pubDate>
		<dc:creator>MemSQL Engineering</dc:creator>
				<category><![CDATA[Distributed]]></category>

		<guid isPermaLink="false">http://developers.memsql.com/blog/?p=346</guid>
		<description><![CDATA[When we started MemSQL a little over two years ago, our goal was to deliver the fastest OLTP database ever. Inspired by the scale and architectures we saw at Facebook, we hoped to help every enterprise leverage in-memory technologies similar &#8230; <a href="http://developers.memsql.com/blog/real-time-analytics-platform/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>When we started MemSQL a little over two years ago, our goal was to deliver the fastest OLTP database ever. Inspired by the scale and architectures we saw at Facebook, we hoped to help every enterprise leverage in-memory technologies similar to those that leading web companies use.</p>
<p>As we worked with our early customers, we saw that an in-memory solution could provide the greatest value by enabling users to analyze real-time and recent historical data together. Customers like <a href="http://www.memsql.com/customers">Zynga</a> and <a href="http://www.memsql.com/press/morgan-stanley-award">Morgan Stanley</a> not only wanted to quickly commit transactions to the database, they also wanted instant answers to questions about how their real-time data compared to historical data. This inspired us to build something new &#8211; a solution that supports highly concurrent transactional and analytical workloads at Big Data scale.</p>
<p>That brings us to today. We’re proud to <a href="http://www.memsql.com/press/memsql-distributed-launch">announce</a> that MemSQL’s <a href="http://www.memsql.com/product">real-time analytics platform</a> is available for <a href="http://www.memsql.com/download?lead_source=Web%20Direct&amp;lead_source_detail=Blog">download</a>. This is the first generally available version of MemSQL that scales horizontally on commodity hardware. It provides the blazing fast performance for which MemSQL is known, and now does it at Big Data scale. Customers have deployed MemSQL across hundreds of nodes and dozens of terabytes of data, and we’ve tested at even greater volumes and velocities. (Check out our <a href="http://www.memsql.com/why-memsql#scale-out">calculator</a> to get an idea of the number of reads and writes you can perform depending on the size of your cluster.)</p>
<p>This is also the first version to include <a href="http://www.memsql.com/features#dashboard">MemSQL Watch</a>, a visual web-based interface for monitoring and managing your cluster. We expect this to be the beginning of our foray into real-time visualizations as many of our customers look to operationalize their analytics.</p>
<p dir="ltr">Deploying a database can be difficult, so we’ve made it as simple as possible. <a href="http://www.memsql.com/download?lead_source=Web%20Direct&amp;lead_source_detail=Blog">Download MemSQL</a> for free on our site and take it for a spin. You’ll definitely be impressed by the performance, but you’ll also be impressed by what’s missing:</p>
<ul>
<li>Batched loading &#8211; Don’t wait until the middle of the night to refresh your reports.</li>
<li>Complicated programming languages (and a limited talent pool) &#8211; Use SQL for real-time analytics.</li>
<li>An expensive, proprietary box (and a plan to rip and replace it in a few years) &#8211; Scale incrementally on commodity hardware.</li>
<li>A lengthy implementation cycle &#8211; Launch your first MemSQL instance in minutes in the cloud.</li>
</ul>
<p>We’re proud of the progress our engineering team has made building out an enterprise-grade software solution. Stay tuned to this blog to learn more about the real-time analytics challenges we are helping customers conquer. More to come.</p>
]]></content:encoded>
			<wfw:commentRss>http://developers.memsql.com/blog/real-time-analytics-platform/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Practical Techniques to Achieve Quality in Large Software Projects</title>
		<link>http://developers.memsql.com/blog/practical-techniques-to-achieve-quality-in-large-software-projects/</link>
		<comments>http://developers.memsql.com/blog/practical-techniques-to-achieve-quality-in-large-software-projects/#comments</comments>
		<pubDate>Wed, 10 Apr 2013 17:27:11 +0000</pubDate>
		<dc:creator>MemSQL Engineering</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://developers.memsql.com/blog/?p=326</guid>
		<description><![CDATA[High quality is hard to achieve and very expensive, but it’s worth every penny and must be taken extremely seriously. There is no silver bullet &#8211; just lines of defense. The good news is with the proper lines of defense, &#8230; <a href="http://developers.memsql.com/blog/practical-techniques-to-achieve-quality-in-large-software-projects/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>High quality is hard to achieve and very expensive, but it’s worth every penny and must be taken extremely seriously. There is no silver bullet &#8211; just lines of defense. The good news is with the proper lines of defense, quality becomes incremental. It only goes up with every release. With enough test coverage and quality tools you can substantially increase the quality of your product and protect it from regressions.</p>
<p class="c5"><img src="/blog/wp-content/uploads/2013/04/joplin-expats-stamp-of-approval.png" alt="" width="600" height="340" /></p>
<p class="c6 c5"><span id="more-326"></span>When you embark upon a large software project you need figure out how to think about quality. And you should start with testing. Not all tests are created equal. Here are the most common types:</p>
<ol class="c4" start="1">
<li class="c0"><span>Unit tests</span></li>
<li class="c0"><span>Invariant tests (asserts, etc)</span></li>
<li class="c0"><span>Functional tests</span></li>
<li class="c0"><span>Stress </span><span>tests</span></li>
<li class="c0"><span>Performance tests</span></li>
<li class="c0"><span>Scalability tests</span></li>
<li class="c0"><span>Customer workload based testing</span></li>
<li class="c0"><span>Scenario based testing</span></li>
</ol>
<p class="c5"><span>In this blog post we will discuss test coverage as well as how to manage the long tail of rarely surfaced bugs using </span><span class="c1">force multipliers</span><span> - a slew of engineering techniques that transform our existing test suite to produce new ways of testing the product. Each of these has been a small &#8220;aha&#8221; moment and yielded good results.</span></p>
<h1 class="c5"><a name="h.a09xuhjuaw9"></a><span>Put Your Test Plan on Paper: The Test Matrix</span></h1>
<p class="c5"><span>With testing, one of the hardest things is deciding </span><span class="c1">exactly </span><span class="c1"><em>what</em> to test</span><span>. Every test you create or run has a cost, and this is where a tester&#8217;s intuition shines. When your product has a lot of features it’s easy to poke around, but the real question is how can you do it in a systematic way.</span></p>
<p class="c5"><span>It’s important to track which areas of the product are tested well and which are not, and this is made all the more difficult by the many moving parts of the codebase. Here are a few MemSQL examples:</span></p>
<ol class="c4" start="1">
<li class="c0"><span>Correctness of read queries in the presence of write queries</span></li>
<li class="c0"><span>Correctness of replication in the presence of alter table</span></li>
</ol>
<p class="c5"><span>It helps tremendously to test combinations of features. It’s especially hard because different people or even teams could work on those features and the problem may only arise when both features are involved at the same time.</span></p>
<p class="c5"><span>The number of possible combinations explodes very quickly. However, we&#8217;ve noticed that in practice </span><span>the majority of </span><span>bugs surface</span><span> </span><span class="c1">in the combination of just <em>two</em> features</span><span>.</span></p>
<p class="c5"><span>So, one way to tackle the combinatorial explosion is to only consider </span><span class="c7"><a class="c10" href="http://en.wikipedia.org/wiki/All-pairs_testing">pairs of features</a></span><span> and write tests for every pair. You can also employ n-wise testing and use a different combination every time.</span></p>
<p class="c5"><span>On top of that you should also think about </span><span class="c1">dimensions</span><span>. A classical test dimension for a SQL database is “all data types” or “all possible positions within a SQL query such as the where clause, select clause, group by, etc.” When testing a specific feature you want to test it with every dimension.</span></p>
<p class="c5"><span>We wrote down all feature pairs and dimensions into a giant spreadsheet. After </span><span>that we fanned out the test work to the engineering team to </span><span class="c1">color the matrix </span><span class="c1">green</span><span>.</span></p>
<h1 class="c5"><a name="h.ehvmcqozayyd"></a><span>Invest Into A Stellar Test Execution System</span></h1>
<p class="c5"><span>You can write a lot of tests, but it is </span><span class="c1">continuous integration testing that allows developers to make far-reaching changes without a paralyzing fear of undetected break</span><span class="c1">s</span><sup class="c1"><a name="ftnt_ref1" href="#ftnt1"></a>[1]</sup><span>. </span><span>Such integration testing should be fast and scalable. You need stellar test infrastructure to frictionlessly add, manage, and run these tests. With a well-built execution system, the number of functional tests can grow safely and quickly.</span></p>
<p class="c5"><span>Building good</span><span> </span><span>test infrastructure is similar to writing a consumer product for your engineering team. The easier it is to produce tests, the more the engineering team is engaged and more tests are running against your system every day. In the ideal world, when you modify a single line of code you should instantly know what tests you just broke. Practically it’s not always possible because of the computational complexity of test runs, but you should push towards getting instant feedback as much as possible.</span></p>
<p class="c5"><span><strong>A perfect test execution system would run the entire test suite after every push.</strong>  We used to run every test before commits on each developer&#8217;s machine. When that started taking too long, we ran only a subset of tests locally and performed full test runs every night on a dedicated box. When the dedicated box couldn&#8217;t handle the load, we built </span><span>a cloud-based test execution platform called &#8220;Psyduck.&#8221;</span></p>
<p class="c5"><span>The </span><span>Psyduck platform</span><span> can run any subset of our tests against any version of our codebase.  </span><span>Furthermore, if you want to run tests against local code changes, Psyduck accepts patches, and so we enforce running Psyduck before pushing code. For example:</span></p>
<pre>memcompute1:~/memsql/memsqltest nikita(arcpatch-D2497)$ ./psy test --filter=.nikita
Compressing patch...done.
Sending 5340 bytes to S3.....done.
patch id = 901be82c33ee4b07b142d102660e3206Psyduck <span class="c1">uses a combination of in-house hardware along with hundreds of Amazon </span><span class="c1 c7"><a class="c10" href="http://aws.amazon.com/ec2/spot-instances/">spot instances</a></span> to run tests as fast as possible in parallel.</pre>
<p class="c5"><span>Last summer a MemSQL intern built a real-time visualization layer called </span><span class="c1">Liveduck</span><span> and it became an instant hit.  This interface displays all ongoing and recently completed tests along with metadata such as the associated engineer and the pass/fail count.</span></p>
<p class="c5"><img src="/blog/wp-content/uploads/2013/04/Psyduck.png" alt="" width="680" height="638" /></p>
<p class="c5"><span>Psyduck provides us with a quick metric on where we stand now and where we need to be at release. As we approach a release, the team pushes towards what we call “green Psyduck”. This means that all tests are passing.</span></p>
<p class="c5"><span>Another property of an excellent test system is that every test </span><span class="c1">must</span><span> run the same on a </span><span>developer’s</span><span> machine as it does on the platform. </span><span> Furthermore, each test should be self-contained so that it requires </span><span class="c1">zero setup</span><span>.</span><span>  This will greatly assist in test suite maintenance and accelerate failure investigation.</span></p>
<h1 class="c5"><a name="h.kudaqcu2keps"></a><span>Force Multipliers</span></h1>
<p class="c5"><span>Every one of these tricks took MemSQL quality to the next level. Here is the list.</span></p>
<h2 class="c5"><a name="h.h8uo9iu7npyw"></a><span>Transforms</span></h2>
<p class="c5"><span>Transforms allow to put a twist on all existing tests. By implementing a few functions in Python you can munge both the incoming query and the expected output. </span><span>Then, you can run your </span><span class="c1">entire</span><span> functional test suite via a transform.</span><span> MemSQL has many transforms. Here are few:</span></p>
<ol class="c4" start="1">
<li class="c0"><span>Replication transform. All the read queries are directed to a replication slave.</span></li>
<li class="c0"><span>Subquery transform. Every read query is wrapped into subquery</span></li>
<li class="c0"><span>Backup restore transform. As queries run, the transform performs backups and restore and makes sure the results of the queries stay the same</span></li>
</ol>
<p class="c5"><span>We have had internal transform competitions, where the goal is to write the transform which finds the most bugs. When you write transforms you feel like you are standing of the shoulders of giants. With a few lines of code, you can stress the system with thousands of new tests.</span></p>
<h2 class="c5"><a name="h.i3sxf0mo7q18"></a><span>Random</span><span> Query </span><span>Generation</span></h2>
<p class="c5"><span>Random query generators produce SQL statements using a given grammar. The cool part is that it can read the bison grammar of the actual product and use it to generate random queries. There are a bunch of force multipliers applicable for random query generation:</span></p>
<ol class="c4" start="1">
<li class="c0"><span>Produce many different queries that give the same result; for example, identical queries over tables with different indexes and cross verify the results.</span></li>
<li class="c0"><span>Build intelligence into the generator to gradually increase the complexity of the generated tests. This ensures that the system is robust against simple cases before you proceed into more complex cases. If you start with complex cases you won’t be able to converge to a quality system fast enough.</span></li>
<li class="c0"><span>Once a bug is identified, the generator </span><span>automatically reduces the complexity of the query to come up with the smallest possible reproducible test case.</span><span> Random query generators can produce extremely intimidating queries. If the repro is left “as is” it would take a lot more time for a developer to investigate the root cause of the failure.</span></li>
</ol>
<h2 class="c5"><a name="h.dei6egkkaxeh"></a><span>Functional Stress</span></h2>
<p class="c5"><span>Now that you have created a lot of functional tests, you can leverage them to run </span><span class="c1"><em>functional stress</em></span><span>. </span><span>The idea is that you take all these tests and randomly throw them at the system in parallel. When you do that you can’t really verify the test results, but all you care about is </span><span>crashes</span><span> and internal consistency checks.</span></p>
<h2 class="c5"><a name="h.8nhvv7tv4e53"></a><span>Stack Hasher</span></h2>
<p class="c5"><span>This is a very neat </span><span>trick. Every time there is a condition that is true 99.9% of the time (like memory allocations), you inject a failure </span><span class="c1">once per<em> unique call stack</em></span><span>. So if you run a query &#8220;select * from t&#8221; the first time the server will throw an error with the first memory allocation. Then when you run this command again, the first memory allocation succeeds because this call stack has already been failed once (and saved in the stackhasher), but the next allocation fails, and so forth. If you can keep re-running a query until it succeeds, you can deterministically test each possible resource failure. We have a transform which does exactly this with every test in our code base, and it has proven invaluable.</span></p>
<h1 class="c5"><a name="h.4nh7u7pyo83i"></a><span>Production failures</span></h1>
<p class="c5"><span>Even though you test relentlessly, you still need pathways for your customers to surface issues back to your engineering team </span><span>for investigation. You want to introduce minidump and full core dump functionality, in addition to logging to correctly diagnose bugs.</span></p>
<h1 class="c5"><a name="h.5twj4g55gs86"></a><span>Promote Transparency and Quality Culture Via Code Review</span></h1>
<p class="c5"><span>One of the first steps towards quality that we did was to have every change go through a code review. To assist with this process a good tool is a must. We use </span><span class="c7"><a class="c10" href="http://www.phabricator.org">Phabricator</a></span><span> because it integrates into our workflow and is fun and </span><span>easy to use.</span></p>
<p class="c5"><img src="/blog/wp-content/uploads/2013/04/phabricator.png" alt="" width="611" height="535" /></p>
<p class="c5"><span>Code review helps promote a quality-oriented culture in the office.  Engineers will trend towards producing better code and more tests to increase the number of positive comments they receive.  Furthermore, having such a system in place helps new engineers learn the ropes faster.</span></p>
<h1 class="c5"><a name="h.4lohiytb7okx"></a><span>Conclusion</span></h1>
<p class="c5"><span>It&#8217;s entirely worthwhile to invest into testing infrastructure from Day One. By doing so, you can achieve the following goals:</span></p>
<ol class="c4" start="1">
<li class="c0"><span>Using stellar tools and force multipliers to do more with fewer engineers and really</span><span> push the long tail of bugs</span></li>
<li class="c0"><span>Always be aware of the current state of the quality of the product</span></li>
<li class="c0"><span>Quickly stabilize and ship the product!</span></li>
</ol>
<hr class="c3" />
<div>
<p class="c5 c12"><a name="ftnt1" href="#ftnt_ref1"></a>[1]<span class="c9"> Steven Hemingray. Google</span></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://developers.memsql.com/blog/practical-techniques-to-achieve-quality-in-large-software-projects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Common Pitfalls in Writing Lock-Free Algorithms</title>
		<link>http://developers.memsql.com/blog/common-pitfalls-in-writing-lock-free-algorithms/</link>
		<comments>http://developers.memsql.com/blog/common-pitfalls-in-writing-lock-free-algorithms/#comments</comments>
		<pubDate>Wed, 27 Mar 2013 22:16:34 +0000</pubDate>
		<dc:creator>Pieguy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://developers.memsql.com/blog/?p=300</guid>
		<description><![CDATA[Formally, a multi-threaded algorithm is considered to be lock-free if there is an upper bound on the total number of steps it must perform between successive completions of operations. The statement is simple, but its implications are deep &#8211; at &#8230; <a href="http://developers.memsql.com/blog/common-pitfalls-in-writing-lock-free-algorithms/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<div class="document">
<div class="section" id="common-pitfalls-in-writing-lock-free-algorithms">
<p>
<img alt="failstack.jpeg" src="/blog/wp-content/uploads/2013/03/failstack.jpeg" /></p>
<p>Formally, a multi-threaded algorithm is considered to be lock-free if there is an upper bound on the total number of steps it must perform between successive completions of operations.<br />
The statement is simple, but its implications are deep &#8211; at every stage, a lock-free algorithm guarantees forward progress in some finite number of operations.<br />
Deadlock is impossible.</p>
<p><span id="more-300"></span></p>
<p>The promise of a lock-free algorithm seems remarkable in theory.<br />
Concurrent threads can modify the same object, and even if some thread or set of threads stalls or stops completely in the middle of an operation,<br />
the remaining threads will carry on as if nothing were the matter.<br />
Any interleaving of operations still guarantees of forward progress.<br />
It seems like the holy grail of multi-threaded programming.</p>
<p>This stands in contrast to the traditional method of placing locks around &quot;critical sections&quot; of code.<br />
Locking prevents multiple threads from entering these critical sections of code at the same time.<br />
For highly concurrent applications, locking can constitute a serious bottleneck.<br />
Lock-free programming aims to solve concurrency problems without locks. Instead, lock-free algorithms rely on atomic primitives such as the classic &quot;compare-and-swap&quot; which atomically performs the following:</p>
<pre class="code c literal-block">
<span class="ln">1 </span><span class="n">bool</span> <span class="n">CompareAndSwap</span><span class="p">(</span><span class="n">Value</span><span class="o">*</span> <span class="n">addr</span><span class="p">,</span> <span class="n">Value</span> <span class="n">oldVal</span><span class="p">,</span> <span class="n">Value</span> <span class="n">newVal</span><span class="p">){</span>
<span class="ln">2 </span>    <span class="k">if</span><span class="p">(</span><span class="o">*</span><span class="n">addr</span> <span class="o">==</span> <span class="n">oldVal</span><span class="p">){</span>
<span class="ln">3 </span>        <span class="o">*</span><span class="n">addr</span> <span class="o">=</span> <span class="n">newVal</span><span class="p">;</span>
<span class="ln">4 </span>        <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="ln">5 </span>    <span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="ln">6 </span>        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="ln">7 </span>    <span class="p">}</span>
<span class="ln">8 </span><span class="p">}</span>
</pre>
<p>The biggest drawbacks to using lock-free approaches are</p>
<ul class="simple">
<li>Lock-free algorithms are not always practical.</li>
<li>Writing lock-free code is difficult.</li>
<li>Writing correct lock-free code is extremely difficult.</li>
</ul>
<p>To illustrate the third point above, let’s break down a typical first attempt at writing a lock-free stack.  The idea is to use a linked-list to store nodes, and use CompareAndSwap to modify the head of the list, in order to prevent multiple threads from interfering with each other.</p>
<p>To push an element, we first create a new node to hold our data.<br />
We point this node at the current head of the stack, then use CompareAndSwap to point the head of the stack to the new element.<br />
The CompareAndSwap operation ensures that we only change the head of the stack if our new node correctly points to the old head (since an interleaving thread could have changed it).</p>
<p>To pop an element, we snapshot the current head, then replace the head with the head&#8217;s next node.<br />
We again use CompareAndSwap to make sure we only change the head if its value is equal to our snapshot.</p>
<p>The code, in C++</p>
<pre class="code c literal-block">
<span class="ln"> 1 </span><span class="n">template</span> <span class="o">&lt;</span><span class="n">class</span> <span class="n">Entry</span><span class="o">&gt;</span>
<span class="ln"> 2 </span><span class="n">class</span> <span class="n">LockFreeStack</span><span class="p">{</span>
<span class="ln"> 3 </span>    <span class="k">struct</span> <span class="n">Node</span><span class="p">{</span>
<span class="ln"> 4 </span>        <span class="n">Entry</span><span class="o">*</span> <span class="n">entry</span><span class="p">;</span>
<span class="ln"> 5 </span>        <span class="n">Node</span><span class="o">*</span> <span class="n">next</span><span class="p">;</span>
<span class="ln"> 6 </span>    <span class="p">};</span>
<span class="ln"> 7 </span>
<span class="ln"> 8 </span>    <span class="n">Node</span><span class="o">*</span> <span class="n">m_head</span><span class="p">;</span>
<span class="ln"> 9 </span>
<span class="ln">10 </span>    <span class="kt">void</span> <span class="n">Push</span><span class="p">(</span><span class="n">Entry</span><span class="o">*</span> <span class="n">e</span><span class="p">){</span>
<span class="ln">11 </span>        <span class="n">Node</span><span class="o">*</span> <span class="n">n</span> <span class="o">=</span> <span class="n">new</span> <span class="n">Node</span><span class="p">;</span>
<span class="ln">12 </span>        <span class="n">n</span><span class="o">-&gt;</span><span class="n">entry</span> <span class="o">=</span> <span class="n">e</span><span class="p">;</span>
<span class="ln">13 </span>        <span class="k">do</span><span class="p">{</span>
<span class="ln">14 </span>            <span class="n">n</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">=</span> <span class="n">m_head</span><span class="p">;</span>
<span class="ln">15 </span>        <span class="p">}</span><span class="k">while</span><span class="p">(</span><span class="o">!</span><span class="n">CompareAndSwap</span><span class="p">(</span><span class="o">&amp;</span><span class="n">m_head</span><span class="p">,</span> <span class="n">n</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">,</span> <span class="n">n</span><span class="p">));</span>
<span class="ln">16 </span>    <span class="p">}</span>
<span class="ln">17 </span>
<span class="ln">18 </span>    <span class="n">Entry</span><span class="o">*</span> <span class="n">Pop</span><span class="p">(){</span>
<span class="ln">19 </span>        <span class="n">Node</span><span class="o">*</span> <span class="n">old_head</span><span class="p">;</span>
<span class="ln">20 </span>        <span class="n">Entry</span><span class="o">*</span> <span class="n">result</span><span class="p">;</span>
<span class="ln">21 </span>        <span class="k">do</span><span class="p">{</span>
<span class="ln">22 </span>            <span class="n">old_head</span> <span class="o">=</span> <span class="n">m_head</span><span class="p">;</span>
<span class="ln">23 </span>            <span class="k">if</span><span class="p">(</span><span class="n">old_head</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">){</span>
<span class="ln">24 </span>                <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="ln">25 </span>            <span class="p">}</span>
<span class="ln">26 </span>        <span class="p">}</span><span class="k">while</span><span class="p">(</span><span class="o">!</span><span class="n">CompareAndSwap</span><span class="p">(</span><span class="o">&amp;</span><span class="n">m_head</span><span class="p">,</span> <span class="n">old_head</span><span class="p">,</span> <span class="n">old_head</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">));</span>
<span class="ln">27 </span>
<span class="ln">28 </span>        <span class="n">result</span> <span class="o">=</span> <span class="n">old_head</span><span class="o">-&gt;</span><span class="n">entry</span><span class="p">;</span>
<span class="ln">29 </span>        <span class="n">delete</span> <span class="n">old_head</span><span class="p">;</span>
<span class="ln">30 </span>        <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="ln">31 </span>    <span class="p">}</span>
<span class="ln">32 </span><span class="p">}</span>
</pre>
<p>Unfortunately, this stack is riddled with errors.</p>
<div class="section" id="segfault">
<h2>Segfault</h2>
<p>The Push() method allocates memory to store linked-list information, and the Pop() method deallocates the memory.<br />
However, between the time a thread obtains a pointer to a node on line 22, and subsequently accesses the node on line 26, another thread could have removed and deleted the node, and the thread will crash.<br />
A safe way to reclaim the memory is needed.</p>
</div>
<div class="section" id="corruption">
<h2>Corruption</h2>
<p>The CompareAndSwap method makes no guarantees about whether the value has changed, only that the new value is the same as the old value.<br />
If the value is snapshotted on line 22, then changes, then changes back to the original value, the CompareAndSwap will succeed.  This is known as the ABA problem.<br />
Suppose the top two nodes on the stack are <strong>A</strong> and <strong>C</strong>.<br />
Consider the following sequence of operations:</p>
<ul class="simple">
<li>Thread 1 calls pop, and on line 22 reads m_head (<strong>A</strong>), on line 26 reads old_head-&gt;next (<strong>C</strong>), and then blocks just before calling CompareAndSwap.</li>
<li>Thread 2 calls pop, and removes node <strong>A</strong>.</li>
<li>Thread 2 calls push, and pushes a new node <strong>B</strong>.</li>
<li>Thread 2 calls push again, and this time pushes a new node occupying the reclaimed memory from <strong>A</strong>.</li>
<li>Thread 1 wakes up, and calls CompareAndSwap.</li>
</ul>
<p>The CompareAndSwap on line 26 succeeds even though m_head has changed 3 times, because all it checks is that old_head is equal to m_head.<br />
This is bad because now m_head will point to <strong>C</strong>, even though <strong>B</strong> should be the new head.</p>
</div>
<div class="section" id="not-lock-free">
<h2>Not lock-free</h2>
<p>The C++ standard makes no guarantee that new and delete will be lock-free.<br />
What good is a lock-free data structure that makes calls to non-lock-free library calls?<br />
For our stack to be truly lock-free, we need a lock-free allocator.</p>
</div>
<div class="section" id="data-races">
<h2>Data races</h2>
<p>When one thread writes a value to a location in memory, and another thread simultaneously reads from the same location,<br />
the result is undefined in C++ unless std::atomic is used.<br />
The reads and writes both need to be atomic, and C++ makes no such guarantee for primitive types.<br />
Prior to C++11, it was a common practice to use volatile for atomic variables, however this approach is <a class="reference external" href="http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming">fundamentally flawed</a>.</p>
<p>In this case, threads reading the head pointer constitute data races, both in Push and Pop, because another thread could be simultaneously modifying it.</p>
</div>
<div class="section" id="memory-reordering">
<h2>Memory reordering</h2>
<p>It is convenient to think of computers as being sequentially consistent machines,<br />
where every load or store can be placed into a single total order that is consistent with every thread.  At the very least, we would expect the “happens before” relationship to be transitive.<br />
Unfortunately this is not the case, and in both theory and practice the following sequence of events is possible, with x and y initialized to 0:</p>
<table border="1" class="docutils">
<colgroup>
<col width="50%" />
<col width="50%" />
</colgroup>
<thead valign="bottom">
<tr>
<th class="head">thread 1</th>
<th class="head">thread 2</th>
</tr>
</thead>
<tbody valign="top">
<tr>
<td>
<p class="first">print x</p>
<p>x.store(1)</p>
<p class="last">print y</p>
</td>
<td>
<p class="first">print y</p>
<p>y.store(1)</p>
<p class="last">print x</p>
</td>
</tr>
</tbody>
</table>
<p>output:</p>
<table border="1" class="docutils">
<colgroup>
<col width="50%" />
<col width="50%" />
</colgroup>
<thead valign="bottom">
<tr>
<th class="head">thread 1</th>
<th class="head">thread 2</th>
</tr>
</thead>
<tbody valign="top">
<tr>
<td>
<p class="first">x -&gt; 0</p>
<p class="last">y -&gt; 0</p>
</td>
<td>
<p class="first">y -&gt; 0</p>
<p class="last">x -&gt; 0</p>
</td>
</tr>
</tbody>
</table>
<p>This would seem to imply that the printing of x happened before the store of x, which happened before the printing of y, which happened before the store of y, which in turn happened before the printing of x.  This is just one example of how different threads may see changes to memory occur in different orders.<br />
Furthermore, it is possible for loads and stores to be reordered within a single thread, both by the compiler and by the hardware.<br />
In the above lock-free stack a reordered store could result in another thread seeing a stale version of a node&#8217;s next pointer and subsequently dereferencing an invalid memory location.</p>
</div>
</div>
<div class="section" id="how-to-write-a-correct-lock-free-stack">
<h1>How to write a correct lock-free stack</h1>
<p>Most of the above problems have many different solutions.<br />
Here I&#8217;ll describe the approaches I use at work for our lock-free stack.</p>
<div class="section" id="id1">
<h2>Segfault</h2>
<p>Before dereferencing a node, we need to make sure it cannot be deleted.<br />
Each thread has a special globally visible pointer called a &quot;hazard pointer&quot;.<br />
Before accessing the head node, a thread will set its hazard pointer to point to that node.<br />
Then, after setting the hazard pointer it makes sure the node is still the head of the stack.<br />
If it is still the head, then it is now safe to access.<br />
Meanwhile, other threads that may have removed the node from the stack cannot free the associated memory until no hazard pointer points to this node.<br />
For efficiency, the deletion process is deferred to a garbage collection thread that amortizes the cost of checking hazard pointers.</p>
<p>Note that the ABA problem does not have any consequences here.  It does not matter if the head changed between the two reads.  As long as the hazard pointer has been continuously pointing to a node for some interval of time that includes a moment in which the node belonged to the stack, then it is safe to access the node.</p>
</div>
<div class="section" id="id2">
<h2>Corruption</h2>
<p>One way to avoid the ABA problem is to ensure that the head of the stack never has the same value twice.<br />
We use &quot;tagged pointers&quot; to ensure uniqueness of head values.<br />
A tagged pointer contains a pointer and a 64-bit counter.<br />
Every time the head changes, the counter is incremented.<br />
This requires a double-width CompareAndSwap operation, which is available on most processors.</p>
</div>
<div class="section" id="id3">
<h2>Not lock-free</h2>
<p>Instead of allocating a separate node to store each entry, the &quot;next&quot; pointer is embedded in the entry itself,<br />
thus no memory allocation is needed in order to push it onto the stack.<br />
Furthermore, we may reuse the same node multiple times, recycling rather than deleting.<br />
Requiring an extra 8 bytes per entry is an unattractive property if you want a stack for small data structures,<br />
but we only use the stack for large items where the 8 bytes is insignificant.</p>
</div>
<div class="section" id="id4">
<h2>Data races</h2>
<p>We currently use boost::atomic for this.<br />
Our compiler is gcc 4.6, which currently supports std::atomic, but its implementation is much less efficient than boost&#8217;s.  In gcc 4.6, all operations on atomic variables apply expensive memory barriers, even when a memory barrier is not requested.</p>
</div>
<div class="section" id="id5">
<h2>Memory reordering</h2>
<p>C++11 provides a new memory model and memory ordering semantics for atomic operations that control reordering.<br />
For our lock-free stack to work correctly, CompareAndSwap needs to be performed with sequentially consistent memory semantics (the strongest kind).<br />
Sequential consistency means that all such operations can be put into a total order in which all threads observe the operations.<br />
There is a very easy to miss race condition (that went unnoticed in our code for months) involving the aforementioned hazard pointers.<br />
It turns out that hazard pointers also need to be assigned using sequentially consistent memory semantics.</p>
<p>Here&#8217;s the case that broke our stack:</p>
<ul class="simple">
<li>Thread 1, in preparation for a Pop operation, reads the head of the stack.</li>
<li>Thread 1 writes the current head to its hazard pointer (using only release semantics, which are weaker than sequentially consistent semantics).</li>
<li>Thread 1 reads the head of the stack again.</li>
<li>Thread 2 removes head from the stack, and passes it to the garbage collector thread (using sequentially consistent memory semantics).</li>
<li>The garbage collector scans the hazard pointers,<br />
and (because the assignment was not done with sequentially consistent memory semantics) is <em>not</em> guaranteed to see thread 1&#8242;s hazard pointer pointing to the node.</li>
<li>The garbage collector deletes the node</li>
<li>Thread 1 dereferences the node, and segfaults.</li>
</ul>
<p>With sequentially consistent memory semantics applied to both the hazard pointer assignment and head modification,<br />
the race condition cannot happen.<br />
This is because for any two sequentially consistent operations, all threads must see them happen in the same order.<br />
So if thread 2 removing the pointer happens first, thread 1 will see a different value on its second read and not attempt to dereference it.<br />
If thread 1 writes to its hazard pointer first, the garbage collector is guaranteed to see that value and not delete the node.</p>
</div>
</div>
<div class="section" id="performance">
<h1>Performance</h1>
<p>Now that we’ve solved the issues with our stack, let&#8217;s take a look at a benchmark.<br />
This test was performed on an 8 core Intel(R) Xeon(R) machine.<br />
The workload consisted of random operations, with Push and Pop equally likely.<br />
The threads were not throttled in any way &#8211; all threads performed as many operations as the machine could handle.</p>
<p><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script><br />
<script src="http://code.highcharts.com/highcharts.js"></script><br />
<script src="http://code.highcharts.com/modules/exporting.js"></script></p>
<div id="container1" style="min-width: 400px; height: 600px; margin: 0 auto"></div>
<p><script>
    var chart;
    $(document).ready(function() {
        chart = new Highcharts.Chart({
            chart: {
                renderTo: 'container1',
                type: 'line',
                marginRight: 130,
                marginBottom: 50
            },
            title: {
                text: 'Stack Throughput',
                x: -20 //center
            },
            subtitle: {
                text: 'Intel(R) Xeon(R) CPU E5620 @ 2.40GHz',
                x: -20
            },
            xAxis: {
                title: {
                    text: 'Threads'
                },
                categories: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
                            14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
                            25, 26, 27, 28, 29, 30, 31, 32 ]
            },
            yAxis: {
                title: {
                    text: 'Througput'
                },
                plotLines: [{
                    value: 0,
                    width: 1,
                    color: '#808080'
                }]
            },
            tooltip: {
                formatter: function() {
                        return '<b>'+ this.series.name +'</b>' +
                        this.x +': '+ this.y;
                 }
            },
            legend: {
                layout: 'vertical',
                align: 'right',
                verticalAlign: 'top',
                x: -10,
                y: 100,
                borderWidth: 0
            },
            series: [{
                name: 'std::mutex implemetation',
                data: [
                        35897346, 9151349, 4265780, 2702898, 3016852, 3418822, 3722790, 3870681,
                        3941228, 4037120, 4050701, 4113459, 4108263, 4164088, 4197925, 4144704,
                        4195454, 4161911, 4218244, 4209897, 4173361, 4175901, 4202012, 4177636,
                        4188165, 4160506, 4185804, 4167197, 4184693, 4183586, 4175180, 4187125 ]
            }, {
                name: 'Naive lockfree implementation',
                data: [
                        43315570, 6590806, 4801719, 4294738, 4278610, 3783040, 3828198, 3539073,
                        3761088, 4033439, 4130918, 4143925, 4282582, 4250531, 4302928, 4233264,
                        4269443, 4237030, 4309971, 4252211, 4275367, 4309706, 4272583, 4294058,
                        4286744, 4304626, 4329975, 4333077, 4306904, 4311042, 4325959, 4337241  ]
            }]
        });
    });
</script>
<p>Well, that&#8217;s not very impressive.</p>
<p>The stack has a single point of contention, and is limited by the rate at which we can modify the head of the stack.<br />
As contention increases, so does the number of failed CompareAndSwap operations.<br />
A simple yet highly effective way to reduce the number of failed operations is simply to sleep after each failed operation.<br />
This naturally throttles the stack to a rate it can effectively handle.<br />
Below is the result of adding &quot;usleep(250)&quot; after any failed operation.</p>
<p><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script><br />
<script src="http://code.highcharts.com/highcharts.js"></script><br />
<script src="http://code.highcharts.com/modules/exporting.js"></script></p>
<div id="container2" style="min-width: 400px; height: 600px; margin: 0 auto"></div>
<p><script>
    var chart;
    $(document).ready(function() {
        chart = new Highcharts.Chart({
            chart: {
                renderTo: 'container2',
                type: 'line',
                marginRight: 130,
                marginBottom: 50
            },
            title: {
                text: 'Stack Throughput',
                x: -20 //center
            },
            subtitle: {
                text: 'Intel(R) Xeon(R) CPU E5620 @ 2.40GHz',
                x: -20
            },
            xAxis: {
                title: {
                    text: 'Threads'
                },
                categories: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
                            14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
                            25, 26, 27, 28, 29, 30, 31, 32 ]
            },
            yAxis: {
                title: {
                    text: 'Througput'
                },
                plotLines: [{
                    value: 0,
                    width: 1,
                    color: '#808080'
                }]
            },
            tooltip: {
                formatter: function() {
                        return '<b>'+ this.series.name +'</b>' +
                        this.x +': '+ this.y;
                 }
            },
            legend: {
                layout: 'vertical',
                align: 'right',
                verticalAlign: 'top',
                x: -10,
                y: 100,
                borderWidth: 0
            },
            series: [{
                name: 'std::mutex implemetation',
                data: [
                        35897346, 9151349, 4265780, 2702898, 3016852, 3418822, 3722790, 3870681,
                        3941228, 4037120, 4050701, 4113459, 4108263, 4164088, 4197925, 4144704,
                        4195454, 4161911, 4218244, 4209897, 4173361, 4175901, 4202012, 4177636,
                        4188165, 4160506, 4185804, 4167197, 4184693, 4183586, 4175180, 4187125 ]
            }, {
                name: 'Naive lockfree implementation',
                data: [
                        43315570, 6590806, 4801719, 4294738, 4278610, 3783040, 3828198, 3539073,
                        3761088, 4033439, 4130918, 4143925, 4282582, 4250531, 4302928, 4233264,
                        4269443, 4237030, 4309971, 4252211, 4275367, 4309706, 4272583, 4294058,
                        4286744, 4304626, 4329975, 4333077, 4306904, 4311042, 4325959, 4337241  ]
            }, {
                name: 'Lockfree implementation with sleeps',
                data: [
                        43666153, 40084659, 40751169, 40189837, 39963036, 39378468, 38674501, 37991135,
                        37351525, 36629465, 36318846, 35629337, 35327952, 35042277, 34614599, 34793151,
                        34427289, 33940550, 33965631, 33754617, 33942473, 33827729, 33577612, 33524987,
                        33409740, 33321596, 33313824, 33249787, 33259567, 33064570, 33342046, 33109555 ]
            }]
        });
    });
</script>
<p>That&#8217;s right, the addition of a sleep improved throughput by roughly 7x!  Furthermore, the addition of usleep(250) reduced processor utilization.  Take a look at the output from HTOP while running each benchmark for 16 threads.</p>
<p>Locked stack:</p>
<p><img alt="htop_mutex.png" src="/blog/wp-content/uploads/2013/03/htop_mutex.png" /></p>
<p>Lock-free stack, no sleep:</p>
<p><img alt="htop_lockfree.png" src="/blog/wp-content/uploads/2013/03/htop_lockfree.png" /></p>
<p>Lock-free stack with usleep(250):</p>
<p><img alt="htop_usleep.png" src="/blog/wp-content/uploads/2013/03/htop_usleep.png" /></p>
<p>So lock-free is better, right?  Well, the lock can be improved as well.  Instead of using std::mutex, we can use a spinlock that performs the same usleep(250) each time it fails to acquire the lock.  Here are the results:</p>
<p><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script><br />
<script src="http://code.highcharts.com/highcharts.js"></script><br />
<script src="http://code.highcharts.com/modules/exporting.js"></script></p>
<div id="container3" style="min-width: 400px; height: 600px; margin: 0 auto"></div>
<p><script>
    var chart;
    $(document).ready(function() {
        chart = new Highcharts.Chart({
            chart: {
                renderTo: 'container3',
                type: 'line',
                marginRight: 130,
                marginBottom: 50
            },
            title: {
                text: 'Stack Throughput',
                x: -20 //center
            },
            subtitle: {
                text: 'Intel(R) Xeon(R) CPU E5620 @ 2.40GHz',
                x: -20
            },
            xAxis: {
                title: {
                    text: 'Threads'
                },
                categories: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
                            14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
                            25, 26, 27, 28, 29, 30, 31, 32 ]
            },
            yAxis: {
                title: {
                    text: 'Througput'
                },
                plotLines: [{
                    value: 0,
                    width: 1,
                    color: '#808080'
                }]
            },
            tooltip: {
                formatter: function() {
                        return '<b>'+ this.series.name +'</b>' +
                        this.x +': '+ this.y;
                 }
            },
            legend: {
                layout: 'vertical',
                align: 'right',
                verticalAlign: 'top',
                x: -10,
                y: 100,
                borderWidth: 0
            },
            series: [{
                name: 'std::mutex implemetation',
                data: [
                        35897346, 9151349, 4265780, 2702898, 3016852, 3418822, 3722790, 3870681,
                        3941228, 4037120, 4050701, 4113459, 4108263, 4164088, 4197925, 4144704,
                        4195454, 4161911, 4218244, 4209897, 4173361, 4175901, 4202012, 4177636,
                        4188165, 4160506, 4185804, 4167197, 4184693, 4183586, 4175180, 4187125 ]
            }, {
                name: 'Naive lockfree implementation',
                data: [
                        43315570, 6590806, 4801719, 4294738, 4278610, 3783040, 3828198, 3539073,
                        3761088, 4033439, 4130918, 4143925, 4282582, 4250531, 4302928, 4233264,
                        4269443, 4237030, 4309971, 4252211, 4275367, 4309706, 4272583, 4294058,
                        4286744, 4304626, 4329975, 4333077, 4306904, 4311042, 4325959, 4337241  ]
            }, {
                name: 'Lockfree implementation with sleeps',
                data: [
                        43666153, 40084659, 40751169, 40189837, 39963036, 39378468, 38674501, 37991135,
                        37351525, 36629465, 36318846, 35629337, 35327952, 35042277, 34614599, 34793151,
                        34427289, 33940550, 33965631, 33754617, 33942473, 33827729, 33577612, 33524987,
                        33409740, 33321596, 33313824, 33249787, 33259567, 33064570, 33342046, 33109555 ]
            }, {
                name: 'Spinlock implementation with sleeps',
                data: [
                        54416870, 47764557, 44120058, 42809938, 40801095, 41278893, 39700878, 39562952,
                        39826669, 39703070, 40243267, 40628533, 40834262, 40531092, 41516055, 40633523,
                        40866936, 40717895, 40371452, 40547040, 40844535, 40543848, 40578820, 40446310,
                        40373348, 40445347, 40374922, 40085105, 40202616, 40008703, 39983415, 40156710 ]
            }]
        });
    });
</script>
<div class="section" id="results">
<h2>Results</h2>
<p>Under high contention, additional threads dramatically reduced overall throughput.  The addition of a sleep reduced contention, and consequently both increased throughput while decreasing processor utilization.<br />
Beyond 3 threads all stacks showed a relatively level performance.<br />
None of the multi-threaded stacks performed better than a single-threaded stack.</p>
</div>
<div class="section" id="conclusion">
<h2>Conclusion</h2>
<p>Lock-free guarantees progress, but it does not guarantee efficiency.  If you want to use lock-free in your applications, make sure that it’s going to be worth it &#8211; both in actual performance and in added complexity.  The lock-free stack presented at the beginning of this article contained a multitude of errors, and even once the errors were fixed it performed no better than the much simpler locked version.  Avoid trying to write your own lock-free algorithms, and look for existing implementations instead.</p>
</div>
<div class="section" id="code">
<h2>Code</h2>
<p>Lock-based.</p>
<pre class="code c literal-block">
<span class="ln"> 1 </span><span class="cp">#include &lt;mutex&gt;
</span><span class="ln"> 2 </span><span class="cp">#include &lt;stack&gt;
</span><span class="ln"> 3 </span><span class="cp"></span>
<span class="ln"> 4 </span><span class="n">template</span><span class="o">&lt;</span><span class="n">class</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="ln"> 5 </span><span class="n">class</span> <span class="n">LockedStack</span><span class="p">{</span>
<span class="ln"> 6 </span><span class="nl">public:</span>
<span class="ln"> 7 </span>    <span class="kt">void</span> <span class="n">Push</span><span class="p">(</span><span class="n">T</span><span class="o">*</span> <span class="n">entry</span><span class="p">){</span>
<span class="ln"> 8 </span>        <span class="n">std</span><span class="o">::</span><span class="n">lock_guard</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">mutex</span><span class="o">&gt;</span> <span class="n">lock</span><span class="p">(</span><span class="n">m_mutex</span><span class="p">);</span>
<span class="ln"> 9 </span>        <span class="n">m_stack</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">entry</span><span class="p">);</span>
<span class="ln">10 </span>    <span class="p">}</span>
<span class="ln">11 </span>
<span class="ln">12 </span>    <span class="c1">// For compatability with the LockFreeStack interface,
</span><span class="ln">13 </span><span class="c1"></span>    <span class="c1">// add an unused int parameter.
</span><span class="ln">14 </span><span class="c1"></span>    <span class="c1">//
</span><span class="ln">15 </span><span class="c1"></span>    <span class="n">T</span><span class="o">*</span> <span class="n">Pop</span><span class="p">(</span><span class="kt">int</span><span class="p">){</span>
<span class="ln">16 </span>        <span class="n">std</span><span class="o">::</span><span class="n">lock_guard</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">mutex</span><span class="o">&gt;</span> <span class="n">lock</span><span class="p">(</span><span class="n">m_mutex</span><span class="p">);</span>
<span class="ln">17 </span>        <span class="k">if</span><span class="p">(</span><span class="n">m_stack</span><span class="p">.</span><span class="n">empty</span><span class="p">()){</span>
<span class="ln">18 </span>            <span class="k">return</span> <span class="n">nullptr</span><span class="p">;</span>
<span class="ln">19 </span>        <span class="p">}</span>
<span class="ln">20 </span>        <span class="n">T</span><span class="o">*</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">m_stack</span><span class="p">.</span><span class="n">top</span><span class="p">();</span>
<span class="ln">21 </span>        <span class="n">m_stack</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
<span class="ln">22 </span>        <span class="k">return</span> <span class="n">ret</span><span class="p">;</span>
<span class="ln">23 </span>    <span class="p">}</span>
<span class="ln">24 </span>
<span class="ln">25 </span><span class="nl">private:</span>
<span class="ln">26 </span>    <span class="n">std</span><span class="o">::</span><span class="n">stack</span><span class="o">&lt;</span><span class="n">T</span><span class="o">*&gt;</span> <span class="n">m_stack</span><span class="p">;</span>
<span class="ln">27 </span>    <span class="n">std</span><span class="o">::</span><span class="n">mutex</span> <span class="n">m_mutex</span><span class="p">;</span>
<span class="ln">28 </span><span class="p">};</span>
</pre>
<p>Lock-free.  The garbage collection interface is omitted, but in real applications you would need to scan the hazard pointers before deleting a node.  The cost of the scan can be amortized by waiting until you have many nodes to delete, and snapshotting the hazard pointers in some data structure with sublinear search times.</p>
<pre class="code c literal-block">
<span class="ln"> 1 </span><span class="n">class</span> <span class="n">LockFreeStack</span><span class="p">{</span>
<span class="ln"> 2 </span><span class="nl">public:</span>
<span class="ln"> 3 </span>    <span class="c1">// The elements we wish to store should inherit Node
</span><span class="ln"> 4 </span><span class="c1"></span>    <span class="c1">//
</span><span class="ln"> 5 </span><span class="c1"></span>    <span class="k">struct</span> <span class="n">Node</span><span class="p">{</span>
<span class="ln"> 6 </span>        <span class="n">boost</span><span class="o">::</span><span class="n">atomic</span><span class="o">&lt;</span><span class="n">Node</span><span class="o">*&gt;</span> <span class="n">next</span><span class="p">;</span>
<span class="ln"> 7 </span>    <span class="p">};</span>
<span class="ln"> 8 </span>
<span class="ln"> 9 </span>    <span class="c1">// Unfortunately, there is no platform independent way to
</span><span class="ln">10 </span><span class="c1"></span>    <span class="c1">// define this class.  The following definition works in
</span><span class="ln">11 </span><span class="c1"></span>    <span class="c1">// gcc on x86_64 architectures
</span><span class="ln">12 </span><span class="c1"></span>    <span class="c1">//
</span><span class="ln">13 </span><span class="c1"></span>    <span class="n">class</span> <span class="n">TaggedPointer</span><span class="p">{</span>
<span class="ln">14 </span>    <span class="nl">public:</span>
<span class="ln">15 </span>        <span class="n">TaggedPointer</span><span class="p">()</span><span class="o">:</span> <span class="n">m_node</span><span class="p">(</span><span class="n">nullptr</span><span class="p">),</span> <span class="n">m_counter</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{}</span>
<span class="ln">16 </span>
<span class="ln">17 </span>        <span class="n">Node</span><span class="o">*</span> <span class="n">GetNode</span><span class="p">(){</span>
<span class="ln">18 </span>            <span class="k">return</span> <span class="n">m_node</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">memory_order_acquire</span><span class="p">);</span>
<span class="ln">19 </span>        <span class="p">}</span>
<span class="ln">20 </span>
<span class="ln">21 </span>        <span class="kt">uint64_t</span> <span class="n">GetCounter</span><span class="p">(){</span>
<span class="ln">22 </span>            <span class="k">return</span> <span class="n">m_counter</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">memory_order_acquire</span><span class="p">);</span>
<span class="ln">23 </span>        <span class="p">}</span>
<span class="ln">24 </span>
<span class="ln">25 </span>        <span class="n">bool</span> <span class="n">CompareAndSwap</span><span class="p">(</span><span class="n">Node</span><span class="o">*</span> <span class="n">oldNode</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="n">oldCounter</span><span class="p">,</span> <span class="n">Node</span><span class="o">*</span> <span class="n">newNode</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="n">newCounter</span><span class="p">){</span>
<span class="ln">26 </span>            <span class="n">bool</span> <span class="n">cas_result</span><span class="p">;</span>
<span class="ln">27 </span>            <span class="n">__asm__</span> <span class="n">__volatile__</span>
<span class="ln">28 </span>            <span class="p">(</span>
<span class="ln">29 </span>                <span class="s">&quot;lock;&quot;</span>           <span class="c1">// This makes the following instruction atomic (it is non-blocking)
</span><span class="ln">30 </span><span class="c1"></span>                <span class="s">&quot;cmpxchg16b %0;&quot;</span>  <span class="c1">// cmpxchg16b sets ZF on success
</span><span class="ln">31 </span><span class="c1"></span>                <span class="s">&quot;setz       %3;&quot;</span>  <span class="c1">// if ZF set, set cas_result to 1
</span><span class="ln">32 </span><span class="c1"></span>
<span class="ln">33 </span>                <span class="o">:</span> <span class="s">&quot;+m&quot;</span> <span class="p">(</span><span class="o">*</span><span class="n">this</span><span class="p">),</span> <span class="s">&quot;+a&quot;</span> <span class="p">(</span><span class="n">oldNode</span><span class="p">),</span> <span class="s">&quot;+d&quot;</span> <span class="p">(</span><span class="n">oldCounter</span><span class="p">),</span> <span class="s">&quot;=q&quot;</span> <span class="p">(</span><span class="n">cas_result</span><span class="p">)</span>
<span class="ln">34 </span>                <span class="o">:</span> <span class="s">&quot;b&quot;</span> <span class="p">(</span><span class="n">newNode</span><span class="p">),</span> <span class="s">&quot;c&quot;</span> <span class="p">(</span><span class="n">newCounter</span><span class="p">)</span>
<span class="ln">35 </span>                <span class="o">:</span> <span class="s">&quot;cc&quot;</span><span class="p">,</span> <span class="s">&quot;memory&quot;</span>
<span class="ln">36 </span>            <span class="p">);</span>
<span class="ln">37 </span>            <span class="k">return</span> <span class="n">cas_result</span><span class="p">;</span>
<span class="ln">38 </span>        <span class="p">}</span>
<span class="ln">39 </span>    <span class="nl">private:</span>
<span class="ln">40 </span>        <span class="n">boost</span><span class="o">::</span><span class="n">atomic</span><span class="o">&lt;</span><span class="n">Node</span><span class="o">*&gt;</span> <span class="n">m_node</span><span class="p">;</span>
<span class="ln">41 </span>        <span class="n">boost</span><span class="o">::</span><span class="n">atomic</span><span class="o">&lt;</span><span class="kt">uint64_t</span><span class="o">&gt;</span> <span class="n">m_counter</span><span class="p">;</span>
<span class="ln">42 </span>    <span class="p">}</span>
<span class="ln">43 </span>    <span class="c1">// 16-byte alignment is required for double-width
</span><span class="ln">44 </span><span class="c1"></span>    <span class="c1">// compare and swap
</span><span class="ln">45 </span><span class="c1"></span>    <span class="c1">//
</span><span class="ln">46 </span><span class="c1"></span>    <span class="n">__attribute__</span><span class="p">((</span><span class="n">aligned</span><span class="p">(</span><span class="mi">16</span><span class="p">)));</span>
<span class="ln">47 </span>
<span class="ln">48 </span>    <span class="n">bool</span> <span class="n">TryPushStack</span><span class="p">(</span><span class="n">Node</span><span class="o">*</span> <span class="n">entry</span><span class="p">){</span>
<span class="ln">49 </span>        <span class="n">Node</span><span class="o">*</span> <span class="n">oldHead</span><span class="p">;</span>
<span class="ln">50 </span>        <span class="kt">uint64_t</span> <span class="n">oldCounter</span><span class="p">;</span>
<span class="ln">51 </span>
<span class="ln">52 </span>        <span class="n">oldHead</span> <span class="o">=</span> <span class="n">m_head</span><span class="p">.</span><span class="n">GetNode</span><span class="p">();</span>
<span class="ln">53 </span>        <span class="n">oldCounter</span> <span class="o">=</span> <span class="n">m_head</span><span class="p">.</span><span class="n">GetCounter</span><span class="p">();</span>
<span class="ln">54 </span>        <span class="n">entry</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">.</span><span class="n">store</span><span class="p">(</span><span class="n">oldHead</span><span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">memory_order_relaxed</span><span class="p">);</span>
<span class="ln">55 </span>        <span class="k">return</span> <span class="n">m_head</span><span class="p">.</span><span class="n">CompareAndSwap</span><span class="p">(</span><span class="n">oldHead</span><span class="p">,</span> <span class="n">oldCounter</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">oldCounter</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="ln">56 </span>    <span class="p">}</span>
<span class="ln">57 </span>
<span class="ln">58 </span>    <span class="n">bool</span> <span class="n">TryPopStack</span><span class="p">(</span><span class="n">Node</span><span class="o">*&amp;</span> <span class="n">oldHead</span><span class="p">,</span> <span class="kt">int</span> <span class="n">threadId</span><span class="p">){</span>
<span class="ln">59 </span>        <span class="n">oldHead</span> <span class="o">=</span> <span class="n">m_head</span><span class="p">.</span><span class="n">GetNode</span><span class="p">();</span>
<span class="ln">60 </span>        <span class="kt">uint64_t</span> <span class="n">oldCounter</span> <span class="o">=</span> <span class="n">m_head</span><span class="p">.</span><span class="n">GetCounter</span><span class="p">();</span>
<span class="ln">61 </span>        <span class="k">if</span><span class="p">(</span><span class="n">oldHead</span> <span class="o">==</span> <span class="n">nullptr</span><span class="p">){</span>
<span class="ln">62 </span>            <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="ln">63 </span>        <span class="p">}</span>
<span class="ln">64 </span>        <span class="n">m_hazard</span><span class="p">[</span><span class="n">threadId</span><span class="o">*</span><span class="mi">8</span><span class="p">].</span><span class="n">store</span><span class="p">(</span><span class="n">oldHead</span><span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">memory_order_seq_cst</span><span class="p">);</span>
<span class="ln">65 </span>        <span class="k">if</span><span class="p">(</span><span class="n">m_head</span><span class="p">.</span><span class="n">GetNode</span><span class="p">()</span> <span class="o">!=</span> <span class="n">oldHead</span><span class="p">){</span>
<span class="ln">66 </span>            <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="ln">67 </span>        <span class="p">}</span>
<span class="ln">68 </span>        <span class="k">return</span> <span class="n">m_head</span><span class="p">.</span><span class="n">CompareAndSwap</span><span class="p">(</span><span class="n">oldHead</span><span class="p">,</span> <span class="n">oldCounter</span><span class="p">,</span> <span class="n">oldHead</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">memory_order_acquire</span><span class="p">),</span> <span class="n">oldCounter</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="ln">69 </span>    <span class="p">}</span>
<span class="ln">70 </span>
<span class="ln">71 </span>    <span class="kt">void</span> <span class="n">Push</span><span class="p">(</span><span class="n">Node</span><span class="o">*</span> <span class="n">entry</span><span class="p">){</span>
<span class="ln">72 </span>        <span class="k">while</span><span class="p">(</span><span class="nb">true</span><span class="p">){</span>
<span class="ln">73 </span>            <span class="k">if</span><span class="p">(</span><span class="n">TryPushStack</span><span class="p">(</span><span class="n">entry</span><span class="p">)){</span>
<span class="ln">74 </span>                <span class="k">return</span><span class="p">;</span>
<span class="ln">75 </span>            <span class="p">}</span>
<span class="ln">76 </span>            <span class="n">usleep</span><span class="p">(</span><span class="mi">250</span><span class="p">);</span>
<span class="ln">77 </span>        <span class="p">}</span>
<span class="ln">78 </span>    <span class="p">}</span>
<span class="ln">79 </span>
<span class="ln">80 </span>    <span class="n">Node</span><span class="o">*</span> <span class="n">Pop</span><span class="p">(</span><span class="kt">int</span> <span class="n">threadId</span><span class="p">){</span>
<span class="ln">81 </span>        <span class="n">Node</span><span class="o">*</span> <span class="n">res</span><span class="p">;</span>
<span class="ln">82 </span>        <span class="k">while</span><span class="p">(</span><span class="nb">true</span><span class="p">){</span>
<span class="ln">83 </span>            <span class="k">if</span><span class="p">(</span><span class="n">TryPopStack</span><span class="p">(</span><span class="n">res</span><span class="p">,</span> <span class="n">threadId</span><span class="p">)){</span>
<span class="ln">84 </span>                <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
<span class="ln">85 </span>            <span class="p">}</span>
<span class="ln">86 </span>            <span class="n">usleep</span><span class="p">(</span><span class="mi">250</span><span class="p">);</span>
<span class="ln">87 </span>        <span class="p">}</span>
<span class="ln">88 </span>    <span class="p">}</span>
<span class="ln">89 </span>
<span class="ln">90 </span><span class="nl">private:</span>
<span class="ln">91 </span>    <span class="n">TaggedPointer</span> <span class="n">m_head</span><span class="p">;</span>
<span class="ln">92 </span>    <span class="c1">// Hazard pointers are separated into different cache lines to avoid contention
</span><span class="ln">93 </span><span class="c1"></span>    <span class="c1">//
</span><span class="ln">94 </span><span class="c1"></span>    <span class="n">boost</span><span class="o">::</span><span class="n">atomic</span><span class="o">&lt;</span><span class="n">Node</span><span class="o">*&gt;</span> <span class="n">m_hazard</span><span class="p">[</span><span class="n">MAX_THREADS</span><span class="o">*</span><span class="mi">8</span><span class="p">];</span>
<span class="ln">95 </span><span class="p">};</span>
</pre>
<p>The code is also available on github (if you want to test it locally): <a class="reference external" href="https://github.com/memsql/lockfree-bench">https://github.com/memsql/lockfree-bench</a></p>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://developers.memsql.com/blog/common-pitfalls-in-writing-lock-free-algorithms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Where Should TopCoders Work. One Year Later.</title>
		<link>http://developers.memsql.com/blog/where-should-topcoders-work-one-year-later/</link>
		<comments>http://developers.memsql.com/blog/where-should-topcoders-work-one-year-later/#comments</comments>
		<pubDate>Sun, 23 Sep 2012 21:39:26 +0000</pubDate>
		<dc:creator>MemSQL Engineering</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://developers.memsql.com/blog/?p=258</guid>
		<description><![CDATA[A little over a year ago we published a blog post “Where Should Top Coders Work?”. In a few weeks we were approached by topcoder.com and offered to sponsor TopCoder Open. We hired two amazing folks after that event, and &#8230; <a href="http://developers.memsql.com/blog/where-should-topcoders-work-one-year-later/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A little over a year ago we published a blog post “<a title="Where Should Top Coders Work?" href="http://developers.memsql.com/blog/where-should-top-coders-work/">Where Should Top Coders Work?</a>”. In a few weeks we were approached by topcoder.com and offered to sponsor TopCoder Open. We hired two amazing folks after that event, and two more joined as interns. With a handful of red TopCoders working on the engine, we&#8217;ve had a great relationship with the TopCoder community.</p>
<p>When I published the original blog post, I had absolute faith into the TopCoder brand, but we had nothing to really back it up. Since a year has passed, I thought it&#8217;d be worthwhile to share what our Top Coders have been working on.</p>
<h2>What have TopCoders built at MemSQL?</h2>
<p>Here at MemSQL, engineers have a lot of freedom in deciding what to work on. Instead of saying “we have a great team solving hard problems,&#8221; I&#8217;d like to share what each TopCoder has worked on since joining the company.</p>
<p><a href="http://community.topcoder.com/tc?module=MemberProfile&amp;cr=22777893">Pieguy</a>. David fell in love with concurrency and lock-free data structures. He has built/improved our entire lock-free story.  David is also great at finding tough race conditions by studying the code and investigating various concurrency scenarios including finding a bug in a well-known, lock-free paper (<a href="http://www.research.ibm.com/people/m/michael/podc-1996.pdf">http://www.research.ibm.com/people/m/michael/podc-1996.pdf</a>). TopCoder trains people to read and understand code very well.</p>
<p><a href="http://community.topcoder.com/tc?module=MemberProfile&amp;cr=20315020">Nika</a>. Nika tackled the challenges in implementing joins and subqueries, which included building an updated optimizer, an artificial intelligence component that decides what indexes and what join order to use in a complex query.</p>
<p><a href="http://www.google.com/url?q=http%3A%2F%2Fcommunity.topcoder.com%2Ftc%3Fmodule%3DMemberProfile%26cr%3D22661890&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNHHrSQvkGkgwZwsypxsZkpraCamlQ">Momchil</a>. As an intern, Momchil worked on various components of the codebase, but he really got hooked working on distributed query execution. By the end of his internship MemSQL was able to run queries like the one below in a distributed environment over a 100 node cluster (actual use case):</p>
<pre>select x.i, x.a, x.b, o.c, o.x from (select * from t) as x left join (select c, count(*) as x from ob group by c) o on x.a = o.c</pre>
<p>Check out Momchil&#8217;s blog in which he writes about <a href="http://wantrepreneur.net/2012/09/09/memsql-my-first-real-startup-experience/">his experience</a> at MemSQL.</p>
<p><a href="http://community.topcoder.com/tc?module=MemberProfile&amp;cr=22712322">Decowboy</a>. While interning at MemSQL, Jelle worked on replication. He helped with the robust design and implemented major components of the feature. This is a highly technical project that involved transaction log shipping and recovery on the slave, failover, and resiliency to all kinds of DDL (data definition language) such as create/drop table and create drop database, etc.</p>
<p><a href="http://community.topcoder.com/tc?module=MemberProfile&amp;cr=22662189">SkidanovAlex</a>. Alex is the first MemSQL TopCoder and he has contributed to all the major components of MemSQL. He has been a crucial contributor to MemSQL&#8217;s distributed product.</p>
<p>The list can go on and it’s just the highlights of what the TopCoder crew has built.</p>
<h2>What can TopCoders learn at MemSQL?</h2>
<p>Databases are complex at every level: storage engines, optimizers, parsers, distributed systems &#8211; things most regular developers don&#8217;t work with on a day-to-day basis.</p>
<p>In a famous blog post (<a href="http://herbsutter.com/welcome-to-the-jungle/">http://herbsutter.com/welcome-to-the-jungle/</a>), Herb Sutter claims:</p>
<ul>
<li>Applications will need to be at least massively parallel, and ideally able to use non-local cores and heterogeneous cores.</li>
<li>Efficiency and performance optimization will get more, not less, important.</li>
<li>Programming languages and systems will increasingly be forced to deal with heterogeneous distributed parallelism.</li>
</ul>
<p>MemSQL is at the forefront of building massively parallel software. For engineers who possess a solid foundation in problem solving with algorithms and data structures, MemSQL is a great place to build these skills.</p>
<h2>Why do TopCoders succeed at MemSQL?</h2>
<p>Apart from the obvious such as an incredibly high IQ, excellent problem solving skills, and proficiency in algorithms, there is one trait that we find very attractive: TopCoders love to code. If you code a lot every day it generates a compound effect. You are getting much better and more productive.</p>
<h2>Startup vs Big Company</h2>
<p>Growth and opportunity are crucial for a successful engineering culture. Unfortunately, big company environments often hinder growth potential because of bureaucracy and a lack of emphasis on engineering culture. We are lucky to have very hard problems in spades and have no bureaucratic roadblocks for a TopCoder to grow and advance his or her career.</p>
<h2>Are we going to hire more TopCoders?</h2>
<p>We are happy to announce that we are sponsoring TopCoder Open once again and to keep our doors open for more amazing engineers coming out of this unique community.</p>
<p>Being a TopCoder is not a prerequisite for working at MemSQL, but being a great engineer is. Please find us at <a href="mailto:careers@memsql.com">careers@memsql.com</a></p>
]]></content:encoded>
			<wfw:commentRss>http://developers.memsql.com/blog/where-should-topcoders-work-one-year-later/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MemSQL: My First *Real* Startup Experience</title>
		<link>http://developers.memsql.com/blog/memsql-my-first-real-startup-experience/</link>
		<comments>http://developers.memsql.com/blog/memsql-my-first-real-startup-experience/#comments</comments>
		<pubDate>Tue, 11 Sep 2012 02:33:17 +0000</pubDate>
		<dc:creator>momchil</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://developers.memsql.com/blog/?p=242</guid>
		<description><![CDATA[This is reposted from Momchil Tomov&#8217;s blog. Momchil was part of the first summer batch of MemSQL Interns. After seemingly stumbling into their office by accident, getting interviewed on a lark, and receiving an offer as my Christmas gift, I &#8230; <a href="http://developers.memsql.com/blog/memsql-my-first-real-startup-experience/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<blockquote><p>This is reposted from Momchil Tomov&#8217;s <a href="http://wantrepreneur.net/2012/09/09/memsql-my-first-real-startup-experience/">blog</a>. Momchil was part of the first summer batch of MemSQL Interns.</p></blockquote>
<p>After seemingly stumbling into their office by accident, getting interviewed on a lark, and receiving an offer as my Christmas gift, I kept an open mind for what to expect from <a href="http://www.memsql.com">MemSQL</a>. The one-year-old YC alum was set to build the world’s fastest database, leaving competitors like MySQL and MongoDB in the dust. Very ambitious indeed.</p>
<p>From day one, I was thrown in the fire pit. Someone had to finish the <a title="Workload Simulator" href="https://github.com/memsql/workload-simulator">Workload Simulator</a>, an important developer tool, before the launch. Everyone was super busy fixing bugs and polishing the product, so I had to do a quick Javascript/Flask/Python crash course and jump on it. After eight long nights, a thousand lines of code, and a huge amount of support from Ankur, my mentor, the Workload Simulator was finished to coincide with launch.</p>
<p>I spent the next month working on code generation: writing code that compiles SQL to C++, the core strength of MemSQL. Once I got acquainted with the codebase, Ankur decided to step up my game with data compression. I had to find a way to compress 10 TB of random strings down to at most 5 TB without compromising the speed of the transactions, and I had two weeks to do so. After some research, experimentation, and lots of dumb luck, I managed to bring it down to 2 TB. It required all the MemSQL knowledge I had obtained thus far, including things I learned during my interview.</p>
<p>Just as I finished the first prototype, I joined the team working on sharding. Sharding is what enables MemSQL to get distributed across multiple machines, an important feature of every scalable database and also an important feature for our biggest clients. I was onboarded on Sunday, began work on Monday, and shipped my first code review on Tuesday. One of the dev leads, Ankur, gauged my progress, and kept assigning me more and more sharding tasks, slowly walking me through the implementation of Distributed MemSQL. Just as a father silently lets go of the back seat of his kid’s bicycle, he slowly backed away and moved on to testing and bug fixing. Before realizing it, I found myself working on the team with no safety wheels, full speed ahead, pushing the forefront of MemSQL. I was no longer an intern. I was a full-time MemSQL engineer.</p>
<p>They say Princetonians work hard and play really really hard. If that’s true, then MemSQL felt even more like home. From the <a title="Feeding Grizzly" href="http://gourmet.memsql.com/">extraordinarily delicious meals</a> prepared by our in-house chef Daniel, to the post-launch Las Vegas Celebration Trip, to the relaxing Saturdays on <a title="imonaboat" href="http://wantrepreneurdotnet.files.wordpress.com/2012/09/imonaboat1.jpg">Vasili’s boat</a> underneath the Golden Gate, the MemSQL team knows how to have a good time. As MemSQL is growing, I sincerely hope they maintain their great culture of ridiculous engineering and chill free time. I had an amazing summer many thanks to the incredible people at 380 10th Street. I wish Eric, Nikita, Marko, Vasili, Alex, Masha, Nika, Pieguy, Adam, Ankur, Daniel, et al. all the best and hope they build a company 300x better than the rest!</p>
<p><strong>Go MemSQL!</strong></p>
<p><a href="http://wantrepreneurdotnet.files.wordpress.com/2012/09/cimg1174.jpg"><img class="wp-image-6 aligncenter" title="CIMG1174" src="http://wantrepreneurdotnet.files.wordpress.com/2012/09/cimg1174.jpg?w=600&amp;h=450" alt="" width="600" height="450" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://developers.memsql.com/blog/memsql-my-first-real-startup-experience/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Excellent Post On MemSQL Architecture</title>
		<link>http://developers.memsql.com/blog/excellent-post-on-memsql-architecture/</link>
		<comments>http://developers.memsql.com/blog/excellent-post-on-memsql-architecture/#comments</comments>
		<pubDate>Wed, 15 Aug 2012 02:28:15 +0000</pubDate>
		<dc:creator>MemSQL Engineering</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://developers.memsql.com/blog/?p=225</guid>
		<description><![CDATA[http://highscalability.com/blog/2012/8/14/memsql-architecture-the-fast-mvcc-inmem-lockfree-codegen-and.html]]></description>
			<content:encoded><![CDATA[<p><a href="http://highscalability.com/blog/2012/8/14/memsql-architecture-the-fast-mvcc-inmem-lockfree-codegen-and.html">http://highscalability.com/blog/2012/8/14/memsql-architecture-the-fast-mvcc-inmem-lockfree-codegen-and.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://developers.memsql.com/blog/excellent-post-on-memsql-architecture/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Loading half a billion records in 40 minutes</title>
		<link>http://developers.memsql.com/blog/loading-half-a-billion-records-into-memsql/</link>
		<comments>http://developers.memsql.com/blog/loading-half-a-billion-records-into-memsql/#comments</comments>
		<pubDate>Mon, 13 Aug 2012 18:58:19 +0000</pubDate>
		<dc:creator>MemSQL Engineering</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://developers.memsql.com/blog/?p=210</guid>
		<description><![CDATA[Disclaimer. This will not be an apples to apples comparison with derwik, since we obviously don’t have the same dataset, and we need a much bigger machine to load everything into memory. But I believe this experiment will get the &#8230; <a href="http://developers.memsql.com/blog/loading-half-a-billion-records-into-memsql/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Disclaimer. This will not be an apples to apples comparison with derwik, since we obviously don’t have the same dataset, and we need a much bigger machine to load everything into memory. But I believe this experiment will get the point across. So without further ado, let’s go through the steps.</p>
<p>Adam Derewecki wrote a <a href="http://derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql">cool post</a> about his experience loading half a billion records into MySQL. MemSQL is a MySQL-compatible drop-in replacement that is built from the ground up to run really fast in memory.</p>
<p>Disclamer: this isn’t an apples-to-apples comparison with derwik since we don’t have his dataset and need a much beefier machine to load everything into memory.</p>
<h1 dir="ltr">Schema</h1>
<p>Here is the schema for the table. Note that the table has three indexes. On top of it memsql will automatically generate a primary index under the covers. We won’t be disabling keys.</p>
<pre>drop table if exists store_sales_fact;
create table store_sales_fact( 
       date_key                smallint not null,
       pos_transaction_number  integer not null,
       sales_quantity          smallint not null,
       sales_dollar_amount     smallint not null,
       cost_dollar_amount      smallint not null,
       gross_profit_dollar_amount smallint not null,
       transaction_type        varchar(16) not null,
       transaction_time        time not null,
       tender_type             char(6) not null,
       product_description     varchar(128) not null,
       sku_number              char(12) not null,
       store_name              char(10) not null,
       store_number            smallint not null,
       store_city              varchar(64) not null,
       store_state             char(2) not null,
       store_region            varchar(64) not null,
       key date_key(date_key),
       key store_region(store_region),
       key store_state(store_state)
);</pre>
<p>&nbsp;</p>
<h1 dir="ltr">Hardware</h1>
<p>We have a very cool machine, with 64 cores and 512 GB of RAM, from <a href="http://www.peakhosting.com/">Peak Hosting</a> . You can rent one for yourself for a little under two grand a month. They were kind enough to give it to us to use for free. Here is a spec of one core.</p>
<pre>vendor_id       : AuthenticAMD
cpu family      : 21
model           : 1
model name      : AMD Opteron(TM) Processor 6276
stepping        : 2
cpu MHz         : 2300.254
cache size      : 2048 KB</pre>
<p dir="ltr">You read that correctly, this machine has sixty-four 2.3 GHz cores and 512 GB of RAM or almost 8 times the largest memory footprint available in the cloud today, all on dedicated hardware with no virtualization overhead or resource contention with other unknown third parties.</p>
<h1 dir="ltr">Loading efficiently</h1>
<p>Loading data efficiently is actually not that trivial. The best way of doing it with MemSQL is to use as much CPU as you can get. Here are a few tricks that can be applied.</p>
<h2 dir="ltr">1. Multi-inserts</h2>
<p>We can batch inserts into 100 row multi-inserts. This will reduce the number of network roundtrips. Each roundtrip now accounts for 100 rows instead of one. Here is what multi-inserts look like.</p>
<pre>insert into store_sales_fact values('1','1719','4','280','97','183','purchase','14:09:10','Cash','Brand #6 chicken noodle soup','SKU-#6','Store71','71','Lancaster','CA','West'),
('1','1719','4','280','97','183','purchase','14:09:10','Cash','Brand #5 golf clubs','SKU-#5','Store71','71','Lancaster','CA','West'),
('1','1719','4','280','97','183','purchase','14:09:10','Cash','Brand #4 brandy','SKU-#4','Store71','71','Lancaster','CA','West'),</pre>
<h2>2. Load in parallel.</h2>
<p>Our customer has a sample file of  510,593,334 records. We can use the command line mysql client to pipe this file into MemSQL, but this would not leverage all the cores available in the system. So ideally we should spit the file to at least as many chunks as there are CPUs in the system.</p>
<h2 dir="ltr">3. Increase granularity</h2>
<p>Splitting the file into 64 big chunks will introduce a data skew. The total data load time will be the time the slowest thread loads the data. To address this problem we will split the file into thousands of chunks. And every time a thread frees up we will start loading another chunk. So we split the file into 2000 chunks.</p>
<pre> 1 -rw-r--r--  1  35662844 2012-06-06 11:42 data10.sql
 2 -rw-r--r--  1  35651723 2012-06-06 11:42 data11.sql
 3 -rw-r--r--  1  35658433 2012-06-06 11:42 data12.sql
 4 -rw-r--r--  1  35663665 2012-06-06 11:42 data13.sql
 5 -rw-r--r--  1  35667480 2012-06-06 11:42 data14.sql
 6 -rw-r--r--  1  35659549 2012-06-06 11:42 data15.sql
 7 -rw-r--r--  1  35661617 2012-06-06 11:42 data16.sql
 8 -rw-r--r--  1  35650414 2012-06-06 11:42 data17.sql
 9 -rw-r--r--  1  35661625 2012-06-06 11:42 data18.sql
10 -rw-r--r--  1  35667634 2012-06-06 11:42 data19.sql
11 -rw-r--r--  1  35662989 2012-06-06 11:42 data1.sql</pre>
<h2 dir="ltr">4. Load script. The load script uses python multiprocessing library to load data efficiently.</h2>
<pre> 1 import re
 2 import sys
 3 import os
 4 import multiprocessing
 5 import optparse
 6
 7 parser = optparse.OptionParser()
 8 parser.add_option("-D", "--database", help="database name")
 9 parser.add_option("-P", "--port", help="port to connect. use 3306 to connect to memsql and 3307 to connect to mysql", type="int")
 10 (options, args) = parser.parse_args()
 11
 12 if not options.database or not options.port:
 13     parser.print_help()
 14     exit(1)
 15
 16 total_files = 2000
 17
 18 def load_file(filename):
 19     try:
 20         print "loading from cpu: %d" % os.getpid()
 21         query = 'mysql -h 127.0.0.1 -D %s -u root -P %d &lt; %s' % (options.database, options.port, filename)
 22         print query
 23         os.system(query)
 24         print "done loading from cpu: %d" % os.getpid()
 25     except e as Exception:
 26         print e
 27         pass
 28
 29 os.system('echo "delete from store_sales_fact" | mysql -h 127.0.0.1 -u root -P %d' % options.port)
 30 p = multiprocessing.Pool(processes = 2*multiprocessing.cpu_count())
 31 for j in range(0, total_files):
 32     p.apply_async(load_file, ['data/data%d.sql' % j])
 33
 34 p.close()
 35 p.join()</pre>
<h2 dir="ltr">5. Running it</h2>
<p>I started loading by issuing the following command.</p>
<pre dir="ltr">time python load.py -D test -P 3306</pre>
<p>After we do this let’s start htop to check the processor saturation. It looks pretty busy <img src='http://developers.memsql.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .<br />
<img src="https://lh4.googleusercontent.com/c-rO176IaxVGuS0aXOzv5Ap2jeUhsFQtnRWAozw5o7FAUsQP2UmZbyJsW8GoiRAJ-XsbG4KfqKlGLI2TmtVqDRmhTVcrT8RU_ZYqx9gsM73E00-pjA" alt="" width="634px;" height="357px;" /><br />
MemSQL uses lockfree data structures that eliminate a lot of contention.</p>
<p>It took a bit of time, but the data has been loaded.</p>
<pre> real    39m21.465s
 user    33m53.210s
 sys     5m24.470s</pre>
<p>The result is almost 200K inserts a second for a table with 4 indexes. The memory footprint of the memsql process is 267 Gb.</p>
<h1 dir="ltr">Running the same test against mysql</h1>
<p>I would not be fair to skip comparison with mysql, particularly that it’s so easy to do since memsql uses mysql wire protocol and support mysql syntax. I used the my.cnf settings from <a href="http://derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql">http://derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql</a><br />
and fired up the same command</p>
<pre>time python load.py -D test -P 3307</pre>
<pre>real    536m0.376s
user    27m17.130s
sys     5m36.780s</pre>
<p>I did not disable indexes for this run to make it fair compared to MemSQL.</p>
<h1 dir="ltr">Conclusion</h1>
<p>With the <a href="http://www.peakhosting.com/">Peak Hosting</a> offering of 512Gb of RAM and memory optimized software like MemSQL you can save full business days in data loading and get immediate, valuable insight into your data.</p>
]]></content:encoded>
			<wfw:commentRss>http://developers.memsql.com/blog/loading-half-a-billion-records-into-memsql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reading Between the Benchmarks: How MemSQL Designs for Speed and Durability</title>
		<link>http://developers.memsql.com/blog/reading-between-the-benchmarks/</link>
		<comments>http://developers.memsql.com/blog/reading-between-the-benchmarks/#comments</comments>
		<pubDate>Mon, 25 Jun 2012 21:11:24 +0000</pubDate>
		<dc:creator>Jelle</dc:creator>
				<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://developers.memsql.com/blog/?p=59</guid>
		<description><![CDATA[Foreword There&#8217;s been a lot of discussion recently about how MemSQL compares to MySQL and other databases. Prior to the recent controversy, we were planning to publish the post below, where we jump in and describe a workload that we &#8230; <a href="http://developers.memsql.com/blog/reading-between-the-benchmarks/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Foreword</strong></p>
<p>There&#8217;s been a lot of discussion recently about how MemSQL compares to MySQL and other databases. Prior to the recent controversy, we were planning to publish the post below, where we jump in and describe a workload that we ran against MemSQL, MySQL, and MongoDB, all configured for asynchronous durability, on a few different hardware scenarios. Before that, though, we&#8217;d like to address some of the comments.</p>
<p>First, we&#8217;ve built MemSQL with a sensible set of trade-offs around index performance and durability in mind. The customers that we&#8217;ve worked with and optimized for have indeed seen on average a 30 times improvement for their workloads. Of course, just the fact that their data now lives in memory is a major part of the boost. But an important point is that MemSQL&#8217;s ease-of-use is what gets them there in the first place. MemSQL helps to relieve the cost of engineering caching or NoSQL infrastructure that syncs back to a database like MySQL.</p>
<p>Of course, we must consider MySQL&#8217;s in-memory performance. Jelle, one of our interns, explores this below by tuning InnoDB to behave like MemSQL. But the short answer is that MemSQL is a lot faster. And that&#8217;s because the database has been engineered from the ground up to run in memory. Everything from the index data structures (lock-free skip lists and hash tables) to every detail of our durability (log and snapshot format, transaction buffer, etc.) was designed and built for the in-memory, archive-to-disk use case.</p>
<p>Even though MemSQL runs in memory, it logs transactions to disk as fast as the disk will write. MemSQL uses an in-memory transaction buffer that is flushed to disk in a separate log flusher thread. By the time a transaction commits in memory, it has been written to the in-memory buffer. If the amount of data in the buffer exceeds <code>transaction-buffer</code> MB, then writes block until there is space available. Both MongoDB and MySQL are often run with similar configurations.</p>
<p>We expose the performance of this component through the <code>show status</code> query as <code>Transaction_buffer_wait_time.</code> This value measures the cumulative amount of time transaction threads have blocked trying to insert into the transaction buffer. The default size of the transaction buffer, 128 MB, is a heuristic: most disks can easily sequentially write 128 MB/s, so you shouldn&#8217;t lose more than a second of data. Visit the <a href="http://developers.memsql.com/docs/1b/durability.html">durability page</a> in our documentation for more information.</p>
<p>We haven&#8217;t yet encountered a client who has asked us to optimize MemSQL for synchronous durability. Nevertheless, we know how to improve it in our current design and can discuss this in a future post.</p>
<p>The post below is meant to be a seed for you to run your own experiments with MemSQL. Since we can&#8217;t cover every workload, hardware configuration, and database in a benchmark, we&#8217;ve built something simple that runs MemSQL, MySQL, and MongoDB and we hope it will enable the community to continue running its own experiments. The more data points we have, the more we can improve the product.</p>
<p>- MemSQL Engineering</p>
<hr />
<p>When I joined MemSQL at the beginning of this summer, I decided to write a small benchmark to see on my own how fast MemSQL can be. One of MemSQL’s main strengths is its highly optimized lock-free skiplist implementation. This means that MemSQL should scale almost linearly on machines with many cores. To explore this, I wrote a benchmark comparing the performance of MemSQL, MongoDB, and MySQL. My benchmark simulates a simplified online multiplayer game, with the database responsible for tracking players, games and events. The code for the benchmark is available on <a href="http://www.github.com/memsql/bench">github.com/memsql/bench</a> and can easily be extended to other databases.</p>
<h2>The databases</h2>
<p>The two databases I compared against MemSQL are MySQL and MongoDB. MemSQL is wire compatible with MySQL, so a comparison is natural and very easy. MemSQL and MongoDB have radically different interfaces as MongoDB is a NoSQL database. However, MongoDB is a popular choice for social applications so considering its performance is worthwhile as well.</p>
<p>MemSQL is an in-memory database that stores all the contents of the database in RAM but backs up to disk. MongoDB and MySQL store their data on disk, though can be configured to cache the contents of the disk in RAM and asynchronously write changes back to disk. This fundamental difference influences exactly how MemSQL, MongoDB and MySQL store their data-structures: MemSQL uses lock-free skip lists and hash tables to store its data, whereas MongoDB and MySQL use disk-optimized B-trees.</p>
<h2>Description of the benchmark</h2>
<p>The benchmark tests performance of the database when used as the backend for an online turn based multiplayer game. It was inspired by mobile phone versions of games such as multiplayer chess. For the core game logic, the database stores players and games. To track statistics, the database also stores a log of all past game actions and average game lengths.</p>
<p><img class="aligncenter" src="https://lh4.googleusercontent.com/BgnZ6TIJKiwfv9aJVbQWZzwiLRVTzeYGlSmBDBeY2pVNvwFQqyUasjuxgginYKZiP01ZphXC2SGDtRD7Z3Q6p7vmjZOLL9eHcmkUi46PNo267uDBrZc" alt="" width="480px;" height="220px;" /></p>
<p>The database stores four kinds of objects:</p>
<ul>
<li>Players. Every player has an ID, and two statistics: the number of games started and the number of games won.</li>
<li>Games. Each game has an ID, two players and a turn.</li>
<li>Game length statistics. We store a histogram of finished game lengths, composed of a game length and an integer counting the number of games.</li>
<li>Events. Finally, every action performed is stored as an up to 32-character description, together with a timestamp and a player ID.</li>
</ul>
<p>The benchmark simulates many players simultaneously playing games. Several Python worker processes each simulate hundreds of players. Each worker continually picks a player and then simulates one player action. All actions are logged in the events table. This logic is implemented in <a href="https://github.com/memsql/bench/blob/master/benchmark.py">benchmark.py</a>, and executes according to the following diagram: <img class="aligncenter" src="https://lh3.googleusercontent.com/D7Hhn6ovSOufJ2O5Hpuk2nF4Bem3W7qqjjO2Ab7OBx73FvgN4xmE3uoRzSqh18xfVxKGT47D3eFp48USOGrNBdDgs4LWGg_fa7jLKyUrEs03pRvZkaA" alt="" width="553px;" height="645px;" /> To support this simulation, the database needs to support several operations: find all games a player is currently playing, create a game, store statistics, etc. In the benchmark, these operations are described in<a href="https://github.com/memsql/bench/blob/master/base_database.py"> base_database.py</a>. Database-specific implementations can be found in<a href="https://github.com/memsql/bench/blob/master/sql_database.py"> sql_database.py</a> and<a href="https://github.com/memsql/bench/blob/master/mongo_database.py"> mongo_database.py</a>. Since MySQL and MemSQL are protocol compatible, sql_database.py implements the interface for both MySQL and MemSQL. The MongoDB implementation can be found in <a href="https://github.com/memsql/bench/blob/master/mongo_database.py">mongo_database.py</a>.</p>
<p>To support efficient queries, I added indices on all player ID fields. To allow efficient exploration of past events, I also added an index to the timestamp column in the events table. In MongoDB, the timestamp column is integrated in the object ID and is thus simpler. Furthermore, in MongoDB, embedded documents can be used as an alternative to seperate queries with indices. In this benchmark, I could have stored the list of active games in each player object. However, since each game is used by two players, I decided against this approach as it would move all writes to the player table. That would be an undesirable situation as MongoDB has a per collection write lock.</p>
<h2>Settings used</h2>
<p>By default, MySQL flushes after every transaction. To make MySQL behave like MongoDB and MemSQL, I set up MySQL to use a transaction buffer. The settings different from the default Ubuntu settings are the following:</p>
<pre>default-storage-engine=INNODB
innodb_buffer_pool_size = 4GB
innodb_log_file_size = 128M
innodb_log_buffer_size = 4M
innodb_flush_log_at_trx_commit=2
innodb_thread_concurrency=0
innodb_flush_method=O_DIRECT
innodb_file_per_table</pre>
<p>MemSQL and MongoDB are running with their default configurations, which means both are durable and use a transaction buffer. This means that all databases are configured to behave the same way. I used the latest stable version of each database (MongoDB 2.0.6, MySQL 5.5.25, MemSQL 1b).</p>
<h2>Results</h2>
<p>I ran the benchmark for 10 minutes on several machines. I first ran it on my old MacBook Pro (running Ubuntu natively), which has a dual core Intel(R) Core(TM) 2 Duo T9400. After that, I tried a server with 8 Intel(R) Xeon(R) cores, each running at 2.4GHz. Finally, I tried a 24 core machine with AMD(R) Opteron(TM) processors, each core clocking in at a 1.9GHz. For the two and eight core machines, the benchmark client was running on the same server as the database. For the 24 core machine the benchmark was running on a different server, directly connected over gigabit ethernet. The benchmark is configured to use 140 worker processes and 4000 players per worker process. This can be changed in<a href="https://github.com/memsql/bench/blob/master/config.py"> config.py</a>. I achieved the following number of actions (as described above) processed per second:</p>
<div id="benchmark-results-graph" style="min-width: 400px; height: 400px; margin: 0 auto;"></div>
<p><script type="text/javascript" src="http://developers.memsql.com/blog/wp-content/themes/twentyeleven/js/graphs.js"></script>In all of these configurations, MemSQL outperforms both MongoDB and MySQL. Going from 2 to 8 cores, MemSQL improves its performanced by a factor 5. MySQL is almost four times as fast, and MongoDB is almost three times as fast as in the 2 core scenario. When going from 8 to 24 cores, MemSQL performs more than 3 times faster. However, MongoDB and MySQL perform slower than before. To verify this effect, I limited MongoDB and MySQL to run on 8 of the 24 cores, and they performed about as well as they did running on <em>all</em> 24 cores.</p>
<p>In this benchmark, MemSQL is significantly faster on all fronts. On two cores, MemSQL benefits from its efficient query parsing and pre-compiled code per query. When scaling from two to eight cores, all three databases are able to take advantage of the faster hardware. However, MemSQL scales better thanks to its lock-free data-structures which allow all 8 cores to interact efficiently with the database at once. The 24 core machine has individual cores slower than the individual cores of the 8 core machine. MongoDB and MySQL are not capable of taking advantage of these extra cores; instead, their performance degrades due to the slower cores. MemSQL on the other hand has a speed increase, as it is able to take advantage of all the available cores.</p>
<p>As a final note, the performance of all databases does not change significantly over time. I sampled the number of actions per second every second over the 10 minute run on the 24 core machine, and performance doesn’t change:</p>
<div id="time-series-chart" style="min-width: 400px; height: 400px; margin: 0 auto;"></div>
<p>&nbsp;</p>
<h2></h2>
<h2>Conclusion</h2>
<p>In the end, this simulation is just that: a simulation. But it demonstrates that MemSQL is very fast and scales well for write-heavy workloads like this game. We want this code to serve as a template for benchmarking MemSQL and other databases.</p>
<p>We made a strong effort to configure MySQL and MongoDB fairly. These tests can also be run on a variety of different hardware scenarios, network configurations, and modified workloads. There are even tune-able parameters within the provided benchmark (number of worker processes, number of players). We are as interested as you are to see your findings with MemSQL against other databases and in other benchmarks.</p>
<p>To explore MemSQL on your own, visit <a href="http://www.memsql.com/#download">the MemSQL download page</a> and get the developer edition. If you choose to <a href="http://developers.memsql.com/docs/1b/guides/ec2.html">set up a MemSQL AMI on Amazon EC2</a>, you can get the database up and running on an 8 core machine in less than 5 minutes. The code for this benchmark is <a href="https://github.com/memsql/bench">available on github</a>. Happy Benchmarking!</p>
]]></content:encoded>
			<wfw:commentRss>http://developers.memsql.com/blog/reading-between-the-benchmarks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Where Should Top Coders Work?</title>
		<link>http://developers.memsql.com/blog/where-should-top-coders-work/</link>
		<comments>http://developers.memsql.com/blog/where-should-top-coders-work/#comments</comments>
		<pubDate>Mon, 18 Jun 2012 03:49:45 +0000</pubDate>
		<dc:creator>Nikita Shamgunov</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://developers.memsql.com/blog/?p=33</guid>
		<description><![CDATA[My career as a software engineer really began when I won a medal at the ACM ICPC programming contest in 2001. To place in the tournament, I had spent 24 hours traveling from Russia to Vancouver and back, just to &#8230; <a href="http://developers.memsql.com/blog/where-should-top-coders-work/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p dir="ltr">My career as a software engineer really began when I won a medal at the ACM ICPC programming contest in 2001. To place in the tournament, I had spent 24 hours traveling from Russia to Vancouver and back, just to spend 5 hours on the actual competition.</p>
<p dir="ltr">The rules are simple: you have 5 hours to solve up to 12 problems. For each problem you need to implement a small program in Java or C++ and send it to the jury. They compile it and run it through an extremely intensive set of tests. Only if it passes every test will the jury count your submission.</p>
<p dir="ltr">Even though it only marked the beginning of my career, it had taken 4 years of intense preparation to place at the tournament &#8211; 4 years of training, learning to think fast, practicing on weekends, and other sorts of mental gymnastics. ACM was a good school for me. I<br />
loved it, but I wasn’t alone.</p>
<h2>Is it really hard to become a Top Coder?</h2>
<p>Becoming an ACP ICPC medalist in 2011 is about 20 times harder than it was in 2001. People who can do it now are coding machines and algorithm junkies. They practice every day on TopCoder, Google Code Jam, and Code Force to stay sharp. They memorize whole books filled with algorithms and equations in case they need a tool to solve a problem quicker than their opponent. It should be no surprise that this programming subculture has caught the attention of many great companies.</p>
<p>So where do programming contest winners go and work? It used to be Microsoft (where I started my career), then Google. Now it’s Facebook. These companies know how valuable top coders are. Microsoft, Google and Facebook wouldn’t be where they are without exceptional engineers.</p>
<h2>How do Top Coders fare after graduation?</h2>
<p>They fare very well and tend to build their careers at big companies. Many are attracted to the high salary right out of school. However, according to <a href="http://topcoder.com/home/blog/2008/01/">topcoder.com</a>, many ultimately find work at large companies to be tedious and less challenging than the mental jujitsu of programming contests.</p>
<p>Large teams have the luxury of compartmentalizing a problem to reduce complexity. This creates an unfortunate side effect: these smaller problems just aren&#8217;t that interesting.</p>
<p>In addition, many ICPC champions soon miss the dynamic of small teams, the kind their experienced while training and competing during university.</p>
<p>As it so happens, there is a time in a company&#8217;s history when it&#8217;s perfect for a top coder to join &#8211; when the company&#8217;s just getting started.</p>
<h2>Why do some Top Coders found/join an early-stage startup?</h2>
<p>For the challenge, of course.</p>
<p>Just take a look at these real-life examples:</p>
<ol>
<li><a href="http://www.businessinsider.com/what-i-learned-from-being-cto-of-facebook-why-i-started-quora-and-this-is-why-gen-y-kicks-ass-at-entrepreneurship-2010-9">Adam D’Angelo</a> was a finalist in the international Topcoder Collegiate Challenge in 2005. Later he was VP and CTO of Facebook and then left to found Quora.</li>
<li><a href="http://en.wikipedia.org/wiki/Nikolai_Durov">Nikolai Durov</a> is Employee #1 at the biggest Russian social network <em>vkontakte</em>. It beats Facebook on the Russian market. He could’ve gone to Google or stayed in academia, but he made a small bet that had lots of upside.</li>
<li>One of my team members Leonid Volkov went to an early stage company and built the &#8220;TurboTax of Russia&#8221;. He enjoyed an incredibly successful exit, and he&#8217;s since gone into politics.</li>
<li><a href="http://startuphoodlum.com/tag/topcoder/">Prasanna Sankaranarayanan</a> is the founder of LikeALittle and was the highest ranked Top Coder in India. It took him one year at Microsoft to realize that the perfect job for a Top Coder is at an early stage startup.</li>
</ol>
<p>Small startups offer Top Coders lots of responsibility and with it the trust and autonomy to solve tough problems.</p>
<h2>Top Coders at MemSQL</h2>
<p>Today, MemSQL has four Top Coders. I won a bronze medal in ACM ICPC in 2001, and <a href="http://www.topcoder.com/tc?module=MemberProfile&amp;cr=22662189">Alex Skidanov</a> was a Top Coder #13 in 2008 and ACM ICPC #3 Champion. A Top Coder would feel right at home at MemSQL. Here, we work on hard algorithmic and systems-level problems, distributed systems, and cloud infrastructure. We also now have Top Coders who ranked #4 and #8 in algorithms. Sometimes it’s scary to leave a big corporation, but the truth is that apart from fun, market pay, and the potential of a huge upside, a good early stage startup gives the kind of experience that makes a Top Coder extremely relevant in today’s tech industry.</p>
<p>If you&#8217;d like to learn more, shoot us an email at <a href="mailto:topcoders@memsql.com">topcoders@memsql.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://developers.memsql.com/blog/where-should-top-coders-work/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Welcome to the MemSQL Developer Blog!</title>
		<link>http://developers.memsql.com/blog/welcome-to-the-memsql-developer-blog/</link>
		<comments>http://developers.memsql.com/blog/welcome-to-the-memsql-developer-blog/#comments</comments>
		<pubDate>Mon, 18 Jun 2012 03:41:08 +0000</pubDate>
		<dc:creator>MemSQL Engineering</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://developers.memsql.com/blog/?p=46</guid>
		<description><![CDATA[We&#8217;ve been hard at work building the world&#8217;s fastest database, and now that we&#8217;re shipping MemSQL, we&#8217;re looking forward to having a bit more time to blog about some of the fundamentals around the MemSQL technology. In the coming weeks, &#8230; <a href="http://developers.memsql.com/blog/welcome-to-the-memsql-developer-blog/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve been hard at work building the world&#8217;s fastest database, and now that we&#8217;re shipping MemSQL, we&#8217;re looking forward to having a bit more time to blog about some of the fundamentals around the MemSQL technology.</p>
<p>In the coming weeks, we&#8217;ll be publishing posts that cover an array of topics, including benchmarking, stress testing, database theories, algorithms, and more.</p>
<p>In the mean time, we encourage you to <a href="http://www.memsql.com/#download">download MemSQL</a> and have some fun doing your own benchmarking. We&#8217;ve also published a <a href="http://github.com/memsql">workload simulator on Github</a> to help get you started in the right direction.</p>
<p>Thanks for dropping by and we look forward to a lot of great posts and discussions.</p>
]]></content:encoded>
			<wfw:commentRss>http://developers.memsql.com/blog/welcome-to-the-memsql-developer-blog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
