<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>cosmic realms</title>
  <link href="http://cosmicrealms.com/atom.xml" rel="self"/>
  <link href="http://cosmicrealms.com/"/>
  <updated>2012-01-13T16:00:58-05:00</updated>
  <id>http://cosmicrealms.com/</id>
  <author>
    <name>Sembiance (Robert Schultz)</name>
    
      <email>robert@cosmicrealms.com</email>
    
  </author>

  
  <entry>
    <title>Benchmark of node.js JSON Validation Modules</title>
    <link href="http://cosmicrealms.com/blog/2012/01/13/benchmark-of-node-dot-js-json-validation-modules/"/>
    <updated>2012-01-13T14:33:00-05:00</updated>
    <id>http://cosmicrealms.com/blog/2012/01/13/benchmark-of-node-dot-js-json-validation-modules</id>
    <content type="html">&lt;p&gt;I need to validate JSON in a node.js project I am working on.&lt;/p&gt;

&lt;p&gt;Speed is critical in my project, so I decided to benchmark several node.js JSON validation modules.&lt;/p&gt;

&lt;p&gt;I only included modules that support the JSON schema described here: &lt;a href=&quot;http://json-schema.org/&quot;&gt;http://json-schema.org/&lt;/a&gt;&lt;/p&gt;

&lt;p style=&quot;margin-bottom: 0;&quot;&gt;The following modules were benchmarked:&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt; &lt;a href=&quot;https://github.com/kriszyp/json-schema&quot;&gt;https://github.com/kriszyp/json-schema&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href=&quot;https://github.com/akidee/schema.js&quot;&gt;https://github.com/akidee/schema.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href=&quot;https://github.com/garycourt/JSV&quot;&gt;https://github.com/garycourt/JSV&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Two JSON objects and schemas were used, one basic and one advanced. The source code for these are at the bottom of this post.&lt;/p&gt;

&lt;p&gt;Due to varying module support, I had to create both a v2 and v3 schema document.&lt;/p&gt;

&lt;h3&gt;Results&lt;/h3&gt;


&lt;div id=&quot;basicResults&quot;&gt;&lt;/div&gt;


&lt;script&gt;new Highcharts.Chart(
{
    chart :
    {
        renderTo : &quot;basicResults&quot;,
        defaultSeriesType : &quot;column&quot;,
        backgroundColor : &quot;transparent&quot;
    },
    credits : { enabled : false },
    title : { text : &quot;10,000 Iterations - Basic Object&quot; },
    xAxis : { categories : [ &quot;JSV (v2)&quot;, &quot;JSV (v3)&quot;, &quot;schema (v2)&quot;, &quot;json-schema (v3)&quot; ] },
    yAxis : { title : { text : &quot;Time Per Validation&quot; } },
    legend : { enabled : false },
    tooltip :
    {
        formatter : function()
        {
            return &quot;&lt;b&gt;&quot; + this.x + &quot;&lt;/b&gt;&lt;br/&gt;&quot; + &quot;Time Per Validation: &quot; + this.y + &quot;ms&quot;;
        }
    },
    series :
    [{
        data : [ 0.45, 0.49, 0.03, 0.01 ],
        dataLabels : 
        {
            enabled : true,
            formatter : function()
            {
                return this.y + &quot;ms&quot;;
            },
            style : { fontWeight : &quot;bold&quot; }
        }
    }]
}
);&lt;/script&gt;




&lt;br&gt;


&lt;br&gt;


&lt;br&gt;




&lt;div id=&quot;advancedResults&quot;&gt;&lt;/div&gt;


&lt;script&gt;new Highcharts.Chart(
{
    chart :
    {
        renderTo : &quot;advancedResults&quot;,
        defaultSeriesType : &quot;column&quot;,
        backgroundColor : &quot;transparent&quot;
    },
    credits : { enabled : false },
    title : { text : &quot;10,000 Iterations - Advanced Object&quot; },
    xAxis : { categories : [ &quot;JSV (v2)&quot;, &quot;JSV (v3)&quot;, &quot;schema (v2)&quot;, &quot;json-schema (v3)&quot; ] },
    yAxis : { title : { text : &quot;Time Per Validation&quot; } },
    legend : { enabled : false },
    tooltip :
    {
        formatter : function()
        {
            return &quot;&lt;b&gt;&quot; + this.x + &quot;&lt;/b&gt;&lt;br/&gt;&quot; + &quot;Time Per Validation: &quot; + this.y + &quot;ms&quot;;
        }
    },
    series :
    [{
        data : [ 2.21, 2.27, 0.08, 0.09 ],
        dataLabels : 
        {
            enabled : true,
            formatter : function()
            {
                return this.y + (this.y===0.1 ? &quot;0&quot; : &quot;&quot;) + &quot;ms&quot;;
            },
            style : { fontWeight : &quot;bold&quot; }
        }
    }]
}
);&lt;/script&gt;




&lt;br&gt;


&lt;br&gt;




&lt;h3&gt;Conclusion&lt;/h3&gt;


&lt;p&gt;Looks like JSV is the slowest, even more so when dealing with V3 of the JSON schema. Also note that we are using a pre-processed JSV JSON schema. When that wasn&amp;#8217;t used, JSV was an additional 20 times slower.&lt;/p&gt;

&lt;p&gt;So easy conclusion right? Use json-schema or schema as they are the fastest?&lt;/p&gt;

&lt;p&gt;Well, it turns out that  bothjson-schema and schema lack supprt for serveral properties mentioned in the spec such as divisibleBy, uniqueItems and format.&lt;/p&gt;

&lt;p&gt;For my project I&amp;#8217;m not currently using any unsupported properties, so I&amp;#8217;ll be choosing json-schema for it&amp;#8217;s speed.&lt;/p&gt;

&lt;p&gt;In the future if I need to use an unsupported property, I can always just add it to json-schema myself and send a pull request :)&lt;/p&gt;

&lt;h3&gt;Modules not used&lt;/h3&gt;




&lt;p style=&quot;margin-bottom: 0;&quot;&gt;These modules were NOT tested due to each having a custom JSON schema format:&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt; &lt;a href=&quot;https://github.com/observing/gatekeeper&quot;&gt;https://github.com/observing/gatekeeper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href=&quot;https://github.com/zzdhidden/EVE&quot;&gt;https://github.com/zzdhidden/EVE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href=&quot;http://doffm.github.com/Onvalid/onvalid.html&quot;&gt;http://doffm.github.com/Onvalid/onvalid.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href=&quot;https://github.com/Baggz/Amanda&quot;&gt;https://github.com/Baggz/Amanda&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p style=&quot;margin-bottom: 0;&quot;&gt;Lastly this module was also not tested because it lacks support for the &amp;#8216;required&amp;#8217; attribute:&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt; &lt;a href=&quot;https://github.com/onirame/json-validate&quot;&gt;https://github.com/onirame/json-validate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Source Code&lt;/h3&gt;


&lt;p&gt;Here are the JSON data objects and schema used for the benchmarks:&lt;/p&gt;

&lt;div&gt;&lt;script src=&#8217;https://gist.github.com/1608305.js?file=&#8217;&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;{
    fullName : &amp;quot;John Doe&amp;quot;,
    age : 47,
    state : &amp;quot;Massachusetts&amp;quot;,
    city : &amp;quot;Boston&amp;quot;,
    zip : 02201,
    married : false,
    dozen : 12,
    dozenOrBakersDozen : 13,
    favoriteEvenNumber : 14,
    topThreeFavoriteColors : [ &amp;quot;red&amp;quot;, &amp;quot;magenta&amp;quot;, &amp;quot;cyan&amp;quot; ],
    favoriteSingleDigitWholeNumbers : [ 7 ],
    favoriteFiveLetterWord : &amp;quot;coder&amp;quot;,
    emailAddresses : 
    [
        &amp;quot;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@letters-in-local.org&amp;quot;,
        &amp;quot;01234567890@numbers-in-local.net&amp;quot;,
        &amp;quot;&amp;amp;&#8217;*+-./=?^_{}~@other-valid-characters-in-local.net&amp;quot;,
        &amp;quot;mixed-1234-in-{+^}-local@sld.net&amp;quot;,
        &amp;quot;a@single-character-in-local.org&amp;quot;,
        &amp;quot;\&amp;quot;quoted\&amp;quot;@sld.com&amp;quot;,
        &amp;quot;\&amp;quot;&#92;e&#92;s&#92;c&#92;a&#92;p&#92;e&#92;d\&amp;quot;@sld.com&amp;quot;,
        &amp;quot;\&amp;quot;quoted-at-sign@sld.org\&amp;quot;@sld.com&amp;quot;,
        &amp;quot;\&amp;quot;escaped&#92;\&amp;quot;quote\&amp;quot;@sld.com&amp;quot;,
        &amp;quot;\&amp;quot;back&#92;slash\&amp;quot;@sld.com&amp;quot;,
        &amp;quot;one-character-third-level@a.example.com&amp;quot;,
        &amp;quot;single-character-in-sld@x.org&amp;quot;,
        &amp;quot;local@dash-in-sld.com&amp;quot;,
        &amp;quot;letters-in-sld@123.com&amp;quot;,
        &amp;quot;one-letter-sld@x.org&amp;quot;,
        &amp;quot;uncommon-tld@sld.museum&amp;quot;,
        &amp;quot;uncommon-tld@sld.travel&amp;quot;,
        &amp;quot;uncommon-tld@sld.mobi&amp;quot;,
        &amp;quot;country-code-tld@sld.uk&amp;quot;,
        &amp;quot;country-code-tld@sld.rw&amp;quot;,
        &amp;quot;local@sld.newTLD&amp;quot;,
        &amp;quot;the-total-length@of-an-entire-address.cannot-be-longer-than-two-hundred-and-fifty-four-characters.and-this-address-is-254-characters-exactly.so-it-should-be-valid.and-im-going-to-add-some-more-words-here.to-increase-the-lenght-blah-blah-blah-blah-bla.org&amp;quot;,
        &amp;quot;the-character-limit@for-each-part.of-the-domain.is-sixty-three-characters.this-is-exactly-sixty-three-characters-so-it-is-valid-blah-blah.com&amp;quot;,
        &amp;quot;local@sub.domains.com&amp;quot;
    ],
    ipAddresses : [ &amp;quot;127.0.0.1&amp;quot;, &amp;quot;24.48.64.2&amp;quot;, &amp;quot;192.168.1.1&amp;quot;, &amp;quot;209.68.44.3&amp;quot;, &amp;quot;2.2.2.2&amp;quot; ]
}&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;



</content>
  </entry>
  
  <entry>
    <title>Web Traffic Time Analysis by Server, Client and Client IP</title>
    <link href="http://cosmicrealms.com/blog/2011/10/30/time-analysis-by-server/"/>
    <updated>2011-10-30T15:34:00-04:00</updated>
    <id>http://cosmicrealms.com/blog/2011/10/30/time-analysis-by-server</id>
    <content type="html">&lt;p&gt;Traffic analysis for &lt;a href=&quot;http://worldofsolitaire.com&quot;&gt;World of Solitaire&lt;/a&gt; shows more visits on the weekdays compared to the weekends.&lt;/p&gt;

&lt;p&gt;I suspect that this is due to people playing solitaire from work and school. I wanted to see at what hour of the day people are visiting to see if it is during normal work and school hours.&lt;/p&gt;

&lt;p&gt;Measuring with just the server time however wouldn&amp;#8217;t give an accurate measurement of what time of day it truly was at the visitor&amp;#8217;s geographic location in the world.&lt;/p&gt;

&lt;p&gt;I measured each visit three different ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The server&amp;#8217;s time&lt;/li&gt;
&lt;li&gt;  The client&amp;#8217;s actual local time (read by javascript in their browser)&lt;/li&gt;
&lt;li&gt;  The client&amp;#8217;s IP address (converted to a city/time zone using GeoIP)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The data was collected over a 1 week period from Sun Oct 16 to Sat Oct 22.&lt;/p&gt;

&lt;p&gt;Here are the visits broken down by day:&lt;/p&gt;

&lt;div id=&quot;byDay&quot;&gt;&lt;/div&gt;


&lt;script&gt;new Highcharts.Chart(
{
    chart :
    {
        renderTo : &quot;byDay&quot;,
        defaultSeriesType : &quot;line&quot;,
        backgroundColor : &quot;transparent&quot;
    },
    credits : { enabled : false },
    title : { text : &quot;Visits - By Day&quot; },
    xAxis : { categories : [ &quot;Sunday&quot;, &quot;Monday&quot;, &quot;Tuesdau&quot;, &quot;Wednesday&quot;, &quot;Thursday&quot;, &quot;Friday&quot;, &quot;Saturday&quot; ] },
    yAxis :
    {
        title : { text : &quot;Visits&quot; },
        plotLines : [ { value : 0, width : 1, color : &quot;#808080&quot; } ]
    },
    legend : { enabled : false },
    tooltip :
    {
        formatter : function()
        {
            return &quot;&lt;b&gt;&quot; + this.series.name + &quot;&lt;/b&gt;&lt;br/&gt;&quot; + this.x + &quot;: &quot; + Highcharts.numberFormat(this.y, 0, &#8216;,&#8217;) + &quot; visits&quot;;
        }
    },
    legend :
    {
        layout : &quot;vetical&quot;,
        align : &quot;right&quot;,
        verticalAlign : &quot;top&quot;,
        borderWidth : 0
    },
    series :
    [
        { &quot;name&quot; : &quot;Server&quot;, &quot;data&quot; : [179495,234366,234568,235632,230686,216782,170246] },
        { &quot;name&quot; : &quot;IP&quot;,     &quot;data&quot; : [177824,234386,234644,235364,230721,218387,170449] },
        { &quot;name&quot; : &quot;Client&quot;, &quot;data&quot; : [177406,234192,234006,235082,230341,217767,169878] }
    ]
}
);&lt;/script&gt;


&lt;p&gt;All three show pretty much the same thing. Most of my traffic comes from the states and my server is located here, so it looks like at a &amp;#8216;day&amp;#8217; level, using the server time is reliable.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s break it down by hour:&lt;/p&gt;

&lt;div id=&quot;weekByHour&quot;&gt;&lt;/div&gt;


&lt;script&gt;new Highcharts.Chart(
{
    chart :
    {
        renderTo : &quot;weekByHour&quot;,
        defaultSeriesType : &quot;line&quot;,
        backgroundColor : &quot;transparent&quot;
    },
    credits : { enabled : false },
    title : { text : &quot;Visits - By Hour (Full Week)&quot; },
    xAxis :
    {
        tickInterval : 6,
        categories : [ &quot;12AM&quot;, &quot;1AM&quot;, &quot;2AM&quot;, &quot;3AM&quot;, &quot;4AM&quot;, &quot;5AM&quot;, &quot;6AM&quot;, &quot;7AM&quot;, &quot;8AM&quot;, &quot;9AM&quot;, &quot;10AM&quot;, &quot;11AM&quot;,
                       &quot;12PM&quot;, &quot;1PM&quot;, &quot;2PM&quot;, &quot;3PM&quot;, &quot;4PM&quot;, &quot;5PM&quot;, &quot;6PM&quot;, &quot;7PM&quot;, &quot;8PM&quot;, &quot;9PM&quot;, &quot;10PM&quot;, &quot;11PM&quot; ],
        labels :
        {
            step : 1,
            x : 100,
            formatter : function()
            {
                if(this.value==&quot;12AM&quot;)
                    return &quot;Midnight to 6AM&quot;;
                else if(this.value==&quot;6AM&quot;)
                    return &quot;6AM to Noon&quot;;
                else if(this.value==&quot;12PM&quot;)
                    return &quot;Noon to 6PM&quot;;
                else if(this.value==&quot;6PM&quot;)
                    return &quot;6PM to Midnight&quot;;
            }
        }
    },
    yAxis :
    {
        title : { text : &quot;Visits&quot; },
        plotLines : [ { value : 0, width : 1, color : &quot;#808080&quot; } ]
    },
    legend : { enabled : false },
    tooltip :
    {
        formatter : function()
        {
            return &quot;&lt;b&gt;&quot; + this.series.name + &quot;&lt;/b&gt;&lt;br/&gt;&lt;b&gt;&quot; + this.x + &quot;&lt;/b&gt;: &quot; + Highcharts.numberFormat(this.y, 0, &#8216;,&#8217;) + &quot; visits&quot;;
        }
    },
    legend :
    {
        layout : &quot;vetical&quot;,
        align : &quot;right&quot;,
        verticalAlign : &quot;top&quot;,
        borderWidth : 0
    },
    series :
    [
        {&quot;name&quot;:&quot;Server&quot;,&quot;data&quot;:[31827,27249,24394,25146,27437,34174,44214,57596,68062,76144,83290,86645,87511,89494,93779,94263,87063,78223,76082,73590,72032,66413,55470,41677]},
        {&quot;name&quot;:&quot;IP&quot;,&quot;data&quot;:[23996,14086,9577,7717,8294,14309,27184,45516,64568,76303,82624,87844,92680,94519,97704,103869,103858,90196,84694,88529,90382,85215,65813,42298]},
        {&quot;name&quot;:&quot;Client&quot;,&quot;data&quot;:[25090,13797,8576,6521,6923,11804,23864,40925,62340,75981,83063,87985,94171,95655,98271,104455,106472,90442,83224,86933,89551,86464,70107,46058]}
    ]
}
);&lt;/script&gt;


&lt;p&gt;Now this is much more interesting! It shows that measuring with just the server time is not an accurate reading of what time of day people visit.&lt;/p&gt;

&lt;p&gt;There is a 20% drop in visits between 4PM and 6PM, right about the time people would leave work and school.&lt;/p&gt;

&lt;p&gt;The above graph was for the entire week. What about looking only at weekdays and weekends, will we see something different?&lt;/p&gt;

&lt;div id=&quot;weekdayByHour&quot;&gt;&lt;/div&gt;


&lt;script&gt;new Highcharts.Chart(
{
    chart :
    {
        renderTo : &quot;weekdayByHour&quot;,
        defaultSeriesType : &quot;line&quot;,
        backgroundColor : &quot;transparent&quot;
    },
    credits : { enabled : false },
    title : { text : &quot;Visits - By Hour (Weekdays)&quot; },
    xAxis :
    {
        tickInterval : 6,
        categories : [ &quot;12AM&quot;, &quot;1AM&quot;, &quot;2AM&quot;, &quot;3AM&quot;, &quot;4AM&quot;, &quot;5AM&quot;, &quot;6AM&quot;, &quot;7AM&quot;, &quot;8AM&quot;, &quot;9AM&quot;, &quot;10AM&quot;, &quot;11AM&quot;,
                       &quot;12PM&quot;, &quot;1PM&quot;, &quot;2PM&quot;, &quot;3PM&quot;, &quot;4PM&quot;, &quot;5PM&quot;, &quot;6PM&quot;, &quot;7PM&quot;, &quot;8PM&quot;, &quot;9PM&quot;, &quot;10PM&quot;, &quot;11PM&quot; ],
        labels :
        {
            step : 1,
            x : 100,
            formatter : function()
            {
                if(this.value==&quot;12AM&quot;)
                    return &quot;Midnight to 6AM&quot;;
                else if(this.value==&quot;6AM&quot;)
                    return &quot;6AM to Noon&quot;;
                else if(this.value==&quot;12PM&quot;)
                    return &quot;Noon to 6PM&quot;;
                else if(this.value==&quot;6PM&quot;)
                    return &quot;6PM to Midnight&quot;;
            }
        }
    },
    yAxis :
    {
        title : { text : &quot;Visits&quot; },
        plotLines : [ { value : 0, width : 1, color : &quot;#808080&quot; } ]
    },
    legend : { enabled : false },
    tooltip :
    {
        formatter : function()
        {
            return &quot;&lt;b&gt;&quot; + this.series.name + &quot;&lt;/b&gt;&lt;br/&gt;&lt;b&gt;&quot; + this.x + &quot;&lt;/b&gt;: &quot; + Highcharts.numberFormat(this.y, 0, &#8216;,&#8217;) + &quot; visits&quot;;
        }
    },
    legend :
    {
        layout : &quot;vetical&quot;,
        align : &quot;right&quot;,
        verticalAlign : &quot;top&quot;,
        borderWidth : 0
    },
    series :
    [
        {&quot;name&quot;:&quot;Server&quot;,&quot;data&quot;:[23635,20622,18408,19385,21212,27064,35266,45856,53481,59555,65324,67698,68493,69933,73999,73906,66689,58720,56642,53973,52983,48379,40391,30420]},
        {&quot;name&quot;:&quot;IP&quot;,&quot;data&quot;:[16858,9642,6790,5507,6244,11353,22107,36320,50827,59238,64186,69406,73771,75274,77475,82709,81040,67970,63243,65573,66709,62704,48038,30518]},
        {&quot;name&quot;:&quot;Client&quot;,&quot;data&quot;:[17571,9408,5908,4592,5119,9218,19209,32731,49153,59379,64884,69122,75135,76246,78242,83548,84133,68265,61567,64195,65792,63590,51095,33286]}
    ]
}
);&lt;/script&gt;




&lt;div id=&quot;weekendByHour&quot;&gt;&lt;/div&gt;


&lt;script&gt;new Highcharts.Chart(
{
    chart :
    {
        renderTo : &quot;weekendByHour&quot;,
        defaultSeriesType : &quot;line&quot;,
        backgroundColor : &quot;transparent&quot;
    },
    credits : { enabled : false },
    title : { text : &quot;Visits - By Hour (Weekends)&quot; },
    xAxis :
    {
        tickInterval : 6,
        categories : [ &quot;12AM&quot;, &quot;1AM&quot;, &quot;2AM&quot;, &quot;3AM&quot;, &quot;4AM&quot;, &quot;5AM&quot;, &quot;6AM&quot;, &quot;7AM&quot;, &quot;8AM&quot;, &quot;9AM&quot;, &quot;10AM&quot;, &quot;11AM&quot;,
                       &quot;12PM&quot;, &quot;1PM&quot;, &quot;2PM&quot;, &quot;3PM&quot;, &quot;4PM&quot;, &quot;5PM&quot;, &quot;6PM&quot;, &quot;7PM&quot;, &quot;8PM&quot;, &quot;9PM&quot;, &quot;10PM&quot;, &quot;11PM&quot; ],
        labels :
        {
            step : 1,
            x : 100,
            formatter : function()
            {
                if(this.value==&quot;12AM&quot;)
                    return &quot;Midnight to 6AM&quot;;
                else if(this.value==&quot;6AM&quot;)
                    return &quot;6AM to Noon&quot;;
                else if(this.value==&quot;12PM&quot;)
                    return &quot;Noon to 6PM&quot;;
                else if(this.value==&quot;6PM&quot;)
                    return &quot;6PM to Midnight&quot;;
            }
        }
    },
    yAxis :
    {
        title : { text : &quot;Visits&quot; },
        plotLines : [ { value : 0, width : 1, color : &quot;#808080&quot; } ]
    },
    legend : { enabled : false },
    tooltip :
    {
        formatter : function()
        {
            return &quot;&lt;b&gt;&quot; + this.series.name + &quot;&lt;/b&gt;&lt;br/&gt;&lt;b&gt;&quot; + this.x + &quot;&lt;/b&gt;: &quot; + Highcharts.numberFormat(this.y, 0, &#8216;,&#8217;) + &quot; visits&quot;;
        }
    },
    legend :
    {
        layout : &quot;vetical&quot;,
        align : &quot;right&quot;,
        verticalAlign : &quot;top&quot;,
        borderWidth : 0
    },
    series :
    [
        {&quot;name&quot;:&quot;Server&quot;,&quot;data&quot;:[8192,6627,5986,5761,6225,7110,8948,11740,14581,16589,17966,18947,19018,19561,19780,20357,20374,19503,19440,19617,19049,18034,15079,11259]},
        {&quot;name&quot;:&quot;IP&quot;,&quot;data&quot;:[7138,4444,2787,2210,2050,2956,5077,9196,13741,17065,18438,18438,18909,19245,20229,21160,22818,22226,21451,22956,23673,22512,17776,11780]},
        {&quot;name&quot;:&quot;Client&quot;,&quot;data&quot;:[7519,4389,2668,1929,1804,2586,4655,8194,13187,16602,18179,18863,19036,19409,20029,20907,22339,22177,21657,22738,23759,22874,19012,12772]}
    ]
}
);&lt;/script&gt;


&lt;p&gt;The weekday chart shows an even bigger drop between 4PM and 6PM, 27%.&lt;/p&gt;

&lt;p&gt;The weekend only shows a tiny 3% drop during this same period. On the weekends the traffic doesn&amp;#8217;t drop until about 9PM, bed time for many people.&lt;/p&gt;

&lt;p&gt;It looks like using the GeoIP version of the client&amp;#8217;s IP address is an accurate way to measure the client&amp;#8217;s actual local time.&lt;/p&gt;

&lt;p&gt;Can we also say that people are visiting from work and school? The data seems to point in that direction, but it isn&amp;#8217;t definitive proof. People may be playing from home while their significant others go to work and then stop when they arrive home.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Massive Decrease in Memory Usage With Redis 2.4</title>
    <link href="http://cosmicrealms.com/blog/2011/10/03/massive-decrease-in-memory-usage-with-redis-2-dot-4/"/>
    <updated>2011-10-03T20:26:00-04:00</updated>
    <id>http://cosmicrealms.com/blog/2011/10/03/massive-decrease-in-memory-usage-with-redis-2-dot-4</id>
    <content type="html">&lt;p&gt;I love &lt;a href=&quot;http://redis.io&quot;&gt;redis&lt;/a&gt;. It&amp;#8217;s blazingly fast and wonderfully atomic.&lt;/p&gt;

&lt;p&gt;Back in December 2010 I converted the database behind &lt;a href=&quot;http://worldofsolitaire.com&quot;&gt;World of Solitaire&lt;/a&gt; to redis 2.2&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s currently holding over 21 million keys and handling over 1,100 commands per second.&lt;/p&gt;

&lt;p&gt;Over the past 9 months RAM usage has slowly been increasing as more and more keys are inserted. A few days ago I realized I was very short on available RAM and had to do something sooner, rather than later.&lt;/p&gt;

&lt;p&gt;Before throwing more RAM into the box, I decided to try updating to redis 2.4 as I had read a &lt;a href=&quot;http://antirez.com/post/everything-about-redis-24&quot;&gt;blog post&lt;/a&gt; that it was more efficient at storing sorted sets.&lt;/p&gt;

&lt;p&gt;I was SHOCKED at the reduction in RAM usage:&lt;/p&gt;

&lt;div id=&quot;ramReduction&quot;&gt;&lt;/div&gt;


&lt;script&gt;new Highcharts.Chart(
{
    chart :
    {
        renderTo : &quot;ramReduction&quot;,
        defaultSeriesType : &quot;column&quot;,
        backgroundColor : &quot;transparent&quot;
    },
    credits : { enabled : false },
    title : null,
    xAxis : { categories : [ &quot;redis 2.2&quot;, &quot;redis 2.4&quot; ] },
    yAxis : { title : { text : &quot;RAM Usage&quot; } },
    legend : { enabled : false },
    tooltip :
    {
        formatter : function()
        {
            return &quot;&lt;b&gt;&quot; + this.x + &quot;&lt;/b&gt;&lt;br/&gt;&quot; + &quot;RAM Usage: &quot; + this.y + &quot;GB&quot;;
        }
    },
    series :
    [{
        data : [ 11.7, 3.67 ],
        dataLabels : 
        {
            enabled : true,
            formatter : function()
            {
                return this.y + &quot;GB&quot;;
            },
            style : { fontWeight : &quot;bold&quot; }
        }
    }]
}
);&lt;/script&gt;


&lt;p&gt;It was such a dramatic reduction, I questioned whether or not data had been lost in some way.&lt;/p&gt;

&lt;p&gt;Comparing the same dump in both 2.2 and 2.4 yielded the exact same key count: 21,085,659&lt;/p&gt;

&lt;p&gt;Am I really storing that many sorted sets?
I decided to write some code to see how many keys of each type I was storing and what the average length of each type was.&lt;/p&gt;

&lt;p&gt;My first attempt in node.js ended pretty quickly with a memory allocation fault with node.js, so I decided to code it in C.&lt;/p&gt;

&lt;p&gt;Data type breakdown:&lt;/p&gt;

&lt;div id=&quot;dataTypeMakeup&quot;&gt;&lt;/div&gt;


&lt;script&gt;new Highcharts.Chart(
{
    chart :
    {
         renderTo : &#8216;dataTypeMakeup&#8217;,
         plotBackgroundColor : null,
         plotBorderWidth : null,
         plotShadow : false,
         backgroundColor : &quot;transparent&quot;
    },
    credits : { enabled : false },
    title : null,
    tooltip :
    {
        formatter: function()
        {
            return &quot;&lt;b&gt;&quot;+ this.point.name +&quot;&lt;/b&gt;: &quot;+ Highcharts.numberFormat(this.y, 0);
        }
    },
    plotOptions :
    {
        pie :
        {
            allowPointSelect : true,
            cursor : &#8216;pointer&#8217;,
            dataLabels :
            {
                enabled : true,
                color: &#8216;#000000&#8217;,
                connectorColor: &#8216;#000000&#8217;,
                formatter: function()
                {
                    return &quot;&lt;b&gt;&quot;+ this.point.name +&quot;&lt;/b&gt;&lt;br/&gt;&quot;+ Highcharts.numberFormat(this.y, 0);
                }
            }
         }
      },
        series: [{
         type: &#8216;pie&#8217;,
         name: &#8216;Browser share&#8217;,
         data: [
            [&#8216;Hashes&#8217;, 10742038],
            {
               name: &#8216;Sorted Sets&#8217;,    
               y: 10343620,
               sliced : true,
               selected : true
            }
         ]
      }]
   }
);&lt;/script&gt;


&lt;p&gt;Average Length:&lt;/p&gt;

&lt;div id=&quot;typeAverageLength&quot;&gt;&lt;/div&gt;


&lt;script&gt;new Highcharts.Chart(
{
    chart :
    {
        renderTo : &quot;typeAverageLength&quot;,
        defaultSeriesType : &quot;bar&quot;,
        backgroundColor : &quot;transparent&quot;
    },
    credits : { enabled : false },
    title : null,
    xAxis : { categories : [ &quot;Sorted Sets&quot;, &quot;Hashes&quot; ] },
    yAxis : { title : { text : &quot;Average Length&quot; } },
    legend : { enabled : false },
    tooltip :
    {
        formatter : function()
        {
            return &quot;&lt;b&gt;&quot; + this.x + &quot;&lt;/b&gt;&lt;br/&gt;&quot; + &quot;Average Length: &quot; + this.y;
        }
    },
    series :
    [{
        data : [ 1.5, 5.13 ],
        dataLabels : 
        {
            enabled : true,
            formatter : function()
            {
                return this.y;
            },
            style : { fontWeight : &quot;bold&quot; }
        }
    }]
}
);&lt;/script&gt;


&lt;p&gt;Over 10 million sorted sets with only 1.5 entries on average per set.&lt;/p&gt;

&lt;p&gt;Thanks to redis 2.4, I won&amp;#8217;t have to worry about RAM for a while :)&lt;/p&gt;

&lt;p&gt;Here is the hacky C code I coded up to gather redis key type stats:&lt;/p&gt;

&lt;div&gt;&lt;script src=&#8217;https://gist.github.com/1260574.js?file=redis-key-stats.c&#8217;&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;
/*
 1. Install hiredis: git clone git://github.com/antirez/hiredis.git &amp;amp;&amp;amp; cd hiredis &amp;amp;&amp;amp; make &amp;amp;&amp;amp; make install
 2. Build C program: gcc -o redis-key-stats -lhiredis -I/usr/local/include/hiredis redis-key-stats.c
 3. Run program: ./redis-key-stats &amp;lt;address&amp;gt; &amp;lt;port&amp;gt;
*/
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;hiredis.h&amp;gt;

int main(int argc, char ** argv)
{
    redisContext * c;
    redisReply * keysReply;
    redisReply * typeReply;
    redisReply * lengthReply;
    long double counts[5];
    long double sums[5];
    char * key;
    unsigned long i;
    
    if(argc&amp;lt;3)
    {
        printf(&amp;quot;Usage: %s &amp;lt;address&amp;gt; &amp;lt;port&amp;gt;\n&amp;quot;, argv[0]);
        return EXIT_FAILURE;
    }
    
    c = redisConnect(argv[1], atoi(argv[2]));
    if (c-&amp;gt;err)
    {
        printf(&amp;quot;Error: %s\n&amp;quot;, c-&amp;gt;errstr);
        return EXIT_FAILURE;
    }

    sums[0] = sums[1] = sums[2] = sums[3] = sums[4] = 0;
    counts[0] = counts[1] = counts[2] = counts[3] = counts[4] = 0;

    keysReply = redisCommand(c, &amp;quot;KEYS *&amp;quot;);
    for(i=0;i&amp;lt;keysReply-&amp;gt;elements;i++)
    {
        key = keysReply-&amp;gt;element[i]-&amp;gt;str;
        typeReply = redisCommand(c, &amp;quot;TYPE %s&amp;quot;, key);

        if(!strcmp(typeReply-&amp;gt;str, &amp;quot;string&amp;quot;))
        {
            lengthReply = redisCommand(c, &amp;quot;STRLEN %s&amp;quot;, key);
            counts[0]++;
            sums[0] += lengthReply-&amp;gt;integer;
        }

        if(!strcmp(typeReply-&amp;gt;str, &amp;quot;list&amp;quot;))
        {
            lengthReply = redisCommand(c, &amp;quot;LLEN %s&amp;quot;, key);
            counts[1]++;
            sums[1] += lengthReply-&amp;gt;integer;
        }

        if(!strcmp(typeReply-&amp;gt;str, &amp;quot;set&amp;quot;))
        {
            lengthReply = redisCommand(c, &amp;quot;SCARD %s&amp;quot;, key);
            counts[2]++;
            sums[2] += lengthReply-&amp;gt;integer;
        }

        if(!strcmp(typeReply-&amp;gt;str, &amp;quot;zset&amp;quot;))
        {
            lengthReply = redisCommand(c, &amp;quot;ZCARD %s&amp;quot;, key);
            counts[3]++;
            sums[3] += lengthReply-&amp;gt;integer;
        }

        if(!strcmp(typeReply-&amp;gt;str, &amp;quot;hash&amp;quot;))
        {
            lengthReply = redisCommand(c, &amp;quot;HLEN %s&amp;quot;, key);
            counts[4]++;
            sums[4] += lengthReply-&amp;gt;integer;
        }

        freeReplyObject(typeReply);
    }
    freeReplyObject(keysReply);

    printf(&amp;quot;total count: %d\n&amp;quot;, keysReply-&amp;gt;elements);

    printf(&amp;quot;\nstrings count: %Lf\n&amp;quot;, counts[0]);
    printf(&amp;quot;strings avg len: %0.2Lf\n&amp;quot;, sums[0]==0 ? 0 : (sums[0]/counts[0]));

    printf(&amp;quot;\nlists count: %Lf\n&amp;quot;, counts[1]);
    printf(&amp;quot;lists avg len: %0.2Lf\n&amp;quot;, sums[1]==0 ? 0 : (sums[1]/counts[1]));

    printf(&amp;quot;\nsets count: %Lf\n&amp;quot;, counts[2]);
    printf(&amp;quot;sets avg len: %0.2Lf\n&amp;quot;, sums[2]==0 ? 0 : (sums[2]/counts[2]));

    printf(&amp;quot;\nzsets count: %Lf\n&amp;quot;, counts[3]);
    printf(&amp;quot;zsets avg len: %0.2Lf\n&amp;quot;, sums[3]==0 ? 0 : (sums[3]/counts[3]));

    printf(&amp;quot;\nhashes count: %Lf\n&amp;quot;, counts[4]);
    printf(&amp;quot;hashes avg len: %0.2Lf\n&amp;quot;, sums[4]==0 ? 0 : (sums[4]/counts[4]));

    return EXIT_SUCCESS;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;



</content>
  </entry>
  
  <entry>
    <title>First Post!</title>
    <link href="http://cosmicrealms.com/blog/2011/10/01/first-post/"/>
    <updated>2011-10-01T08:35:00-04:00</updated>
    <id>http://cosmicrealms.com/blog/2011/10/01/first-post</id>
    <content type="html">&lt;p&gt;Over the past decade or so of coding I&amp;#8217;ve had several coding related ideas I wanted to research or experiment with.
In many cases I felt that the outcome of the research or experiment would be interestering to others. This blog will be a place where I can post the outcomes of these endeavors.&lt;/p&gt;

&lt;p&gt;I hope they prove to be useful to someone someday :)&lt;/p&gt;
</content>
  </entry>
  
</feed>

