
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Sun, 05 Apr 2026 19:15:13 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Scaling out PostgreSQL for CloudFlare Analytics using CitusDB]]></title>
            <link>https://blog.cloudflare.com/scaling-out-postgresql-for-cloudflare-analytics-using-citusdb/</link>
            <pubDate>Thu, 09 Apr 2015 17:32:05 GMT</pubDate>
            <description><![CDATA[ When I joined CloudFlare about 18 months ago, we had just started to build out our new Data Platform. At that point, the log processing and analytics pipeline built in the early days of the company had reached its limits.  ]]></description>
            <content:encoded><![CDATA[ <p>When I joined CloudFlare about 18 months ago, we had just started to build out our new Data Platform. At that point, the log processing and analytics pipeline built in the early days of the company had reached its limits. This was due to the rapidly increasing log volume from our Edge Platform where we’ve had to deal with traffic growth in excess of 400% annually.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4AxkHPDBZrwj6QJQVWuQcX/fec02af530de1ab2f8a1f516ece59057/keepcalm_scaled.png" />
            
            </figure><p>Our log processing pipeline started out like most everybody else’s: compressed log files shipped to a central location for aggregation by a motley collection of Perl scripts and C++ programs with a single PostgreSQL instance to store the aggregated data. Since then, CloudFlare has grown to serve millions of requests per second for millions of sites. Apart from the hundreds of terabytes of log data that has to be aggregated every day, we also face some unique challenges in providing detailed analytics for each of the millions of sites on CloudFlare.</p><p>For the next iteration of our Customer Analytics application, we wanted to get something up and running quickly, try out Kafka, write the aggregation application in Go, and see what could be done to scale out our trusty go-to database, PostgreSQL, from a single machine to a cluster of servers without requiring us to deal with sharding in the application.</p><p>As we were analyzing our scaling requirements for PostgreSQL, we came across <a href="https://www.citusdata.com/">Citus Data</a>, one of the companies to launch out of <a href="https://www.ycombinator.com/">Y Combinator</a> in the summer of 2011. Citus Data builds a database called CitusDB that scales out PostgreSQL for real-time workloads. Because CitusDB enables both real-time data ingest and sub-second queries across billions of rows, it has become a crucial part of our analytics infrastructure.</p>
    <div>
      <h4>Log Processing Pipeline for Analytics</h4>
      <a href="#log-processing-pipeline-for-analytics">
        
      </a>
    </div>
    <p>Before jumping into the details of our database backend, let’s review the pipeline that takes a log event from CloudFlare’s Edge to our analytics database.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4I3yKJFMKyL4M3gtS2SlTy/b34a4a58d3da74e788950e6af1699582/image01.png" />
            
            </figure><p>An HTTP access log event proceeds through the CloudFlare data pipeline as follows:</p><ol><li><p>A web browser makes a request (e.g., an HTTP GET request).</p></li><li><p>An Nginx web server running <a href="/pushing-nginx-to-its-limit-with-lua/">Lua code</a> handles the request and generates a binary log event in <a href="https://capnproto.org">Cap’n Proto format</a>.</p></li><li><p>A Go program akin to <a href="https://github.com/mozilla-services/heka">Heka</a> receives the log event from Nginx over a UNIX socket, batches it with other events, compresses the batch using a fast algorithm like <a href="https://github.com/google/snappy">Snappy</a> or <a href="https://github.com/Cyan4973/lz4">LZ4</a>, and sends it to our data center over a TLS-encrypted TCP connection.</p></li><li><p>Another Go program (the Kafka shim) receives the log event stream, decrypts it, decompresses the batches, and produces the events into a Kafka topic with partitions replicated on many servers.</p></li><li><p>Go aggregators (one process per partition) consume the topic-partitions and insert aggregates (not individual events) with 1-minute granularity into the CitusDB database. Further rollups to 1-hour and 1-day granularity occur later to reduce the amount of data to be queried and to speed up queries over intervals spanning many hours or days.</p></li></ol>
    <div>
      <h4>Why Go?</h4>
      <a href="#why-go">
        
      </a>
    </div>
    <p>Previous blog <a href="/what-weve-been-doing-with-go/">posts</a> and <a href="https://www.youtube.com/watch?v=8igk2ylk_X4">talks</a> have covered <a href="/go-at-cloudflare/">various CloudFlare projects that have been built using Go</a>. We’ve found that Go is a great language for teams to use when building the kinds of distributed systems needed at CloudFlare, and this is true regardless of an engineer’s level of experience with Go. Our Customer Analytics team is made up of engineers that have been using Go since before its 1.0 release as well as complete Go newbies. Team members that were new to Go were able to spin up quickly, and the code base has remained maintainable even as we’ve continued to build many more data processing and aggregation applications such as a new version of <a href="https://www.hakkalabs.co/articles/optimizing-go-3k-requestssec-480k-requestssec">our Layer 7 DDoS attack mitigation system</a>.</p><p>Another factor that makes Go great is the ever-expanding ecosystem of third party libraries. We used <a href="https://github.com/glycerine/go-capnproto">go-capnproto</a> to generate Go code to handle binary log events in Cap’n Proto format from a common schema shared between Go, C++, and <a href="/introducing-lua-capnproto-better-serialization-in-lua/">Lua projects</a>. Go support for Kafka with <a href="https://godoc.org/github.com/Shopify/sarama">Shopify’s Sarama</a> library, support for ZooKeeper with <a href="https://github.com/samuel/go-zookeeper">go-zookeeper</a>, support for PostgreSQL/CitusDB through <a href="http://golang.org/pkg/database/sql/">database/sql</a> and the <a href="https://github.com/lib/pq">lib/pq driver</a> are all very good.</p>
    <div>
      <h4>Why Kafka?</h4>
      <a href="#why-kafka">
        
      </a>
    </div>
    <p>As we started building our new data processing applications in Go, we had some additional requirements for the pipeline:</p><ol><li><p>Use a queue with persistence to allow short periods of downtime for downstream servers and/or consumer services.</p></li><li><p>Make the data available for processing in real time by <a href="https://github.com/mumrah/kafka-python">scripts</a> written by members of our Site Reliability Engineering team.</p></li><li><p>Allow future aggregators to be built in other languages like Java, <a href="https://github.com/edenhill/librdkafka">C or C++</a>.</p></li></ol><p>After extensive testing, we selected <a href="https://kafka.apache.org/">Kafka</a> as the first stage of the log processing pipeline.</p>
    <div>
      <h4>Why Postgres?</h4>
      <a href="#why-postgres">
        
      </a>
    </div>
    <p>As we mentioned when <a href="http://www.postgresql.org/about/press/presskit93/">PostgreSQL 9.3 was released</a>, PostgreSQL has long been an important part of our stack, and for good reason.</p><p>Foreign data wrappers and other extension mechanisms make PostgreSQL an excellent platform for storing lots of data, or as a gateway to other NoSQL data stores, without having to give up the power of SQL. PostgreSQL also has great performance and documentation. Lastly, PostgreSQL has a large and active community, and we've had the privilege of meeting many of the PostgreSQL contributors at meetups held at the CloudFlare office and elsewhere, organized by the <a href="http://www.meetup.com/postgresql-1/">The San Francisco Bay Area PostgreSQL Meetup Group</a>.</p>
    <div>
      <h4>Why CitusDB?</h4>
      <a href="#why-citusdb">
        
      </a>
    </div>
    <p>CloudFlare has been using PostgreSQL since day one. We trust it, and we wanted to keep using it. However, CloudFlare's data has been growing rapidly, and we were running into the limitations of a single PostgreSQL instance. Our team was tasked with scaling out our analytics database in a short time so we started by defining the criteria that are important to us:</p><ol><li><p><b>Performance</b>: Our system powers the Customer Analytics dashboard, so typical queries need to return in less than a second even when dealing with data from many customer sites over long time periods.</p></li><li><p><b>PostgreSQL</b>: We have extensive experience running PostgreSQL in production. We also find several extensions useful, e.g., Hstore enables us to store semi-structured data and HyperLogLog (HLL) makes unique count approximation queries fast.</p></li><li><p><b>Scaling</b>: We need to dynamically scale out our cluster for performance and huge data storage. That is, if we realize that our cluster is becoming overutilized, we want to solve the problem by just adding new machines.</p></li><li><p><b>High availability</b>: This cluster needs to be highly available. As such, the cluster needs to automatically recover from failures like disks dying or servers going down.</p></li><li><p><b>Business intelligence queries</b>: in addition to sub-second responses for customer queries, we need to be able to perform business intelligence queries that may need to analyze billions of rows of analytics data.</p></li></ol><p>At first, we evaluated what it would take to build an application that deals with sharding on top of stock PostgreSQL. We investigated using the <a href="http://www.postgresql.org/docs/9.4/static/postgres-fdw.html">postgres_fdw</a> extension to provide a unified view on top of a number of independent PostgreSQL servers, but this solution did not deal well with servers going down.</p><p>Research into the major players in the PostgreSQL space indicated that CitusDB had the potential to be a great fit for us. On the performance point, they already had customers running real-time analytics with queries running in parallel across a large cluster in tens of milliseconds.</p><p>CitusDB has also maintained compatibility with PostgreSQL, not by forking the code base like other vendors, but by extending it to plan and execute distributed queries. Furthermore, CitusDB used the concept of many logical shards so that if we were to add new machines to our cluster, we could easily rebalance the shards in the cluster by calling a simple PostgreSQL user-defined function.</p><p>With CitusDB, we could replicate logical shards to independent machines in the cluster, and automatically fail over between replicas even during queries. In case of a hardware failure, we could also use the rebalance function to re-replicate shards in the cluster.</p>
    <div>
      <h4>CitusDB Architecture</h4>
      <a href="#citusdb-architecture">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/74Tl2hP3Tfk1HNzpF1MV4i/121b31b62700289180653b647a653edb/image00.png" />
            
            </figure><p>CitusDB follows an architecture similar to Hadoop to scale out Postgres: one primary node holds authoritative metadata about shards in the cluster and parallelizes incoming queries. The worker nodes then do all the actual work of running the queries.</p><p>In CloudFlare's case, the cluster holds about 1 million shards and each shard is replicated to multiple machines. When the application sends a query to the cluster, the primary node first prunes away unrelated shards and finds the specific shards relevant to the query. The primary node then transforms the query into many smaller queries for <a href="http://www.citusdata.com/blog/19-ozgun/114-how-to-build-your-distributed-database">parallel execution</a> and ships those smaller queries to the worker nodes.</p><p>Finally, the primary node receives intermediate results from the workers, merges them, and returns the final results to the application. This takes anywhere between 25 milliseconds to 2 seconds for queries in the CloudFlare analytics cluster, depending on whether some or all of the data is available in page cache.</p><p>From a high availability standpoint, when a worker node fails, the primary node automatically fails over to the replicas, even during a query. The primary node holds slowly changing metadata, making it a good fit for continuous backups or PostgreSQL's streaming replication feature. Citus Data is currently working on further improvements to make it easy to replicate the primary metadata to all the other nodes.</p><p>At CloudFlare, we love the CitusDB architecture because it enabled us to continue using PostgreSQL. Our analytics dashboard and BI tools connect to Citus using standard PostgreSQL connectors, and tools like <code>pg_dump</code> and <code>pg_upgrade</code> just work. Two features that stand out for us are CitusDB’s PostgreSQL extensions that power our analytics dashboards, and CitusDB’s ability to parallelize the logic in those extensions out of the box.</p>
    <div>
      <h4>Postgres Extensions on CitusDB</h4>
      <a href="#postgres-extensions-on-citusdb">
        
      </a>
    </div>
    <p>PostgreSQL extensions are pieces of software that add functionality to the core database itself. Some examples are data types, user-defined functions, operators, aggregates, and custom index types. PostgreSQL has more than 150 publicly available official extensions. We’d like to highlight two of these extensions that might be of general interest. It’s worth noting that with CitusDB all of these extensions automatically scale to many servers without any changes.</p>
    <div>
      <h4>HyperLogLog</h4>
      <a href="#hyperloglog">
        
      </a>
    </div>
    <p><a href="https://en.wikipedia.org/wiki/HyperLogLog">HyperLogLog</a> is a sophisticated algorithm developed for doing unique count approximations quickly. And since a <a href="https://github.com/aggregateknowledge/postgresql-hll">HLL implementation for PostgreSQL</a> was open sourced by the good folks at Aggregate Knowledge, we could use it with CitusDB unchanged because it’s compatible with most (if not all) Postgres extensions.</p><p>HLL was important for our application because we needed to compute unique IP counts across various time intervals in real time and we didn’t want to store the unique IPs themselves. With this extension, we could, for example, count the number of unique IP addresses accessing a customer site in a minute, but still have an accurate count when further rolling up the aggregated data into a 1-hour aggregate.</p>
    <div>
      <h4>Hstore</h4>
      <a href="#hstore">
        
      </a>
    </div>
    <p>The <a href="http://www.postgresql.org/docs/9.4/static/hstore.html">hstore data type</a> stores sets of key/value pairs within a single PostgreSQL value. This can be helpful in various scenarios such as with rows with many attributes that are rarely examined, or to represent semi-structured data. We use the hstore data type to hold counters for sparse categories (e.g. country, HTTP status, data center).</p><p>With the hstore data type, we save ourselves from the burden of denormalizing our table schema into hundreds or thousands of columns. For example, we have one hstore data type that holds the number of requests coming in from different data centers per minute per CloudFlare customer. With millions of customers and hundreds of data centers, this counter data ends up being very sparse. Thanks to hstore, we can efficiently store that data, and thanks to CitusDB, we can efficiently parallelize queries of that data.</p><p>For future applications, we are also investigating other extensions such as the Postgres columnar store extension <a href="https://github.com/citusdata/cstore_fdw">cstore_fdw</a> that Citus Data has open sourced. This will allow us to compress and store even more historical analytics data in a smaller footprint.</p>
    <div>
      <h4>Conclusion</h4>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>CitusDB has been working very well for us as the new backend for our Customer Analytics system. We have also found many uses for the analytics data in a business intelligence context. The ease with which we can run distributed queries on the data allows us to quickly answer new questions about the CloudFlare network that arise from anyone in the company, from the SRE team through to Sales.</p><p>We are looking forward to features available in the recently released <a href="https://www.citusdata.com/citus-products/citusdb-software">CitusDB 4.0</a>, especially the performance improvements and the new shard rebalancer. We’re also excited about using the JSONB data type with CitusDB 4.0, along with all the other improvements that come standard as part of <a href="http://www.postgresql.org/docs/9.4/static/release-9-4.html">PostgreSQL 9.4</a>.</p><p>Finally, if you’re interested in building and operating distributed services like Kafka or CitusDB and writing Go as part of a dynamic team dealing with big (nay, gargantuan) amounts of data, <a href="https://www.cloudflare.com/join-our-team">CloudFlare is hiring</a>.</p> ]]></content:encoded>
            <category><![CDATA[Analytics]]></category>
            <category><![CDATA[SQL]]></category>
            <category><![CDATA[Postgres]]></category>
            <category><![CDATA[Kafka]]></category>
            <category><![CDATA[LUA]]></category>
            <category><![CDATA[DDoS]]></category>
            <guid isPermaLink="false">4WkjJAXrP1iZH5uthDDnAh</guid>
            <dc:creator>Albert Strasheim</dc:creator>
        </item>
        <item>
            <title><![CDATA[It's Go Time on Linux]]></title>
            <link>https://blog.cloudflare.com/its-go-time-on-linux/</link>
            <pubDate>Wed, 05 Mar 2014 00:00:00 GMT</pubDate>
            <description><![CDATA[ Some interesting changes related to timekeeping in the upcoming Go 1.3 release inspired us to take a closer look at how Go programs keep time with the help of the Linux kernel. Timekeeping is a complex topic and determining the current time isn’t as simple as it might seem at first glance. ]]></description>
            <content:encoded><![CDATA[ <p>Some interesting changes related to timekeeping in the upcoming Go 1.3 release inspired us to take a closer look at how Go programs keep time with the help of the Linux kernel. Timekeeping is a complex topic and determining the current time isn’t as simple as it might seem at first glance.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4VWH2QXVaqkSnUkzLetIdn/5bfae1adbf588346480801608a09be9e/The_Persistence_of_Memory.jpg" />
            
            </figure><p><a href="http://golang.org/">Go</a> running on the Linux kernel has been used to build <a href="/go-at-cloudflare/">many</a> <a href="/red-october-cloudflares-open-source-implementation-of-the-two-man-rule/">important</a> <a href="/what-weve-been-doing-with-go/">systems</a> like RRDNS (our DNS server) at CloudFlare. Accurately, precisely and efficiently determining the time is an important part of many of the these systems.</p><p>To see why time is important, consider that humans have had some trouble convincing computers to keep time for them in the recent past. It been a bit more than a decade since we had to dust off our best COBOL programmers to tackle <a href="https://en.wikipedia.org/wiki/Year_2000_problem">Y2K</a>.</p><p>More recently, a bug in the handling of a leap second propagated through the Network Time Protocol (NTP) also took many systems off-line. As we've seen in recent days, NTP is very useful for synchronizing computer clocks and/or <a href="/technical-details-behind-a-400gbps-ntp-amplification-ddos-attack">DDoSing them</a>. The leap second bug <a href="http://www.somebits.com/weblog/tech/bad/leap-second-2012.html">received</a> <a href="http://www.datastax.com/dev/blog/linux-cassandra-and-saturdays-leap-second-problem">extensive</a> <a href="http://arstechnica.com/business/2012/07/one-day-later-the-leap-second-v-the-internet-scorecard/">coverage</a>. <a href="http://googleblog.blogspot.com/2011/09/time-technology-and-leaping-seconds.html">Google was ready</a> but many other popular sites were taken offline.</p><p>We also have the <a href="https://en.wikipedia.org/wiki/Year_2038_problem">Year 2038 problem</a> to look forward to. Hopefully there will still be a few engineers around then that remember what this 32-bit thing was all about.</p>
    <div>
      <h2>Time in Go</h2>
      <a href="#time-in-go">
        
      </a>
    </div>
    <p>Everything starts with the <a href="http://golang.org/pkg/time/">time</a> package that is part of Go’s standard library. The time package provides types for <a href="http://golang.org/pkg/time/#Time">Time</a>, <a href="http://golang.org/pkg/time/#Duration">Duration</a>, <a href="http://golang.org/pkg/time/#Ticker">Ticker</a>, <a href="http://golang.org/pkg/time/#Timer">Timer</a> and various utility functions for manipulating these types.</p><p>The most commonly used function in this package is probably the <a href="http://golang.org/pkg/time/#Now">time.Now</a> function, which returns the current time as a Time struct. The Time struct has 3 fields:</p>
            <pre><code>type Time struct {
    sec int64
	nsec uintptr
	loc *Location
}</code></pre>
            <p><a href="http://golang.org/pkg/time/#Location">Location</a> contains the timezone information for the time.</p><p><a href="http://golang.org/pkg/time/#Duration">Duration</a> is used to express the difference between two Times and to configure timers and tickers.</p><p><a href="http://golang.org/pkg/time/#Timer">Timer</a> is useful for implementing a timeout, typically as part of a <a href="http://golang.org/ref/spec#Select_statements">select</a> statement. <a href="http://golang.org/pkg/time/#Ticker">Ticker</a> can be used to wake up periodically, usually when you are using select in a for loop.</p><p>Go’s time package is used in many other places in the Go standard library. When dealing with socket connections that may go slow or stop sending data completely, one uses the SetDeadline functions that are part of the <a href="http://golang.org/pkg/net/#Conn">net.Conn</a> interface.</p><p>We love writing tests at CloudFlare, and having unit tests that include some kind of random component can turn up interesting issues. You can use the current time to seed random number generators in tests, using:</p>
            <pre><code>rand.New(rand.NewSource(time.Now().UnixNano()))</code></pre>
            <p>If you’re generating random numbers for a secure application, you really want to be using the <a href="http://golang.org/pkg/crypto/rand/">crypto/rand</a> package. Interestingly, even the initialization of <a href="http://golang.org/pkg/crypto/rand/#pkg-variables">crypto/rand.Reader</a> <a href="http://golang.org/src/pkg/crypto/rand/rand_unix.go#L114">incorporates</a> the current time.</p><p>The current time also features when one <a href="http://golang.org/src/pkg/log/log.go#L131">logs</a> something using the <a href="http://golang.org/pkg/log">log</a> package.</p><p>A very useful service called <a href="https://sourcegraph.com/code.google.com/p/go/symbols/go/code.google.com/p/go/src/pkg/time/Now">Sourcegraph</a> turns up more than 6000 examples where time.Now is used. For example, the <a href="http://camlistore.org/">Camlistore</a> code base calls time.Now in about 130 different places.</p><p>With time.Now being as pervasive as it is, have you ever wondered how it works? Time to dive deeper.</p>
    <div>
      <h2>System calls</h2>
      <a href="#system-calls">
        
      </a>
    </div>
    <p>The most important changes to the way in which Go programs keep time on Linux was committed on 8 November 2012 in <a href="https://code.google.com/p/go/source/detail?r=42c8d3aadc40">changeset 42c8d3aadc40</a> Let’s analyse the commit message and the code for some clues:</p>
            <pre><code>runtime: use vDSO clock_gettime for time.now &amp; runtime.nanotime
on Linux/amd64. Performance improvement aside, time.Now() now 
gets real nanosecond resolution on supported systems.</code></pre>
            <p>To understand this commit message better, we first need to review the system calls available on Linux for obtaining the value of the clock.</p><p>In the beginning, there was <a href="http://man7.org/linux/man-pages/man2/time.2.html">time</a> and <a href="http://man7.org/linux/man-pages/man2/settimeofday.2.html">gettimeofday</a>, which existed in SVr4, 4.3BSD and was described in POSIX.1-2001. time returns the number of seconds since the <a href="https://en.wikipedia.org/wiki/Unix_time">Unix epoch</a>, 1970-01-01 00:00:00 UTC and is defined in C as:</p>
            <pre><code>time_t time(time_t *t)</code></pre>
            <p>time_t is 4 bytes on 32-bit platforms and 8 bytes on 64-bit platforms, hence the Y2038 problem mentioned above.</p><p>gettimeofday returns the number of seconds and microseconds since the epoch and is defined in C as:</p>
            <pre><code>int gettimeofday(struct timeval *tv, struct timezone *tz)</code></pre>
            <p>gettimeofday populates a <code>struct timeval</code>, which has the following fields:</p>
            <pre><code>struct timeval {
	time_t tv_sec; /* seconds */
	suseconds_t tv_usec; /* microseconds */
}</code></pre>
            <p>gettimeofday yields timestamps that only have microsecond precision. POSIX.1-2008 marks gettimeofday as obsolete, recommending the use of <a href="http://man7.org/linux/man-pages/man2/clock_gettime.2.html">clock_gettime</a> instead, which is defined in C as:</p>
            <pre><code>int clock_gettime(clockid_t clk_id, struct timespec *tp)</code></pre>
            <p>clock_gettime populates a <code>struct timespec</code>, which has the following fields:</p>
            <pre><code>struct timespec {
	time_t tv_sec; /* seconds */
	long tv_nsec; /* nanoseconds */
}</code></pre>
            <p>clock_gettime can yield timestamps that have nanosecond precision. The clock ID parameter determines the type of clock to use. Of interest to us are:</p><ul><li><p><code>CLOCK_REALTIME</code>: a system-wide clock that measures real time. This clock is affected by discontinuous jumps in the system time and by incremental adjustments by made using the <a href="http://man7.org/linux/man-pages/man3/adjtime.3.html">adjtime</a> function or NTP.</p></li><li><p><code>CLOCK_MONOTONIC</code>: a clock that represents monotonic time since some unspecified starting point. This clock is not affected by discontinous jumps in the system time, but is affected by adjtime and NTP.</p></li><li><p><code>CLOCK_MONOTONIC_RAW</code>: similar to <code>CLOCK_MONOTONIC</code>, but not subject to adjustment by adjtime or NTP.</p></li></ul>
    <div>
      <h2>time.Now</h2>
      <a href="#time-now">
        
      </a>
    </div>
    <p>With this background we can look at the code for time.Now. (Hint: click on the <a href="http://golang.org/pkg/time/#Now">function name</a> in godoc to look at the code yourself.)</p><p>The time.Now function is implemented using a function called now that is internal to package time, but is actually provided by the Go runtime. In other words, there is no code for the function in package time itself.</p><p>Let’s take a closer look at the Linux implementations for the <a href="http://golang.org/src/pkg/runtime/sys_linux_386.s#L107">386</a> and <a href="http://golang.org/src/pkg/runtime/sys_linux_amd64.s#L104">amd64</a> platforms. We see that these functions are implemented in assembler and call a function to retrieve the current time. You might have been expecting to see a system call, i.e. an <code>INT 0x80</code> instruction on 386 or the <code>SYSCALL</code> instruction on amd64, to the kernel at this point, but Go does something much more interesting on Linux.</p><p>The Linux kernel provides Virtual Dynamically linked Shared Objects (vDSO) as a way for user space applications to make low-overhead calls to functions that would normally involve a system call to the kernel.</p><p>If you’re writing your application in a language that uses glibc, you are probably already getting your time via vDSO. Go doesn’t use glibc, so it has to implement this functionality in its runtime. The relevant code is in <a href="http://golang.org/src/pkg/runtime/vdso_linux_amd64.c">vdso_linux_amd64.c</a> in the <a href="http://golang.org/pkg/runtime/">runtime package</a>.</p><p>Finally, if you’re the kind of person that likes to stare into the bowels of your operating system, here’s the <a href="http://lxr.free-electrons.com/source/arch/x86/vdso/vclock_gettime.c">kernel side of the vDSO</a>.</p><p>vDSO support for time functions is currently 64-bit only, but a <a href="http://lwn.net/Articles/583963/">kernel patch</a> is in the works to add them on 32-bit platforms. When this happens, the Go runtime code will have to be updated to take advantage of this.</p>
    <div>
      <h2>Benchmarks</h2>
      <a href="#benchmarks">
        
      </a>
    </div>
    <p>When frequently calling a function to determine the time, you may be interested to know how long it takes to return. In other words, how now is “now” really? For benchmarking purposes, you can make these system calls directly from Go code. We have prepared <a href="https://github.com/cloudflare/autobench/commit/7d1effaf1fe0669ac28ee7ebe67216ee95f8a1b5">a patch</a> to Dave Cheney’s excellent <a href="https://github.com/cloudflare/autobench">autobench</a> project so that you may benchmark these system calls and other time-related functions yourself.</p><p>Benchmarks can also help us measure the time saved by calling gettimeofday and clock_gettime via the vDSO mechanism instead of the traditional system call path.</p><p>We’ll also use autobench to compare the performance of different versions of Go for the same set of time functions.</p><p>All benchmarks numbers below were obtained on an Intel Core i7-3540M CPU running at its maximum clock speed of 3 GHz. The CPU frequency scaling governor was set to performance mode to ensure reliable benchmark results.</p><p>We’ll use the Go 1.2 stable release as a baseline.</p><p>BenchmarkSyscallTime and BenchmarkVDSOTime measure the time it takes to make a time system call and vDSO call, respectively:</p>
            <pre><code>BenchmarkSyscallTime 38.2 ns/op
BenchmarkVDSOTime    3.85 ns/op</code></pre>
            <p>BenchmarkSyscallGettimeofday and BenchmarkVDSOGettimeofday measure the time it takes make to call a gettimeofday system call and vDSO call, respectively:</p>
            <pre><code>BenchmarkSyscallGettimeofday 59.3 ns/op
BenchmarkVDSOGettimeofday    23.4 ns/op</code></pre>
            <p>BenchmarkTimeNow measures the time it takes to call time.Now, which makes an underlying vDSO call to <code>clock_gettime(CLOCK_REALTIME)</code> and converts the returned value to a time.Time struct:</p>
            <pre><code>BenchmarkTimeNow 23.6 ns/op</code></pre>
            <p>Using autobench, we can also compare different Go versions against each other. To see how far we've come in the last few years, we also compared Go 1.2 to Go 1.0.3, which was released on Sep 27, 2012. The major difference was in the benchmark for time.Now:</p>
            <pre><code>benchmark        old ns/op  new ns/op  delta
BenchmarkTimeNow 406        23         -94.19%</code></pre>
            <p>To repeat this test with Go 1.0.3, you'll need the fix in <a href="https://code.google.com/p/go/source/detail?r=419dcca62a3d">changeset 419dcca62a3d</a> to compile if you are using a recent version of GCC.</p>
    <div>
      <h2>Clock Sources</h2>
      <a href="#clock-sources">
        
      </a>
    </div>
    <p>The speed at which you can tell time also depending on the clock source being used by your kernel. To see which clock sources you have available, run the following command:</p>
            <pre><code>$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource
tsc hpet acpi_pm</code></pre>
            <p>To see which clock source is currently in use, run this command:</p>
            <pre><code>$ cat /sys/devices/system/clocksource/clocksource0/current_clocksource
tsc</code></pre>
            <p><a href="https://en.wikipedia.org/wiki/Time_Stamp_Counter">Time Stamp Counter (TSC)</a> is a 64-bit register that can be read by the RDTSC instruction. It is faster to read than the <a href="https://en.wikipedia.org/wiki/High_Precision_Event_Timer">High Precision Event Timer (HPET)</a>. The ACPI Power Management Timer (APCI PMT) is another timer that is found on many motherboards.</p><p>We can also use the same benchmarks above to compare the TSC clock source and a HPET clock source. Doing so requires booting Linux with the <code>clocksource=hpet</code> kernel command line parameter. Here are the results:</p>
            <pre><code>benchmark                              tsc ns/op   hpet ns/op  delta
BenchmarkSyscallGettimeofday              59          645      +987.69%
BenchmarkVDSOGettimeofday                 23          598      +2455.56%
BenchmarkSyscallClockGettimeRealtime      58          642      +995.56%
BenchmarkSyscallClockGettimeMonotonic     57          641      +1012.85%
BenchmarkTimeNow                          23          598      +2433.90%</code></pre>
            <p>As you can see, querying the HPET clock source takes significantly longer.</p><p>Not all CPUs are created equal. To see which TSC features your CPU supports, run the following command:</p>
            <pre><code>$ cat /proc/cpuinfo | grep tsc</code></pre>
            <p>You will see some or all of the following CPU flags related to the TSC:</p><ul><li><p>tsc</p></li><li><p>rdtscp</p></li><li><p>constant_tsc</p></li><li><p>nonstop_tsc</p></li></ul><p>The <i>tsc</i> flag indicates that your CPU has the 64-bit TSC register, which has been present since the Pentium.</p><p>The <i>rdtscp</i> flag indicates that your CPU supports the newer RDTSCP instruction, in addition to the RDTSC instruction. Intel has an interesting whitepaper on <a href="http://www.intel.com/content/www/us/en/intelligent-systems/embedded-systems-training/ia-32-ia-64-benchmark-code-execution-paper.html">How to Benchmark Code Execution Times on Intel IA-32 and IA-64 Instruction Set Architectures</a> with more details about the differences.</p><p>The <i>constant_tsc</i> flag indicates that the TSC runs at constant frequency irrespective of the current frequency, voltage or throttling state of the CPU, commonly referred to as its P- and T-state.</p><p>The <i>nonstop_tsc</i> flag indicates that TSC does not stop, irrespective of the CPU’s power saving mode, referred to as its C-state.</p><p>These features work in conjunction to provide an invariant TSC. There is more discussion over at the <a href="http://software.intel.com/en-us/forums/topic/280440">Intel Software forums</a> if you’re interested.</p>
    <div>
      <h2>Coming up in Go 1.3</h2>
      <a href="#coming-up-in-go-1-3">
        
      </a>
    </div>
    <p>There has also been some interesting work on the time front in the upcoming Go 1.3 release. The time.Sleep function, Ticker, and Timer now use <code>clock_gettime(CLOCK_MONOTONIC)</code> on Linux and other platforms. This work has been a good example of the broader community contributing to improve the core of Go, as can be seen in <a href="https://code.google.com/p/go/issues/detail?id=6007">issue 6007</a>, <a href="https://codereview.appspot.com/53010043/">CL 53010043</a> and <a href="https://groups.google.com/d/topic/golang-dev/gVFa7DC8UI0/discussion">discussion on golang-dev</a>.</p>
    <div>
      <h2>Further Reading</h2>
      <a href="#further-reading">
        
      </a>
    </div>
    <p>That’s it for today. If kernels and clocks excite you, CloudFlare is always looking to hire great Go and Linux kernel engineers. See our <a href="https://www.cloudflare.com/join-our-team">Careers</a> page.</p><p>It would not have been possible to write this article without the help from some other sources. If you want to know more, here’s some recommended reading:</p><p>The book <a href="http://www.amazon.com/Understanding-Linux-Kernel-Third-Edition/dp/0596005652">Understanding the Linux Kernel</a> by Daniel Bovet and Marco Cesati has an entire chapter on the timekeeping architecture in the kernel.</p><p>More about timers <a href="http://stackoverflow.com/questions/10921210/cpu-tsc-fetch-operation-especially-in-multicore-multi-processor-environment">on StackOverflow</a></p><p>Read more about <a href="http://www.linuxjournal.com/content/creating-vdso-colonels-other-chicken">vDSOs</a>.</p><p>Read more about <a href="http://juliusdavies.ca/posix_clocks/clock_realtime_linux_faq.html">clock_gettime</a>.</p><p>Sometimes bug reports can be a great source of information on details of the kernel and your CPU. <a href="https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=474091">Red Hat Bugzilla #474091</a> was a gold mine of information on the CPU flags for the TSC.</p><p>More at Quora on the the benefits of <a href="http://www.quora.com/Linux/What-are-the-advantages-and-disadvantages-of-TSC-and-HPET-as-a-clocksource">TSC vs HPET</a>.</p><p>StackOverflow also had some information on the <a href="https://stackoverflow.com/questions/7987671/what-is-the-acpi-pm-linux-clocksource-used-for-what-hardware-implements-it">ACPI PM clock source</a>.</p><p>Finally, some discussion of the <a href="https://twistedmatrix.com/trac/ticket/2424#comment:23">differences between CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW</a> as used in the Twisted framework for Python.</p> ]]></content:encoded>
            <category><![CDATA[Linux]]></category>
            <category><![CDATA[Go]]></category>
            <category><![CDATA[DDoS]]></category>
            <category><![CDATA[Google]]></category>
            <category><![CDATA[Attacks]]></category>
            <guid isPermaLink="false">7xktWOfH0yiQAj7YiLjfh1</guid>
            <dc:creator>Albert Strasheim</dc:creator>
        </item>
    </channel>
</rss>