
<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 12:24:29 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Analysis of the EPYC 145% performance gain in Cloudflare Gen 12 servers]]></title>
            <link>https://blog.cloudflare.com/analysis-of-the-epyc-145-performance-gain-in-cloudflare-gen-12-servers/</link>
            <pubDate>Tue, 15 Oct 2024 15:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare’s Gen 12 server is the most powerful and power efficient server that we have deployed to date. Through sensitivity analysis, we found that Cloudflare workloads continue to scale with higher core count and higher CPU frequency, as well as achieving a significant boost in performance with larger L3 cache per core. ]]></description>
            <content:encoded><![CDATA[ <p>Cloudflare's <a href="https://www.cloudflare.com/network"><u>network</u></a> spans more than 330 cities in over 120 countries, serving over 60 million HTTP requests per second and 39 million DNS queries per second on average. These numbers will continue to grow, and at an accelerating pace, as will Cloudflare’s infrastructure to support them. While we can continue to scale out by deploying more servers, it is also paramount for us to develop and deploy more performant and more efficient servers.</p><p>At the heart of each server is the processor (central processing unit, or CPU). Even though many aspects of a server rack can be redesigned to improve the cost to serve a request, CPU remains the biggest lever, as it is typically the primary compute resource in a server, and the primary enabler of new technologies.</p><p><a href="https://blog.cloudflare.com/gen-12-servers/"><u>Cloudflare’s 12th Generation server with AMD EPYC 9684-X (codenamed Genoa-X) is 145% more performant and 63% more efficient</u></a>. These are big numbers, but where do the performance gains come from? Cloudflare’s hardware system engineering team did a sensitivity analysis on three variants of 4th generation AMD EPYC processor to understand the contributing factors.</p><p>For the 4th generation AMD EPYC Processors, AMD offers three architectural variants: </p><ol><li><p>mainstream classic Zen 4 cores, codenamed Genoa</p></li><li><p>efficiency optimized dense Zen 4c cores, codenamed Bergamo</p></li><li><p>cache optimized Zen 4 cores with 3D V-cache, codenamed Genoa-X</p></li></ol>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7hb5yDJksMIwbWVQcCzuoC/c085edca54d3820f7e93564791b0289a/image6.png" />
            
            </figure><p><sup>Figure 1 (from left to right): AMD EPYC 9654 (Genoa), AMD EPYC 9754 (Bergamo), AMD EPYC 9684X (Genoa-X)</sup></p><p>Key features common across the 4th Generation AMD EPYC processors:</p><ul><li><p>Up to 12x Core Complex Dies (CCDs)</p></li><li><p>Each core has a private 1MB L2 cache</p></li><li><p>The CCDs connect to memory, I/O, and each other through an I/O die</p></li><li><p>Configurable Thermal Design Power (cTDP) up to 400W</p></li><li><p>Support up to 12 channels of DDR5-4800 1DPC</p></li><li><p>Support up to 128 lanes PCIe Gen 5</p></li></ul><p>Classic Zen 4 Cores (Genoa):</p><ul><li><p>Each Core Complex (CCX) has 8x Zen 4 Cores (16x Threads)</p></li><li><p>Each CCX has a shared 32 MB L3 cache (4 MB/core)</p></li><li><p>Each CCD has 1x CCX</p></li></ul><p>Dense Zen 4c Cores (Bergamo):</p><ul><li><p>Each CCX has 8x Zen 4c Cores (16x Threads)</p></li><li><p>Each CCX has a shared 16 MB L3 cache (2 MB/core)</p></li><li><p>Each CCD has 2x CCX</p></li></ul><p>Classic Zen 4 Cores with 3D V-cache (Genoa-X):</p><ul><li><p>Each CCX has 8x Zen 4 Cores (16x Threads)</p></li><li><p>Each CCX has a shared 96MB L3 cache (12 MB/core)</p></li><li><p>Each CCD has 1x CCX</p></li></ul><p>For more information on 4th generation AMD EPYC Processors architecture, see: <a href="https://www.amd.com/system/files/documents/4th-gen-epyc-processor-architecture-white-paper.pdf"><u>https://www.amd.com/system/files/documents/4th-gen-epyc-processor-architecture-white-paper.pdf</u></a> </p><p>The following table is a summary of the specification of the AMD EPYC 7713 CPU in our <a href="https://blog.cloudflare.com/the-epyc-journey-continues-to-milan-in-cloudflares-11th-generation-edge-server/"><u>Gen 11 server</u></a> against the three CPU candidates, one from each variant of the 4th generation AMD EPYC Processors architecture:</p><div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td>
                        <p><span><span><strong>CPU Model</strong></span></span></p>
                    </td>
                    <td>
                        <p><a href="https://www.amd.com/en/products/specifications/server-processor.html"><span><span><strong><u>AMD EPYC 7713</u></strong></span></span></a></p>
                    </td>
                    <td>
                        <p><a href="https://www.amd.com/en/products/specifications/server-processor.html"><span><span><strong><u>AMD EPYC 9654</u></strong></span></span></a></p>
                    </td>
                    <td>
                        <p><a href="https://www.amd.com/en/products/specifications/server-processor.html"><span><span><strong><u>AMD EPYC 9754</u></strong></span></span></a></p>
                    </td>
                    <td>
                        <p><a href="https://www.amd.com/en/products/specifications/server-processor.html"><span><span><strong><u>AMD EPYC 9684X</u></strong></span></span></a></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Series</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>Milan</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Genoa</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Bergamo</span></span></p>
                    </td>
                    <td>
                        <p><span><span>Genoa-X</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong># of CPU Cores</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>64</span></span></p>
                    </td>
                    <td>
                        <p><span><span>96</span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>128</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>96</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong># of Threads</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>128</span></span></p>
                    </td>
                    <td>
                        <p><span><span>192</span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>256</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>192</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Base Clock</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.0 GHz</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.4 GHz</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.25 GHz</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.4 GHz</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>All Core Boost Clock</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>~2.7 GHz*</span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>3.55 Ghz</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>3.1 Ghz</span></span></p>
                    </td>
                    <td>
                        <p><span><span>3.42 Ghz</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Total L3 Cache</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>256 MB</span></span></p>
                    </td>
                    <td>
                        <p><span><span>384 MB</span></span></p>
                    </td>
                    <td>
                        <p><span><span>256 MB</span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>1152 MB</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>L3 cache per core</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>4 MB / core</span></span></p>
                    </td>
                    <td>
                        <p><span><span>4 MB / core</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2 MB / core</span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>12 MB / core</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Maximum configurable TDP</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>240W</span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>400W</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>400W</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>400W</strong></span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div><p><sup>* AMD EPYC 7713 all core boost clock is based on Cloudflare production data, not the official specification from AMD</sup></p>
    <div>
      <h2>cf_benchmark</h2>
      <a href="#cf_benchmark">
        
      </a>
    </div>
    <p>Readers may remember that Cloudflare introduced <a href="https://github.com/cloudflare/cf_benchmark"><u>cf_benchmark</u></a> when we evaluated <a href="https://blog.cloudflare.com/arm-takes-wing/"><u>Qualcomm's ARM chips</u></a>, using it as our first pass benchmark to shortlist <a href="https://blog.cloudflare.com/an-epyc-trip-to-rome-amd-is-cloudflares-10th-generation-edge-server-cpu/"><u>AMD’s Rome CPU for our Gen 10 servers</u></a> and to evaluate <a href="https://blog.cloudflare.com/arms-race-ampere-altra-takes-on-aws-graviton2/"><u>our chosen ARM CPU Ampere Altra Max against AWS Graviton 2</u></a>. Likewise, we ran cf_benchmark against the three candidate CPUs for our 12th Gen servers: AMD EPYC 9654 (Genoa), AMD EPYC 9754 (Bergamo), and AMD EPYC 9684X (Genoa-X). The majority of cf_benchmark workloads are compute bound, and given more cores or higher CPU frequency, they score better. The graph and the table below show the benchmark performance comparison of the three CPU candidates with Genoa 9654 as the baseline, where &gt; 1.00x indicates better performance.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6YNQ8YB5XV3fZEVpVFT7lM/2dadd7fda9832716f198dee2d5fbfd22/image5.png" />
          </figure><div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td> </td>
                    <td>
                        <p><span><span><strong>Genoa 9654 (baseline)</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Bergamo 9754</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Genoa-X 9684X</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>openssl_pki</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.16x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.01x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>openssl_aead</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.20x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.01x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>luajit</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.86x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>brotli</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.11x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.98x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>gzip</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.87x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.01x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>go</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.09x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div><p>Bergamo 9754 with 128 cores scores better in openssl_pki, openssl_aead, brotli, and go benchmark suites, and performs less favorably in luajit and gzip benchmark suites. Genoa-X 9684X (with significantly more L3 cache) doesn’t offer a significant boost in performance for these compute-bound benchmarks.</p><p>These benchmarks are representative of some of the common workloads Cloudflare runs, and are useful in identifying software scaling issues, system configuration bottlenecks, and the impact of CPU design choices on workload-specific performance. However, the benchmark suite is not an exhaustive list of all workloads Cloudflare runs in production, and in reality, the workloads included in the benchmark suites are almost certainly not the exclusive workload running on the CPU. In short, though benchmark results can be informative, they do not represent a good indication of production performance when a mix of these workloads run on the same processor.</p>
    <div>
      <h2>Performance simulation</h2>
      <a href="#performance-simulation">
        
      </a>
    </div>
    <p>To get an early indication of production performance, Cloudflare has an internal performance simulation tool that exercises our software stack to fetch a fixed asset repeatedly. The simulation tool can be configured to fetch a specified fixed-size asset and configured to include or exclude services like WAF or Workers in the request path. Below, we show the simulated performance between the three CPUs for an asset size of 10 KB, where &gt;1.00x indicates better performance.</p><div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td> </td>
                    <td>
                        <p><span><span><strong>Milan 7713</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Genoa 9654</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Bergamo 9754</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Genoa-X 9684X</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Lab simulation performance multiplier</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.20x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.95x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.75x</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div><p>Based on these results, Bergamo 9754, which has the highest core count, but smallest L3 cache per core, is least performant among the three candidates, followed by Genoa 9654. The Genoa-X 9684X with the largest L3 cache per core is the most performant. This data suggests that our software stack is very sensitive to L3 cache size, in addition to core count and CPU frequency. This is interesting and worth a deep dive into a sensitivity analysis of our workload against a few (high level) CPU design points, especially core scaling, frequency scaling, and L2/L3 cache sizes scaling.</p>
    <div>
      <h2>Sensitivity analysis</h2>
      <a href="#sensitivity-analysis">
        
      </a>
    </div>
    
    <div>
      <h3>Core sensitivity</h3>
      <a href="#core-sensitivity">
        
      </a>
    </div>
    <p>Number of cores is the headline specification that practically everyone talks about, and one of the easiest improvements CPU vendors can make to increase performance per socket. The AMD Genoa 9654 has 96 cores, 50% more than the 64 cores available on the AMD Milan 7713 CPUs that we used in our Gen 11 servers. Is more always better? Does Cloudflare’s primary workload scale with core count and effectively utilize all available cores?</p><p>The figure and table below shows the result of a core scaling experiment performed on an AMD Genoa 9654 configured with 96 cores, 80 cores, 64 cores, and 48 cores, which was done by incrementally disabling 2x CCD (8 cores/CCD) at each step. The result is GREAT, as Cloudflare’s simulated primary workload scales linearly with core count on AMD Genoa CPUs.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/f1w9JxhP8aLIoFONMq5tr/b3269fc121b9bfd8f4d9a3394a73c599/image4.png" />
          </figure><div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td>
                        <p><span><span><strong>Core count</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Core increase</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Performance increase</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>48</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>64</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.33x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.39x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>80</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.67x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.71x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>96</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.00x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.05x</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div>
    <div>
      <h3>TDP sensitivity</h3>
      <a href="#tdp-sensitivity">
        
      </a>
    </div>
    <p><a href="https://blog.cloudflare.com/thermal-design-supporting-gen-12-hardware-cool-efficient-and-reliable/"><u>Thermal Design Power (TDP), is the maximum amount of heat generated by a CPU that the cooling system is designed to dissipate</u></a>, but more commonly refers to the power consumption of the processor under the maximum theoretical loads. AMD Genoa 9654’s default TDP is 360W, but can be configured up to 400W TDP. Is more always better? Does Cloudflare continue to see meaningful performance improvement up to 400W, or does performance stagnate at some point?</p><p>The chart below shows the result of sweeping the TDP of the AMD Genoa 9654 (in power determinism mode) from 240W to 400W. (Note: x-axis step size is not linear).</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/216pSnjCDQOLwtRS822ugu/17dc1885d34ae10a8a1cecb6584b7dd7/image3.png" />
          </figure><p>Cloudflare’s simulated primary workload continues to see incremental performance improvements up to the maximum configurable 400W, albeit at a less favorable perf/watt ratio.</p><p>Looking at TDP sensitivity data is a quick and easy way to identify if performance stagnates at some power point, but what does power sensitivity actually measure? There are several factors contributing to CPU power consumption, but let's focus on one of the primary factors: dynamic power consumption. Dynamic power consumption is approximately <i>CV</i><i><sup>2</sup></i><i>f</i>, where C is the switched load capacitance, V is the regulated voltage, and f is the frequency. In modern processors like the AMD Genoa 9654, the CPU dynamically scales its voltage along with frequency, so theoretically, CPU dynamic power is loosely proportional to f<sup>3</sup>. In other words, measuring TDP sensitivity is measuring the frequency sensitivity of a workload. Does the data agree? Yes!</p><div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td>
                        <p><span><span><strong>cTDP</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>All core boost frequency (GHz)</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Perf (rps) / baseline</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>240</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.47</span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.78x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>280</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.75</span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.87x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>320</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.93</span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.93x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>340</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>3.13</span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.97x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>360</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>3.3</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>380</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>3.4</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.03x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>390</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>3.465</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.04x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>400</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>3.55</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.05x</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div>
    <div>
      <h3>Frequency sensitivity</h3>
      <a href="#frequency-sensitivity">
        
      </a>
    </div>
    <p>Instead of relying on an indirect measure through the TDP, let’s measure frequency sensitivity directly by sweeping the maximum boost frequency.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2oobymubOiZrpJjSExQxxo/a02985506ecc803e8b09d7f999b86c55/image2.png" />
          </figure><p>At above 3GHz, the data shows that Cloudflare’s primary workload sees roughly 2% incremental improvement for every 0.1GHz all core average frequency increment. We hit the 400W power cap at 3.545GHz. This is notably higher than the typical all core boost frequency that Cloudflare Gen 11 servers with AMD Milan 7713 at 2.7GHz see in production, or at 2.4GHz in our performance simulation, which is amazing!</p>
    <div>
      <h3>L3 cache size sensitivity</h3>
      <a href="#l3-cache-size-sensitivity">
        
      </a>
    </div>
    <p>What about L3 cache size sensitivity? L3 cache size is one of the primary design choices and major differences between the trio of Genoa, Bergamo, and Genoa-X. Genoa 9654 has 4 MB L3/core, Bergamo 9754 has 2 MB L3/core, and Genoa-X has 12 MB L3/core. L3 cache is the last and largest “memory” bank on-chip before having to access memory on DIMMs outside the chip that would take significantly more CPU cycles.</p><p>We ran an experiment on the Genoa 9654 to check how performance scales with L3 cache size. L3 cache size per core is reduced through MSR writes (but could also be done using <a href="https://www.intel.com/content/www/us/en/developer/articles/technical/use-intel-resource-director-technology-to-allocate-last-level-cache-llc.htm"><u>Intel RDT</u></a>) and L3 cache per core is increased by disabling physical cores in a CCD (which reduces the number of cores sharing the fixed size 32 MB L3 cache per CCD effectively growing the L3 cache per core). Below is the result of the experiment, where &gt;1.00x indicates better performance:</p><div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td>
                        <p><span><span><strong>L3 cache size increase vs baseline 4MB per core</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>0.25x</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>0.5x</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>0.75x</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>1x</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>1.14x</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>1.33x</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>1.60x</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>2.00x</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>rps/core / baseline</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.67x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.78x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.89x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.00x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.08x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.15x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.25x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.31x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>L3 cache miss rate per CCD</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>56.04%</span></span></p>
                    </td>
                    <td>
                        <p><span><span>39.15%</span></span></p>
                    </td>
                    <td>
                        <p><span><span>30.37%</span></span></p>
                    </td>
                    <td>
                        <p><span><span>23.55%</span></span></p>
                    </td>
                    <td>
                        <p><span><span>22.39%</span></span></p>
                    </td>
                    <td>
                        <p><span><span>19.73%</span></span></p>
                    </td>
                    <td>
                        <p><span><span>16.94%</span></span></p>
                    </td>
                    <td>
                        <p><span><span>14.28%</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/cjfPuhUHBfABvQ5hJGchb/e470ca9bb45b0c69b5069556ce866647/image7.png" />
          </figure><p>Even though the expectation was that the impact of a different L3 cache size gets diminished by the faster DDR5 and larger memory bandwidth, Cloudflare’s simulated primary workload is quite sensitive to L3 cache size. The L3 cache miss rate dropped from 56% with only 1 MB L3 per core, to 14.28% with 8 MB L3/core. Changing the L3 cache size by 25% affects the performance by approximately 11%, and we continue to see performance increase to 2x L3 cache size, though the performance increase starts to diminish when we get to 2x L3 cache per core.</p><p>Do we see the same behavior when comparing Genoa 9654, Bergamo 9754 and Genoa-X 9684X? We ran an experiment comparing the impact of L3 cache size, controlling for core count and all core boost frequency, and we also saw significant deltas. Halving the L3 cache size from 4 MB/core to 2 MB/core reduces performance by 24%, roughly matching the experiment above. However, increasing the cache 3x from 4 MB/core to 12 MB/core only increases performance by 25%, less than the indication provided by previous experiments. This is likely because the performance gain we saw on experiment result above could be partially attributed to less cache contention due to reduced number of cores based on how we set up the test. Nevertheless, these are significant deltas!</p><div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td>
                        <p><span><span><strong>L3/core</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>2MB/core</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>4MB/core</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>12MB/core</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Perf (rps) / baseline</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.76x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.25x</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div>
    <div>
      <h3>Putting it all together</h3>
      <a href="#putting-it-all-together">
        
      </a>
    </div>
    <p>The table below summarizes how each factor from sensitivity analysis above contributes to the overall performance gain. There are an additional 6% to 14% of unaccounted performance improvement that are contributed by other factors like larger L2 cache, higher memory bandwidth, and miscellaneous CPU architecture changes that improve IPC.</p><div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td> </td>
                    <td>
                        <p><span><span><strong>Milan</strong></span></span></p>
                        <p><span><span><strong>7713</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Genoa</strong></span></span></p>
                        <p><span><span><strong>9654</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Bergamo</strong></span></span></p>
                        <p><span><span><strong>9754</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Genoa-X</strong></span></span></p>
                        <p><span><span><strong>9684X</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Lab simulation performance multiplier</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.2x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.95x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.75x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Performance multiplier due to Core scaling</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.5x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.5x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Performance multiplier due to Frequency scaling</strong></span></span></p>
                        <p><span><span><strong>(*Note: Milan 7713 all core frequency is ~2.4GHz when running simulated workload at 100% CPU utilization)</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.32x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.21x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.29x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Performance multiplier due to L3 cache size scaling</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>0.76x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.25x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Performance multiplier due to other factors like larger L2 cache, higher memory bandwidth, miscellaneous CPU architecture changes that improve IPC</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.11x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.06x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.14x</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div>
    <div>
      <h2>Performance evaluation in production</h2>
      <a href="#performance-evaluation-in-production">
        
      </a>
    </div>
    <p>How do these CPU candidates perform with real-world traffic and an actual production workload mix? The table below summarizes the performance of the three CPUs in lab simulation and in production. Genoa-X 9684X continues to outperform in production.</p><p>In addition, the Gen 12 server equipped with Genoa-X offered outstanding performance but only consumed 1.5x more power per system than our Gen 11 server with Milan 7713. In other words, we see a 63% increase in performance per watt. Genoa-X 9684X provides the best TCO improvement among the 3 options, and was ultimately chosen as the CPU for our Gen 12 server.</p><div>
    <figure>
        <table>
            <colgroup>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
                <col></col>
            </colgroup>
            <tbody>
                <tr>
                    <td> </td>
                    <td>
                        <p><span><span><strong>Milan 7713</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Genoa 9654</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Bergamo 9754</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span><strong>Genoa-X 9684X</strong></span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Lab simulation performance multiplier</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.2x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.95x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.75x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Production performance multiplier</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.15x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>2.45x</span></span></p>
                    </td>
                </tr>
                <tr>
                    <td>
                        <p><span><span><strong>Production performance per watt multiplier</strong></span></span></p>
                    </td>
                    <td>
                        <p><span><span>1x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.33x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.38x</span></span></p>
                    </td>
                    <td>
                        <p><span><span>1.63x</span></span></p>
                    </td>
                </tr>
            </tbody>
        </table>
    </figure>
</div><p>The Gen 12 server with AMD Genoa-X 9684X is the most powerful and the most power efficient server Cloudflare has built to date. It serves as the underlying platform for all the incredible services that Cloudflare offers to our customers globally, and will help power the growth of Cloudflare infrastructure for the next several years with improved cost structure. </p><p>Hardware engineers at Cloudflare work closely with our infrastructure engineering partners and externally with our vendors to design and develop world-class servers to best serve our customers. </p><p><a href="https://www.cloudflare.com/careers/jobs/"><u>Come join us</u></a> at Cloudflare to help build a better Internet!</p> ]]></content:encoded>
            <category><![CDATA[AMD]]></category>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Cloudflare Network]]></category>
            <guid isPermaLink="false">1Sj8x3oCQRSZqU8oNgMmkE</guid>
            <dc:creator>JQ Lau</dc:creator>
            <dc:creator>Syona Sarma</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare’s 12th Generation servers — 145% more performant and 63% more efficient]]></title>
            <link>https://blog.cloudflare.com/gen-12-servers/</link>
            <pubDate>Wed, 25 Sep 2024 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare is thrilled to announce the general deployment of our next generation of server — Gen 12 powered by AMD Genoa-X processors. This new generation of server focuses on delivering exceptional performance across all Cloudflare services, enhanced support for AI/ML workloads, significant strides in power efficiency, and improved security features. ]]></description>
            <content:encoded><![CDATA[ <p>Cloudflare is thrilled to announce the general deployment of our next generation of servers — Gen 12 powered by AMD EPYC 9684X (code name “Genoa-X”) processors. This next generation focuses on delivering exceptional performance across all Cloudflare services, enhanced support for AI/ML workloads, significant strides in power efficiency, and improved security features.</p><p>Here are some key performance indicators and feature improvements that this generation delivers as compared to the <a href="https://blog.cloudflare.com/the-epyc-journey-continues-to-milan-in-cloudflares-11th-generation-edge-server/"><u>prior generation</u></a>: </p><p>Beginning with performance, with close engineering collaboration between Cloudflare and AMD on optimization, Gen 12 servers can serve more than twice as many requests per second (RPS) as Gen 11 servers, resulting in lower Cloudflare infrastructure build-out costs.</p><p>Next, our power efficiency has improved significantly, by more than 60% in RPS per watt as compared to the prior generation. As Cloudflare continues to expand our infrastructure footprint, the improved efficiency helps reduce Cloudflare’s operational expenditure and carbon footprint as a percentage of our fleet size.</p><p>Third, in response to the growing demand for AI capabilities, we've updated the thermal-mechanical design of our Gen 12 server to support more powerful GPUs. This aligns with the <a href="https://www.cloudflare.com/lp/pg-ai/?utm_medium=cpc&amp;utm_source=google&amp;utm_campaign=2023-q4-acq-gbl-developers-wo-ge-general-paygo_mlt_all_g_search_bg_exp__dev&amp;utm_content=workers-ai&amp;gad_source=1&amp;gclid=CjwKCAjwl6-3BhBWEiwApN6_kjigJdDvEYqHPYi8tdXuTe4APbqX923v-CBjpGiAVwITNhp8GrW3ARoCyJ4QAvD_BwE&amp;gclsrc=aw.ds"><u>Workers AI</u></a> objective to support larger large language models and increase throughput for smaller models. This enhancement underscores our ongoing commitment to advancing AI inference capabilities</p><p>Fourth, to underscore our security-first position as a company, we've integrated hardware <a href="https://trustedcomputinggroup.org/about/what-is-a-root-of-trust-rot/"><u>root of trust</u></a> (HRoT) capabilities to ensure the integrity of boot firmware and board management controller firmware. Continuing to embrace open standards, the baseboard management and security controller (Data Center Secure Control Module or <a href="https://drive.google.com/file/d/13BxuseSrKo647hjIXjp087ei8l5QQVb0/view"><u>OCP DC-SCM</u></a>) that we’ve designed into our systems is modular and vendor-agnostic, enabling a unified <a href="https://www.openbmc.org/"><u>openBMC</u></a> image, quicker prototyping, and allowing for reuse.</p><p>Finally, given the increasing importance of supply assurance and reliability in infrastructure deployments, our approach includes a robust multi-vendor strategy to mitigate supply chain risks, ensuring continuity and resiliency of our infrastructure deployment.</p><p>Cloudflare is dedicated to constantly improving our server fleet, empowering businesses worldwide with enhanced performance, efficiency, and security.</p>
    <div>
      <h2>Gen 12 Servers </h2>
      <a href="#gen-12-servers">
        
      </a>
    </div>
    <p>Let's take a closer look at our Gen 12 server. The server is powered by a 4th generation AMD EPYC Processor, paired with 384 GB of DDR5 RAM, 16 TB of NVMe storage, a dual-port 25 GbE NIC, and two 800 watt power supply units.</p>
<div><table><thead>
  <tr>
    <th><span>Generation</span></th>
    <th><span>Gen 12 Compute</span></th>
    <th><span>Previous Gen 11 Compute</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Form Factor</span></td>
    <td><span>2U1N - Single socket</span></td>
    <td><span>1U1N - Single socket</span></td>
  </tr>
  <tr>
    <td><span>Processor</span></td>
    <td><span>AMD EPYC 9684X Genoa-X 96-Core Processor</span></td>
    <td><span>AMD EPYC 7713 Milan 64-Core Processor</span></td>
  </tr>
  <tr>
    <td><span>Memory</span></td>
    <td><span>384GB of DDR5-4800</span><br /><span>x12 memory channel</span></td>
    <td><span>384GB of DDR4-3200</span><br /><span>x8 memory channel</span></td>
  </tr>
  <tr>
    <td><span>Storage</span></td>
    <td><span>x2 E1.S NVMe</span><br /><span>Samsung PM9A3 7.68TB / Micron 7450 Pro 7.68TB</span></td>
    <td><span>x2 M.2 NVMe</span><br /><span>2x Samsung PM9A3 x 1.92TB</span></td>
  </tr>
  <tr>
    <td><span>Network</span></td>
    <td><span>Dual 25 Gbe OCP 3.0 </span><br /><span>Intel Ethernet Network Adapter E810-XXVDA2 / NVIDIA Mellanox ConnectX-6 Lx</span></td>
    <td><span>Dual 25 Gbe OCP 2.0</span><br /><span>Mellanox ConnectX-4 dual-port 25G</span></td>
  </tr>
  <tr>
    <td><span>System Management</span></td>
    <td><span>DC-SCM 2.0</span><br /><span>ASPEED AST2600 (BMC) + AST1060 (HRoT)</span></td>
    <td><span>ASPEED AST2500 (BMC)</span></td>
  </tr>
  <tr>
    <td><span>Power Supply</span></td>
    <td><span>800W - Titanium Grade</span></td>
    <td><span>650W - Titanium Grade</span></td>
  </tr>
</tbody></table></div>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/ywinOgSFpevEcQSZLhESv/b61d70a1504b4d873d0bbf2e83221bf6/BLOG-2116_2.png" />
          </figure><p><sup><i>Cloudflare Gen 12 server</i></sup></p>
    <div>
      <h3>CPU</h3>
      <a href="#cpu">
        
      </a>
    </div>
    <p>During the design phase, we conducted an extensive survey of the CPU landscape. These options offer valuable choices as we consider how to shape the future of Cloudflare's server technology to match the needs of our customers. We evaluated many candidates in the lab, and short-listed three standout CPU candidates from the 4th generation AMD EPYC Processor lineup: Genoa 9654, Bergamo 9754, and Genoa-X 9684X for production evaluation. The table below summarizes the differences in <a href="https://www.amd.com/content/dam/amd/en/documents/products/epyc/epyc-9004-series-processors-data-sheet.pdf"><u>specifications</u></a> of the short-listed candidates for Gen 12 servers against the AMD EPYC 7713 used in our Gen 11 servers. Notably, all three candidates offer significant increase in core count and marked increase in all core boost clock frequency.</p>
<div><table><thead>
  <tr>
    <th><span>CPU Model</span></th>
    <th><a href="https://www.amd.com/en/products/specifications/server-processor.html"><span>AMD EPYC 7713</span></a></th>
    <th><a href="https://www.amd.com/en/products/specifications/server-processor.html"><span>AMD EPYC 9654</span></a></th>
    <th><a href="https://www.amd.com/en/products/specifications/server-processor.html"><span>AMD EPYC 9754</span></a></th>
    <th><a href="https://www.amd.com/en/products/specifications/server-processor.html"><span>AMD EPYC 9684X</span></a></th>
  </tr>
</thead>
<tbody>
  <tr>
    <td><span>Series</span></td>
    <td><span>Milan</span></td>
    <td><span>Genoa</span></td>
    <td><span>Bergamo</span></td>
    <td><span>Genoa-X</span></td>
  </tr>
  <tr>
    <td><span># of CPU Cores</span></td>
    <td><span>64</span></td>
    <td><span>96</span></td>
    <td><span>128</span></td>
    <td><span>96</span></td>
  </tr>
  <tr>
    <td><span># of Threads</span></td>
    <td><span>128</span></td>
    <td><span>192</span></td>
    <td><span>256</span></td>
    <td><span>192</span></td>
  </tr>
  <tr>
    <td><span>Base Clock</span></td>
    <td><span>2.0 GHz</span></td>
    <td><span>2.4 GHz</span></td>
    <td><span>2.25 GHz</span></td>
    <td><span>2.4 GHz</span></td>
  </tr>
  <tr>
    <td><span>Max Boost Clock</span></td>
    <td><span>3.67 GHz</span></td>
    <td><span>3.7 Ghz</span></td>
    <td><span>3.1 Ghz</span></td>
    <td><span>3.7 Ghz</span></td>
  </tr>
  <tr>
    <td><span>All Core Boost Clock</span></td>
    <td><span>2.7 GHz *</span></td>
    <td><span>3.55 GHz</span></td>
    <td><span>3.1GHz</span></td>
    <td><span>3.42 GHz</span></td>
  </tr>
  <tr>
    <td><span>Total L3 Cache</span></td>
    <td><span>256 MB</span></td>
    <td><span>384 MB</span></td>
    <td><span>256 MB</span></td>
    <td><span>1152 MB</span></td>
  </tr>
  <tr>
    <td><span>L3 cache per core</span></td>
    <td><span>4MB / core</span></td>
    <td><span>4MB / core</span></td>
    <td><span>2MB / core</span></td>
    <td><span>12MB / core</span></td>
  </tr>
  <tr>
    <td><span>Maximum configurable TDP</span></td>
    <td><span>240W</span></td>
    <td><span>400W</span></td>
    <td><span>400W</span></td>
    <td><span>400W</span></td>
  </tr>
</tbody></table></div><p><sub>*Note: AMD EPYC 7713 all core boost clock frequency of 2.7 GHz is not an official specification of the CPU but based on data collected at Cloudflare production fleet.</sub></p><p>During production evaluation, the configuration of all three CPUs were optimized to the best of our knowledge, including thermal design power (TDP) configured to 400W for maximum performance. The servers are set up to run the same processes and services like any other server we have in production, which makes for a great side-by-side comparison. </p>
<div><table><thead>
  <tr>
    <th></th>
    <th><span>Milan 7713</span></th>
    <th><span>Genoa 9654</span></th>
    <th><span>Bergamo 9754</span></th>
    <th><span>Genoa-X 9684X</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Production performance (request per second) multiplier</span></td>
    <td><span>1x</span></td>
    <td><span>2x</span></td>
    <td><span>2.15x</span></td>
    <td><span>2.45x</span></td>
  </tr>
  <tr>
    <td><span>Production efficiency (request per second per watt) multiplier</span></td>
    <td><span>1x</span></td>
    <td><span>1.33x</span></td>
    <td><span>1.38x</span></td>
    <td><span>1.63x</span></td>
  </tr>
</tbody></table></div>
    <div>
      <h4>AMD EPYC Genoa-X in Cloudflare Gen 12 server</h4>
      <a href="#amd-epyc-genoa-x-in-cloudflare-gen-12-server">
        
      </a>
    </div>
    <p>Each of these CPUs outperforms the previous generation of processors by at least 2x. AMD EPYC 9684X Genoa-X with 3D V-cache technology gave us the greatest performance improvement, at 2.45x, when compared against our Gen 11 servers with AMD EPYC 7713 Milan.</p><p>Comparing the performance between Genoa-X 9684X and Genoa 9654, we see a ~22.5% performance delta. The primary difference between the two CPUs is the amount of L3 cache available on the CPU. Genoa-X 9684X has 1152 MB of L3 cache, which is three times the Genoa 9654 with 384 MB of L3 cache. Cloudflare workloads benefit from more low level cache being accessible and avoid the much larger latency penalty associated with fetching data from memory.</p><p>Genoa-X 9684X CPU delivered ~22.5% improved performance consuming the same amount of 400W power compared to Genoa 9654. The 3x larger L3 cache does consume additional power, but only at the expense of sacrificing 3% of highest achievable all core boost frequency on Genoa-X 9684X, a favorable trade-off for Cloudflare workloads.</p><p>More importantly, Genoa-X 9684X CPU delivered 145% performance improvement with only 50% system power increase, offering a 63% power efficiency improvement that will help drive down operational expenditure tremendously. It is important to note that even though a big portion of the power efficiency is due to the CPU, it needs to be paired with optimal thermal-mechanical design to realize the full benefit. Earlier last year, <a href="https://blog.cloudflare.com/cloudflare-gen-12-server-bigger-better-cooler-in-a-2u1n-form-factor/"><u>we made the thermal-mechanical design choice to double the height of the server chassis to optimize rack density and cooling efficiency across our global data centers</u></a>. We estimated that moving from 1U to 2U would reduce fan power by 150W, which would decrease system power from 750 watts to 600 watts. Guess what? We were right — a Gen 12 server consumes 600 watts per system at a typical ambient temperature of 25°C.</p><p>While high performance often comes at a higher price, fortunately AMD EPYC 9684X offer an excellent balance between cost and capability. A server designed with this CPU provides top-tier performance without necessitating a huge financial outlay, resulting in a good Total Cost of Ownership improvement for Cloudflare.</p>
    <div>
      <h3>Memory</h3>
      <a href="#memory">
        
      </a>
    </div>
    <p>AMD Genoa-X CPU supports twelve memory channels of DDR5 RAM up to 4800 mega transfers per second (MT/s) and per socket Memory Bandwidth of 460.8 GB/s. The twelve channels are fully utilized with 32 GB ECC 2Rx8 DDR5 RDIMM with one DIMM per channel configuration for a combined total memory capacity of 384 GB. </p><p>Choosing the optimal memory capacity is a balancing act, as maintaining an optimal memory-to-core ratio is important to make sure CPU capacity or memory capacity is not wasted. Some may remember that our Gen 11 servers with 64 core AMD EPYC 7713 CPUs are also configured with 384 GB of memory, which is about 6 GB per core. So why did we choose to configure our Gen 12 servers with 384 GB of memory when the core count is growing to 96 cores? Great question! A lot of memory optimization work has happened since we introduced Gen 11, including some that we blogged about, like <a href="https://blog.cloudflare.com/scalable-machine-learning-at-cloudflare/"><u>Bot Management code optimization</u></a> and <a href="https://blog.cloudflare.com/how-we-built-pingora-the-proxy-that-connects-cloudflare-to-the-internet/"><u>our transition to highly efficient Pingora</u></a>. In addition, each service has a memory allocation that is sized for optimal performance. The per-service memory allocation is programmed and monitored utilizing Linux control group resource management features. When sizing memory capacity for Gen 12, we consulted with the team who monitor resource allocation and surveyed memory utilization metrics collected from our fleet. The result of the analysis is that the optimal memory-to-core ratio is 4 GB per CPU core, or 384 GB total memory capacity. This configuration is validated in production. We chose dual rank memory modules over single rank memory modules because they have higher memory throughput, which improves server performance (read more about <a href="https://blog.cloudflare.com/ddr4-memory-organization-and-how-it-affects-memory-bandwidth/"><u>memory module organization and its effect on memory bandwidth</u></a>). </p><p>The table below shows the result of running the <a href="https://www.intel.com/content/www/us/en/developer/articles/tool/intelr-memory-latency-checker.html"><u>Intel Memory Latency Checker (MLC)</u></a> tool to measure peak memory bandwidth for the system and to compare memory throughput between 12 channels of dual-rank (2Rx8) 32 GB DIMM and 12 channels of single rank (1Rx4) 32 GB DIMM. Dual rank DIMMs have slightly higher (1.8%) read memory bandwidth, but noticeably higher write bandwidth. As write ratios increased from 25% to 50%, the memory throughput delta increased by 10%.</p>
<div><table><thead>
  <tr>
    <th><span>Benchmark</span></th>
    <th><span>Dual rank advantage over single rank</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Intel MLC ALL Reads</span></td>
    <td><span>101.8%</span></td>
  </tr>
  <tr>
    <td><span>Intel MLC 3:1 Reads-Writes</span></td>
    <td><span>107.7%</span></td>
  </tr>
  <tr>
    <td><span>Intel MLC 2:1 Reads-Writes</span></td>
    <td><span>112.9%</span></td>
  </tr>
  <tr>
    <td><span>Intel MLC 1:1 Reads-Writes</span></td>
    <td><span>117.8%</span></td>
  </tr>
  <tr>
    <td><span>Intel MLC Stream-triad like</span></td>
    <td><span>108.6%</span></td>
  </tr>
</tbody></table></div><p>The table below shows the result of running the <a href="https://www.amd.com/en/developer/zen-software-studio/applications/spack/stream-benchmark.html"><u>AMD STREAM benchmark</u></a> to measure sustainable main memory bandwidth in MB/s and the corresponding computation rate for simple vector kernels. In all 4 types of vector kernels, dual rank DIMMs provide a noticeable advantage over single rank DIMMs.</p>
<div><table><thead>
  <tr>
    <th><span>Benchmark</span></th>
    <th><span>Dual rank advantage over single rank</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Stream Copy</span></td>
    <td><span>115.44%</span></td>
  </tr>
  <tr>
    <td><span>Stream Scale</span></td>
    <td><span>111.22%</span></td>
  </tr>
  <tr>
    <td><span>Stream Add</span></td>
    <td><span>109.06%</span></td>
  </tr>
  <tr>
    <td><span>Stream Triad</span></td>
    <td><span>107.70%</span></td>
  </tr>
</tbody></table></div>
    <div>
      <h3>Storage</h3>
      <a href="#storage">
        
      </a>
    </div>
    <p>Cloudflare’s Gen X server and Gen 11 server support <a href="https://en.wikipedia.org/wiki/M.2"><u>M.2</u></a> form factor drives. We liked the M.2 form factor mainly because it was compact. The M.2 specification was introduced in 2012, but today, the connector system is dated and the industry has concerns about its ability to maintain signal integrity with the high speed signal specified by <a href="https://www.xda-developers.com/pcie-5/"><u>PCIe 5.0</u></a> and <a href="https://pcisig.com/pci-express-6.0-specification"><u>PCIe 6.0</u></a> specifications. The 8.25W thermal limit of the M.2 form factor also limits the number of flash dies that can be fitted, which limits the maximum supported capacity per drive. To address these concerns, the industry has introduced the <a href="https://americas.kioxia.com/content/dam/kioxia/en-us/business/ssd/data-center-ssd/asset/KIOXIA_Meta_Microsoft_EDSFF_E1_S_Intro_White_Paper.pdf"><u>E1.S</u></a> specification and is transitioning from the M.2 form factor to the E1.S form factor. </p><p>In Gen 12, we are making the change to the <a href="https://www.snia.org/forums/cmsi/knowledge/formfactors#EDSFF"><u>EDSFF</u></a> E1 form factor, more specifically the E1.S 15mm. E1.S 15mm, though still in a compact form factor, provides more space to fit more flash dies for larger capacity support. The form factor also has better cooling design to support more than 25W of sustained power.</p><p>While the AMD Genoa-X CPU supports 128 PCIe 5.0 lanes, we continue to use NVMe devices with PCIe Gen 4.0 x4 lanes, as PCIe Gen 4.0 throughput is sufficient to meet drive bandwidth requirements and keep server design costs optimal. The server is equipped with two 8 TB NVMe drives for a total of 16 TB available storage. We opted for two 8 TB drives instead of four 4 TB drives because the dual 8 TB configuration already provides sufficient I/O bandwidth for all Cloudflare workloads that run on each server.</p>
<div><table><thead>
  <tr>
    <th><span>Sequential Read (MB/s) :</span></th>
    <th><span>6,700</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Sequential Write (MB/s) :</span></td>
    <td><span>4,000</span></td>
  </tr>
  <tr>
    <td><span>Random Read IOPS:</span></td>
    <td><span>1,000,000</span></td>
  </tr>
  <tr>
    <td><span>Random Write IOPS: </span></td>
    <td><span>200,000</span></td>
  </tr>
  <tr>
    <td><span>Endurance</span></td>
    <td><span>1 DWPD</span></td>
  </tr>
  <tr>
    <td><span>PCIe GEN4 x4 lane throughput</span></td>
    <td><span>7880 MB/s</span></td>
  </tr>
</tbody></table></div><p><sub><i>Storage devices performance specification</i></sub></p>
    <div>
      <h3>Network</h3>
      <a href="#network">
        
      </a>
    </div>
    <p>Cloudflare servers and top-of-rack (ToR) network equipment operate at <a href="https://en.wikipedia.org/wiki/25_Gigabit_Ethernet"><u>25 GbE</u></a> speeds. In Gen 12, we utilized a <a href="https://www.opencompute.org/wiki/Server/DC-MHS"><u>DC-MHS</u></a> motherboard-inspired design, and upgraded from an <a href="https://drive.google.com/file/d/1VGAtABAKU9fq3KfClYhFOgGFN3oe63Uw/view?usp=sharing"><u>OCP 2.0 form factor</u></a> to an <a href="https://drive.google.com/file/d/1U3oEGiSWfupG4SnIdPuJ_8Nte2lJRqTN/view?usp=sharing"><u>OCP 3.0 form factor</u></a>, which provides tool-less serviceability of the NIC. The OCP 3.0 form factor also occupies less space in the 2U server compared to PCIe-attached NICs, which improves airflow and frees up space for other application-specific PCIe cards, such as GPUs.</p><p>Cloudflare has been using the Mellanox CX4-Lx EN dual port 25 GbE NIC since our <a href="https://blog.cloudflare.com/a-tour-inside-cloudflares-g9-servers/"><u>Gen 9 servers in 2018</u></a>. Even though the NIC has served us well over the years, we are single sourced. During the pandemic, we were faced with supply constraints and extremely long lead times. The team scrambled to qualify the Broadcom M225P dual port 25 GbE NIC as our second-sourced NIC in 2022, ensuring we could continue to turn up servers to serve customer demand. With the lessons learned from single-sourcing the Gen 11 NIC, we are now dual-sourcing and have chosen the Intel Ethernet Network Adapter E810 and NVIDIA Mellanox ConnectX-6 Lx to support Gen 12. These two NICs are compliant with the <a href="https://www.opencompute.org/wiki/Server/NIC"><u>OCP 3.0 specification</u></a> and offer more MSI-X queues that can then be mapped to the increased core count on the AMD EPYC 9684X. The Intel Ethernet Network Adapter comes with an additional advantage, offering full Generic Segmentation Offload (GSO) support including VLAN-tagged encapsulated traffic, whereast many vendors either only support <a href="https://netdevconf.info/1.2/papers/LCO-GSO-Partial-TSO-MangleID.pdf"><u>Partial GSO</u></a> or do not support it at all today. With Full GSO support, the kernel spent noticeably less time in softirq segmenting packets, and servers with Intel E810 NICs are processing approximately 2% more requests per second.</p>
    <div>
      <h3>Improved security with DC-SCM: Project Argus</h3>
      <a href="#improved-security-with-dc-scm-project-argus">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6ur3YccqqXckIL6oWKd6Lq/5352252ff8e5c1fb15eb02d1572a0689/BLOG-2116_3.png" />
          </figure><p><sup><i>DC-SCM in Gen 12 server (Project Argus)</i></sup></p><p>Gen 12 servers are integrated with <a href="https://blog.cloudflare.com/introducing-the-project-argus-datacenter-ready-secure-control-module-design-specification/"><u>Project Argus</u></a>, one of the industry first implementations of <a href="https://drive.google.com/file/d/13BxuseSrKo647hjIXjp087ei8l5QQVb0/view"><u>Data Center Secure Control Module 2.0 (DC-SCM 2.0)</u></a>. DC-SCM 2.0 decouples server management and security functions away from the motherboard. The baseboard management controller (BMC), hardware root of trust (HRoT), trusted platform module (TPM), and dual BMC/BIOS flash chips are all installed on the DC-SCM. </p><p>On our Gen X and Gen 11 server, Cloudflare moved our secure boot trust anchor from the system Basic Input/Output System (BIOS) or the Unified Extensible Firmware Interface (UEFI) firmware to hardware-rooted boot integrity — <a href="https://blog.cloudflare.com/anchoring-trust-a-hardware-secure-boot-story/"><u>AMD’s implementation of Platform Secure Boot (PSB)</u></a> or <a href="https://blog.cloudflare.com/armed-to-boot/"><u>Ampere’s implementation of Single Domain Secure Boot</u></a>. These solutions helped secure Cloudflare infrastructure from BIOS / UEFI firmware attacks. However, we are still vulnerable to out-of-band attacks through compromising the BMC firmware. BMC is a microcontroller that provides out-of-band monitoring and management capabilities for the system. When compromised, attackers can read processor console logs accessible by BMC and control server power states for example. On Gen 12, the HRoT on the DC-SCM serves as the trust store of cryptographic keys and is responsible to authenticate the BIOS/UEFI firmware (independent of CPU vendor) and the BMC firmware for secure boot process.</p><p>In addition, on the DC-SCM, there are additional flash storage devices to enable storing back-up BIOS/UEFI firmware and BMC firmware to allow rapid recovery when a corrupted or malicious firmware is programmed, and to be resilient to flash chip failure due to aging.</p><p>These updates make our Gen 12 server more secure and more resilient to firmware attacks.</p>
    <div>
      <h3>Power</h3>
      <a href="#power">
        
      </a>
    </div>
    <p>A Gen 12 server consumes 600 watts at a typical ambient temperature of 25°C. Even though this is a 50% increase from the 400 watts consumed by the Gen 11 server, as mentioned above in the CPU section, this is a relatively small price to pay for a 145% increase in performance. We’ve paired the server up with dual 800W common redundant power supplies (CRPS) with 80 PLUS Titanium grade efficiency. Both power supply units (PSU) operate actively with distributed power and current. The units are hot-pluggable, allowing the server to operate with redundancy and maximize uptime.</p><p><a href="https://www.clearesult.com/80plus/program-details"><u>80 PLUS</u></a> is a PSU efficiency certification program. The Titanium grade efficiency PSU is 2% more efficient than the Platinum grade efficiency PSU between typical operating load of 25% to 50%. 2% may not sound like a lot, but considering the size of Cloudflare fleet with servers deployed worldwide, 2% savings over the lifetime of all Gen 12 deployment is a reduction of more than 7 GWh, <a href="https://www.epa.gov/energy/greenhouse-gas-equivalencies-calculator#results"><u>equivalent to carbon sequestered by more than 3400 acres of U.S. forests in one year</u></a>.  This upgrade also means our Gen 12 server complies with <a href="https://www.unicomengineering.com/blog/eu-lot-9-update-the-coming-server-power-migration/"><u>EU Lot9 requirements</u></a> and can be deployed in the EU region.</p>
<div><table><thead>
  <tr>
    <th><span>80 PLUS certification</span></th>
    <th><span>10%</span></th>
    <th><span>20%</span></th>
    <th><span>50%</span></th>
    <th><span>100%</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>80 PLUS Platinum</span></td>
    <td><span>-</span></td>
    <td><span>92%</span></td>
    <td><span>94%</span></td>
    <td><span>90%</span></td>
  </tr>
  <tr>
    <td><span>80 PLUS Titanium</span></td>
    <td><span>90%</span></td>
    <td><span>94%</span></td>
    <td><span>96%</span></td>
    <td><span>91%</span></td>
  </tr>
</tbody></table></div>
    <div>
      <h3>Drop-in GPU support</h3>
      <a href="#drop-in-gpu-support">
        
      </a>
    </div>
    <p>Demand for machine learning and AI workloads exploded in 2023, and Cloudflare <a href="https://blog.cloudflare.com/workers-ai/"><u>introduced Workers AI </u></a>to serve the needs of our customers. Cloudflare retrofitted or deployed GPUs worldwide in a portion of our Gen 11 server fleet to support the growth of Workers AI. Our Gen 12 server is also designed to accommodate the addition of more powerful GPUs. This gives Cloudflare the flexibility to support Workers AI in all regions of the world, and to strategically place GPUs in regions to reduce inference latency for our customers. With this design, the server can run Cloudflare’s full software stack. During times when GPUs see lower utilization, the server continues to serve general web requests and remains productive.</p><p>The electrical design of the motherboard is designed to support up to two PCIe add-in cards and the power distribution board is sized to support an additional 400W of power. The mechanics are sized to support either a single FHFL (full height, full length) double width GPU PCIe card, or two FHFL single width GPU PCIe cards. The thermal solution including the component placement, fans, and air duct design are sized to support adding GPUs with TDP up to 400W.</p>
    <div>
      <h3>Looking to the future</h3>
      <a href="#looking-to-the-future">
        
      </a>
    </div>
    <p>Gen 12 Servers are currently deployed and live in multiple Cloudflare data centers worldwide, and already process millions of requests per second. Cloudflare’s EPYC journey has not ended — the 5th-gen AMD EPYC CPUs (code name “Turin”) are already available for testing, and we are very excited to start the architecture planning and design discussion for the Gen 13 server. <a href="https://www.cloudflare.com/careers/jobs/"><u>Come join us</u></a> at Cloudflare to help build a better Internet!</p> ]]></content:encoded>
            <category><![CDATA[Birthday Week]]></category>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[AMD]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Cloudflare Network]]></category>
            <category><![CDATA[Hardware]]></category>
            <guid isPermaLink="false">sdvPBDBwhcEcrODVeOE7A</guid>
            <dc:creator>JQ Lau</dc:creator>
            <dc:creator>Ma Xiong</dc:creator>
            <dc:creator>Syona Sarma</dc:creator>
        </item>
        <item>
            <title><![CDATA[Measuring Hyper-Threading and Turbo Boost]]></title>
            <link>https://blog.cloudflare.com/measuring-hyper-threading-and-turbo-boost/</link>
            <pubDate>Tue, 05 Oct 2021 12:58:35 GMT</pubDate>
            <description><![CDATA[ Contemporary x86 processors implement some variants of Hyper-Threading and Turbo Boost. We decided to learn about the implications of these two technologies. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>We often put together experiments that measure hardware performance to improve our understanding and provide insights to our hardware partners. We recently wanted to know more about Hyper-Threading and Turbo Boost. The last time we assessed these two technologies was when we were still <a href="/a-tour-inside-cloudflares-g9-servers/">deploying the Intel Xeons</a> (Skylake/Purley), but beginning with our Gen X servers we <a href="/technical-details-of-why-cloudflare-chose-amd-epyc-for-gen-x-servers/">switched over to the AMD EPYC</a> (Zen 2/Rome). This blog is about our latest attempt at quantifying the performance impact of Hyper-Threading and Turbo Boost on our AMD-based servers running our software stack.</p><p>Intel briefly introduced Hyper-Threading with NetBurst (Northwood) back in 2002, then reintroduced Hyper-Threading six years later with Nehalem along with Turbo Boost. AMD presented their own implementation of these technologies with Zen in 2017, but AMD’s version of Turbo Boost actually dates back to AMD K10 (Thuban), in 2010, when it used to be called Turbo Core. Since Zen, Hyper-Threading and Turbo Boost are known as simultaneous multithreading (SMT) and Core Performance Boost (CPB), respectively. The underlying implementation of Hyper-Threading and Turbo Boost differs between the two vendors, but the high-level concept remains the same.</p><p>Hyper-Threading or simultaneous multithreading creates a second hardware thread within a processor’s core, also known as a logical core, by duplicating various parts of the core to support the context of a second application thread. The two hardware threads execute simultaneously within the core, across their dedicated and remaining shared resources. If neither hardware threads contend over a particular shared resource, then the throughput can be drastically increased.</p><p>Turbo Boost or Core Performance Boost opportunistically allows the processor to operate beyond its rated base frequency as long as the processor operates within guidelines set by Intel or AMD. Generally speaking, the higher the frequency, the faster the processor finishes a task.</p>
    <div>
      <h2>Simulated Environment</h2>
      <a href="#simulated-environment">
        
      </a>
    </div>
    
    <div>
      <h3>CPU Specification</h3>
      <a href="#cpu-specification">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/STcQJqLbUhlxNm7hYmEc7/b33ed9909e4c56c6db4eb7d8090447dc/image2-12.png" />
            
            </figure><p>Our <a href="/cloudflares-gen-x-servers-for-an-accelerated-future/">Gen X or 10th generation servers</a> are powered by the <a href="https://www.amd.com/en/products/cpu/amd-epyc-7642">AMD EPYC 7642</a>, based on the Zen 2 microarchitecture. The vast majority of the Zen 2-based processors along with its successor Zen 3 that our <a href="/the-epyc-journey-continues-to-milan-in-cloudflares-11th-generation-edge-server/">Gen 11 servers are based on</a>, supports simultaneous multithreading and Core Performance Boost.</p><p>Similar to Intel’s Hyper-Threading, AMD implemented 2-way simultaneous multithreading. The AMD EPYC 7642 has 48 cores, and with simultaneous multithreading enabled it can simultaneously execute 96 hardware threads. Core Performance Boost allows the AMD EPYC 7642 to operate anywhere between 2.3 to 3.3 GHz, depending on the workload and limitations imposed on the processor. With Core Performance Boost disabled, the processor will operate at 2.3 GHz, the rated base frequency on the AMD EPYC 7642. We took our usual simulated traffic pattern of 10 KiB cached assets over HTTPS, <a href="/keepalives-considered-harmful/">provided by our performance team</a>, to generate a sustained workload that saturated the processor to 100% CPU utilization.</p>
    <div>
      <h3>Results</h3>
      <a href="#results">
        
      </a>
    </div>
    <p>After establishing a baseline with simultaneous multithreading and Core Performance Boost disabled, we started enabling one feature at a time. When we enabled Core Performance Boost, the processor operated near its peak turbo frequency, hovering between 3.2 to 3.3 GHz which is more than 39% higher than the base frequency. Higher operating frequency directly translated into 40% additional requests per second. We then disabled Core Performance Boost and enabled simultaneous multithreading. Similar to Core Performance Boost, simultaneous multithreading alone improved requests per second by 43%. Lastly, by enabling both features, we observed an 86% improvement in requests per second.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2NfKzNxMrKrtufGQuYjcHp/483e38c99e370940454158898f7fbe76/image4-8.png" />
            
            </figure><p>Latencies were generally lowered by either or both Core Performance Boost and simultaneous multithreading. While Core Performance Boost consistently maintained a lower latency than the baseline, simultaneous multithreading gradually took longer to process a request as it reached tail latencies. Though not depicted in the figure below, when we examined beyond p9999 or 99.99th percentile, simultaneous multithreading, even with the help of Core Performance Boost, exponentially increased in latency by more than 150% over the baseline, presumably due to the two hardware threads contending over a shared resource within the core.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4aLHnhtg8eOGWoUCBe2g98/2865b9db5d5746d47c510ea6e80eec8f/image7-4.png" />
            
            </figure>
    <div>
      <h2>Production Environment</h2>
      <a href="#production-environment">
        
      </a>
    </div>
    <p>Moving into production, since our <a href="https://radar.cloudflare.com/">traffic fluctuates throughout the day</a>, we took four identical Gen X servers and measured in parallel during peak hours. The only changes we made to the servers were enabling and disabling simultaneous multithreading and Core Performance Boost to create a comprehensive test matrix. We conducted the experiment in two different regions to identify any anomalies and mismatching trends. All trends were alike.</p><p>Before diving into the results, we should preface that the baseline server operated at a higher CPU utilization than others. Every generation, our servers deliver a noticeable improvement in performance. So our load balancer, named Unimog, <a href="/unimog-cloudflares-edge-load-balancer/">sends a different number of connections to the target server based on its generation</a> to balance out the CPU utilization. When we disabled simultaneous multithreading and Core Performance Boost, the baseline server’s performance degraded to the point where Unimog encountered a “guard rail” or the lower limit on the requests sent to the server, and so its CPU utilization rose instead. Given that the baseline server operated at a higher CPU utilization, the baseline server processed more requests per second to meet the minimum performance threshold.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4f2ViyRNLst20bSKZ5I9fe/4fddc3014f888809e9b0a9f120234004/image8-5.png" />
            
            </figure>
    <div>
      <h3>Results</h3>
      <a href="#results">
        
      </a>
    </div>
    <p>Due to the skewed baseline, when core performance boost was enabled, we only observed 7% additional requests per second. Next, simultaneous multithreading alone improved requests per second by 41%. Lastly, with both features enabled, we saw an 86% improvement in requests per second.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6E6GlehsjYmQmKnpjxgkut/cb7c54930c5d90c16d8ce45ecea429fe/image6-6.png" />
            
            </figure><p>Though we lack concrete baseline data, we can normalize requests per second by CPU utilization to approximate the improvement for each scenario. Once normalized, the estimated improvement in requests per second from core performance boost and simultaneous multithreading were 36% and 80%, respectively. With both features enabled, requests per second improved by 136%.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6OGBo0BJ9POefn6afYw5Mc/97f445ce481673d379a7f52ec2907be6/image5-6.png" />
            
            </figure><p>Latency was not as interesting since the baseline server operated at a higher CPU utilization, and in turn, it produced a higher tail latency than we would have otherwise expected. All other servers maintained a lower latency due to their lower CPU utilization in conjunction with Core Performance Boost, simultaneous multithreading, or both.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4JPkPm4EP6DXEGd99nSyVo/5adb7926ab3a25c02ecf4b7c5e74d14b/image1-10.png" />
            
            </figure><p>At this point, our experiment did not go as we had planned. Our baseline is skewed, and we only got half useful answers. However, we find experimenting to be important because we usually end up finding other helpful insights as well.</p><p>Let’s add power data. Since our baseline server was operating at a higher CPU utilization, we knew it was serving more requests and therefore, consumed more power than it needed to. Enabling Core Performance Boost allowed the processor to run up to its peak turbo frequency, increasing power consumption by 35% over the skewed baseline. More interestingly, enabling simultaneous multithreading increased power consumption by only 7%. Combining Core Performance Boost with simultaneous multithreading resulted in 58% increase in power consumption.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5Qxyi4d9qWZDxc7F09w0bv/73b88a522a15b35d5796478fdb11b6de/image3-6.png" />
            
            </figure><p>AMD’s implementation of simultaneous multithreading appears to be power efficient as it achieves 41% additional requests per second while consuming only 7% more power compared to the skewed baseline. For completeness, using the data we have, we bridged performance and power together to obtain performance per watt to summarize power efficiency. We divided the non-normalized requests per second by power consumption to produce the requests per watt figure below. Our Gen X servers attained the best performance per watt by enabling just simultaneous multithreading.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5ZY19SD0eKHUmUo6Zx3bCA/2b0250f752aea47f944a4c6d0b77bf5c/image9-4.png" />
            
            </figure>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>In our assessment of AMD’s implementation of Hyper-Threading and Turbo Boost, the original experiment we designed to measure requests per second and latency did not pan out as expected. As soon as we entered production, our baseline measurement was skewed due to the imbalance in CPU utilization and only partially reproduced our lab results.</p><p>We added power to the experiment and found other meaningful insights. By analyzing the performance and power characteristics of simultaneous multithreading and Core Performance Boost, we concluded that simultaneous multithreading could be a power-efficient mechanism to attain additional requests per second. Drawbacks of simultaneous multithreading include long tail latency that is currently curtailed by enabling Core Performance Boost. While the higher frequency enabled by Core Performance Boost provides latency reduction and more requests per second, we are more mindful that the increase in power consumption is quite significant.</p><p>Do you want to help shape the Cloudflare network? This blog was a glimpse of the work we do at Cloudflare. <a href="https://www.cloudflare.com/careers/">Come join us</a> and help complete the feedback loop for our developers and hardware partners.</p> ]]></content:encoded>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[AMD]]></category>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[Partners]]></category>
            <category><![CDATA[Performance]]></category>
            <guid isPermaLink="false">6eb1jfSeTaXx6866LDX8Nl</guid>
            <dc:creator>Sung Park</dc:creator>
        </item>
        <item>
            <title><![CDATA[The EPYC journey continues to Milan in Cloudflare’s 11th generation Edge Server]]></title>
            <link>https://blog.cloudflare.com/the-epyc-journey-continues-to-milan-in-cloudflares-11th-generation-edge-server/</link>
            <pubDate>Tue, 31 Aug 2021 13:00:45 GMT</pubDate>
            <description><![CDATA[ At Cloudflare we aim to introduce a new server platform to our edge network every 12 to 18 months or so, to ensure that we keep up with the latest industry technologies and developments.  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>When I was interviewing to join Cloudflare in 2014 as a member of the SRE team, we had just introduced our <a href="/a-tour-inside-cloudflares-latest-generation-servers/">generation 4 server</a>, and I was excited about the prospects. Since then, Cloudflare, the industry and I have all changed dramatically. The best thing about working for a rapidly growing company like Cloudflare is that as the company grows, new roles open up to enable career development. And so, having left the SRE team last year, I joined the recently formed hardware engineering team, a team that simply didn’t exist in 2014.</p><p>We aim to introduce a new server platform to our edge network every 12 to 18 months or so, to ensure that we keep up with the latest industry technologies and developments. We announced the <a href="/a-tour-inside-cloudflares-g9-servers/">generation 9 server</a> in October 2018 and we announced the <a href="/a-tour-inside-cloudflares-g9-servers/">generation 10 server</a> in February 2020. We consider this length of cycle optimal: short enough to stay nimble and take advantage of the latest technologies, but long enough to offset the time taken by our hardware engineers to test and validate the entire platform. When we are <a href="https://www.cloudflare.com/network/">shipping servers to over 200 cities</a> around the world with a variety of regulatory standards, it’s essential to get things right the first time.</p><p>We continually work with our silicon vendors to receive product roadmaps and stay on top of the latest technologies. Since mid-2020, the hardware engineering team at Cloudflare has been working on our generation 11 server.</p><p>Requests per Watt is one of our defining characteristics when testing new hardware and we use it to identify how much more efficient a new hardware generation is than the previous generation. We continually strive to reduce our operational costs and <a href="/the-climate-and-cloudflare/">power consumption reduction</a> is one of the most important parts of this. It’s good for the planet and we can fit more servers into a rack, reducing our physical footprint.</p><p>The design of these Generation 11 x86 servers has been in parallel with our efforts to design next-generation edge servers using the <a href="/arms-race-ampere-altra-takes-on-aws-graviton2/">Ampere Altra</a> Arm architecture. You can read more about our tests in a blog post by my colleague Sung and we will document our work on Arm at the edge in a subsequent blog post.</p><p>We evaluated Intel’s latest generation of “Ice Lake” Xeon processors. Although Intel’s chips were able to compete with AMD in terms of raw performance, the power consumption was several hundred watts higher per server - that’s enormous. This meant that Intel’s Performance per Watt was unattractive.</p><p>We previously described how we had deployed AMD EPYC 7642’s processors in our generation 10 server. This has 48 cores and is based on AMD’s 2nd generation EPYC architecture, code named Rome. For our generation 11 server, we evaluated 48, 56 and 64 core samples based on AMD’s 3rd generation EPYC architecture, code named Milan. We were interested to find that comparing the two 48 core processors directly, we saw a performance boost of several percent in the <a href="https://www.amd.com/en/events/epyc">3rd generation EPYC</a> architecture. We therefore had high hopes for the 56 core and 64 core chips.</p><p>So, based on the samples we received from our vendors and our subsequent testing, hardware from AMD and Ampere made the shortlist for our generation 11 server. On this occasion, we decided that Intel did not meet our requirements. However, it’s healthy that Intel and AMD compete and innovate in the x86 space and we look forward to seeing how Intel’s next generation shapes up.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1ajXt7adRxT5V2FVBVw7IJ/56872f59f7e681093f6591fa6ef42840/IMG_4118.jpeg.jpeg" />
            
            </figure>
    <div>
      <h3>Testing and validation process</h3>
      <a href="#testing-and-validation-process">
        
      </a>
    </div>
    <p>Before we go on to talk about the hardware, I’d like to say a few words about the testing process we went through to test out generation 11 servers.</p><p>As we elected to proceed with AMD chips, we were able to use our generation 10 servers as our Engineering Validation Test platform, with the only changes being the new silicon and updated firmware. We were able to perform these upgrades ourselves in our hardware validation lab.</p><p>Cloudflare’s network is built with commodity hardware and we source the hardware from multiple vendors, known as ODMs (Original Design Manufacturer) who build the servers to our specifications.</p><p>When you are working with bleeding edge silicon and experimental firmware, not everything is plain sailing. We worked with one of our ODMs to eliminate an issue which was causing the Linux kernel to panic on boot. Once resolved, we used a variety of synthetic benchmarking tools to verify the performance including <a href="https://github.com/cloudflare/cf_benchmark">cf_benchmark</a>, as well as an internal tool which applies a synthetic load to our entire software stack.</p><p>Once we were satisfied, we ordered Design Validation Test samples, which were manufactured by our ODMs with the new silicon. We continued to test these and iron out the inevitable issues that arise when you are developing custom hardware. To ensure that performance matched our expectations, we used synthetic benchmarking to test the new silicon. We also began testing it in our production environment by gradually introducing customer traffic to them as confidence grew.</p><p>Once the issues were resolved, we ordered the Product Validation Test samples, which were again manufactured by our ODMs, taking into account the feedback obtained in the DVT phase. As these are intended to be production grade, we work with the broader Cloudflare teams to deploy these units like a mass production order.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5qZWpcqMs5De6LfHMCudjn/b7ca612abce657d53e51f2199ebbc7a9/20210722_113627.jpeg.jpeg" />
            
            </figure>
    <div>
      <h3>CPU</h3>
      <a href="#cpu">
        
      </a>
    </div>
    <p>Previously: AMD EPYC 7642 48-Core ProcessorNow: AMD EPYC 7713 64-Core Processor</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6aIqXZIeXOANPykcbW8tJJ/bc57b2023460a731e92e8c2e9b924afd/IMG_4203.jpeg.jpeg" />
            
            </figure>
<div><table><thead>
  <tr>
    <th></th>
    <th><a href="https://www.amd.com/en/products/cpu/amd-epyc-7642"><span>AMD EPYC 7642</span></a></th>
    <th><a href="https://www.amd.com/en/products/cpu/amd-epyc-7643"><span>AMD EPYC 7643</span></a></th>
    <th><a href="https://www.amd.com/en/products/cpu/amd-epyc-7663"><span>AMD EPYC 7663 </span></a></th>
    <th><a href="https://www.amd.com/en/products/cpu/amd-epyc-7713"><span>AMD EPYC 7713</span></a></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Status</span></td>
    <td><span>Incumbent</span></td>
    <td><span>Candidate</span></td>
    <td><span>Candidate</span></td>
    <td><span>Candidate</span></td>
  </tr>
  <tr>
    <td><span>Core Count</span></td>
    <td><span>48</span></td>
    <td><span>48</span></td>
    <td><span>56</span></td>
    <td><span>64</span></td>
  </tr>
  <tr>
    <td><span>Thread Count</span></td>
    <td><span>96</span></td>
    <td><span>96</span></td>
    <td><span>112</span></td>
    <td><span>128</span></td>
  </tr>
  <tr>
    <td><span>Base Clock</span></td>
    <td><span>2.3GHz</span></td>
    <td><span>2.3GHz</span></td>
    <td><span>2.0GHz</span></td>
    <td><span>2.0GHz</span></td>
  </tr>
  <tr>
    <td><span>Max Boost Clock</span></td>
    <td><span>3.3GHz</span></td>
    <td><span>3.6GHz</span></td>
    <td><span>3.5GHz</span></td>
    <td><span>3.675GHz</span></td>
  </tr>
  <tr>
    <td><span>Total L3 Cache</span></td>
    <td><span>256MB</span></td>
    <td><span>256MB</span></td>
    <td><span>256MB</span></td>
    <td><span>256MB</span></td>
  </tr>
  <tr>
    <td><span>Default TDP</span></td>
    <td><span>225W</span></td>
    <td><span>225W</span></td>
    <td><span>240W</span></td>
    <td><span>225W </span></td>
  </tr>
  <tr>
    <td><span>Configurable TDP</span></td>
    <td><span>240W</span></td>
    <td><span>240W</span></td>
    <td><span>240W</span></td>
    <td><span>240W</span></td>
  </tr>
</tbody></table></div><p>In the above chart, TDP refers to Thermal Design Power, a measure of the heat dissipated. All of the above processors have a configurable TDP - assuming the cooling solution is capable - giving more performance at the expense of increased power consumption. We tested all processors configured at their highest supported TDP.</p><p>The 64 core processors have 33% more cores than the 48 core processors so you might hypothesize that we would see a corresponding 33% increase in performance, although our benchmarks saw slightly more modest gains. This can be explained because the 64 core processors have lower base clock frequencies to fit within the same 225W power envelope.</p><p>In production testing, we found that the 64 core EPYC 7713 gave us around a 29% performance boost over the incumbent, whilst having similar power consumption and thermal properties.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3rYE9p57gOFlQ5xwL6D29t/aaf3624f32e1bf15ecf91db8c25dd96a/IMG_4196.jpeg.jpeg" />
            
            </figure>
    <div>
      <h2>Memory</h2>
      <a href="#memory">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2Z86awdPPL6Yt3G5GRZP41/c76caa9c5cbf76f718e5b3da99a989b2/_MG_4100.jpeg.jpeg" />
            
            </figure><p>Previously: 256GB DDR4-2933Now: 384GB DDR4-3200</p><p>Having made a decision about the processor, the next step was to determine the optimal amount of memory for our workload. We ran a series of experiments with our chosen EPYC 7713 processor and 256GB, 384GB and 512GB memory configurations. We started off by running synthetic benchmarks with tools such as <a href="https://www.cs.virginia.edu/stream/">STREAM</a> to ensure that none of the configurations performed unexpectedly poorly and to generate a baseline understanding of the performance.</p><p>After the synthetic benchmarks, we proceeded to test the various configurations with production workloads to empirically determine the optimal quantity. We use Prometheus and Grafana to gather and display a rich set of metrics from all of our servers so that we can monitor and spot trends, and we re-used the same infrastructure for our performance analysis.</p><p>As well as measuring available memory, previous experience has shown us that one of the best ways to ensure that we have enough memory is to observe request latency and disk IO performance. If there is insufficient memory, we expect to see request latency and disk IO volume and latency to increase. The reason for this is that our core HTTP server uses memory to cache web assets and if there is insufficient memory the assets will be ejected from memory prematurely and more assets will be fetched from disk instead of memory, degrading performance.</p><p>Like most things in life, it’s a balancing act. We want enough memory to take advantage of the fact that serving web assets directly from memory is much faster than even the best NVMe disks. We also want to future proof our platform to enable the new features such as the ones that we recently announced in <a href="/tag/security-week/">security week</a> and <a href="/tag/developer-week/">developer week</a>. However, we don’t want to spend unnecessarily on excess memory that will never be used. We found that the 512GB configuration did not provide a performance boost to justify the extra cost and settled on the 384GB configuration.</p><p>We also tested the performance impact of switching from DDR4-2933 to DDR4-3200 memory. We found that it provided a performance boost of several percent and the pricing has improved to the point where it is cost beneficial to make the change.</p>
    <div>
      <h2>Disk</h2>
      <a href="#disk">
        
      </a>
    </div>
    <p>Previously: 3x Samsung PM983 x 960GBNow: 2x Samsung PM9A3 x 1.92TB</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1bzxh2LTLqrPAHlIWynt9t/10c8fe856bf9e3a6feed7a8624451c66/20210722_113829.jpeg.jpeg" />
            
            </figure><p>We validated samples by studying the manufacturer’s data sheets and <a href="https://fio.readthedocs.io/en/latest/fio_doc.html">testing using fio</a> to ensure that the results being obtained in our test environment were in line with the published specifications. We also developed an automation framework to help compare different drive models using fio. The framework helps us to restore the drives close to factory settings, precondition the drives, perform the sequential and random tests in our environment, and analyze the data results to evaluate the bandwidth and latency results. Since our SSD samples were arriving in our test center at different months, having an automated framework helped in dealing with speedy evaluations by reducing our time spent testing and doing analysis.</p><p>For Gen 11 we decided to move to a 2x 2TB configuration from the original 3x 1TB configuration giving us an extra 1 TB of storage. This also meant we could use the higher performance of a 2TB drive and save around 6W of power since there is one less SSD.</p><p>After analyzing the performances of various 2TB drives, their latencies and endurances, we chose Samsung’s PM9A3 SSDs as our Gen11 drives. The results we obtained below were consistent with the manufacturer's claims.</p><p>Sequential performance:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5yOK70l1XM5JJij5aeUHTQ/5653a3e28925e06407b88193780acd77/pasted-image-0-5.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5nifB3rxB1gHWX6JBxBhfY/707192c1a778c46a15aff4b419d42c13/pasted-image-0--1--2.png" />
            
            </figure><p>Random Performance:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/A8p9s1IjM4UnmNmaMPx0T/358e01b8832c5e1ed7c1479a05c6cd5a/pasted-image-0--2-.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/61rhIo4w8sSIYbUiGfHRn9/d07ed49c5b957e3b1dde1db58aa1e484/pasted-image-0--3-.png" />
            
            </figure><p>Compared to our previous generation drives, we could see a 1.5x - 2x improvement in read and write bandwidths. The higher values for the PM9A3 can be attributed to the fact that these are PCIe 4.0 drives, have more intelligent SSD controllers and an upgraded NAND architecture.</p>
    <div>
      <h3>Network</h3>
      <a href="#network">
        
      </a>
    </div>
    <p>Previously: Mellanox ConnectX-4 dual-port 25GNow: Mellanox ConnectX-4 dual-port 25G</p><p>There is no change on the network front; the Mellanox ConnectX-4 is a solid performer which continues to meet our needs. We investigated higher speed Ethernet, but we do not currently see this as beneficial. Cloudflare’s network is built on cheap commodity hardware and the highly distributed nature of Cloudflare’s network means we don’t have discrete DDoS scrubbing centres. All points of presence operate as scrubbing centres. This means that we distribute the load across our entire network and do not need to employ higher speed and more expensive Ethernet devices.</p>
    <div>
      <h3>Open source firmware</h3>
      <a href="#open-source-firmware">
        
      </a>
    </div>
    <p>Transparency, security and integrity is absolutely critical to us at Cloudflare. Last year, we described how we had <a href="/anchoring-trust-a-hardware-secure-boot-story/">deployed Platform Secure Boot</a> to create trust that we were running the software that we thought we were.</p><p>Now, we are pleased to announce that we are deploying open source firmware to our servers using OpenBMC. With access to the source code, we have been able to configure BMC features such as the fan PID controller, having BIOS POST codes recorded and accessible, and managing networking ports and devices. Prior to OpenBMC, requesting these features from our vendors led to varying results and misunderstandings of the scope and capabilities of the BMC. After working with the BMC source code much more directly, we have the flexibility to work on features ourselves to our liking, or understand why the BMC is incapable of running our desired software.</p><p>Whilst our current BMC is an industry standard, we feel that OpenBMC better suits our needs and gives us advantages such as allowing us to deal with upstream security issues without a dependency on our vendors. Some opportunities with security include integration of desired authentication modules, usage of specific software packages, staying up to date with the latest Linux kernel, and controlling a variety of attack vectors. Because we have a kernel lockdown implemented, flashing tooling is difficult to use in our environment. With access to source code of the flashing tools, we have an understanding of what the tools need access to, and assess whether or not this meets our standard of security.</p>
    <div>
      <h3>Summary</h3>
      <a href="#summary">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/01wz0PNamn0NdOlkgxbgUs/104ce7600fe455376a0e39538c929882/IMG_4195.jpeg.jpeg" />
            
            </figure><p>The jump between our generation 9 and generation 10 servers was enormous. To summarise, we changed from a dual-socket Intel platform to a single socket AMD platform. We upgraded the SATA SSDs to NVMe storage devices, and physically the multi-node chassis changed to a 1U form factor.</p><p>At the start of the generation 11 project we weren’t sure if we would be making such radical changes again. However, after a thorough testing of the latest chips and a review of how well the generation 10 server has performed in production for over a year, our generation 11 server built upon the solid foundations of generation 10 and ended up as a refinement rather than total revamp. Despite this, and bearing in mind that performance varies by time of day and geography, we are pleased that generation 11 is capable of serving approximately 29% more requests than generation 10 without an increase in power consumption.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1hWA14j4FrNG6KYDaHVFI4/30172744bf9b0d94a08c8a8abdb34b3f/Screenshot-2021-06-22-at-15.27.27.png" />
            
            </figure><p>Thanks to Denny Mathew and Ryan Chow’s work on benchmarking and OpenBMC, respectively.</p><p>If you are interested in working with bleeding edge hardware, open source server firmware, solving interesting problems, helping to improve our performance, and are interested in helping us work on our generation 12 server platform (amongst many other things!), <a href="https://www.cloudflare.com/careers/jobs/?department=Infrastructure&amp;location=default">we’re hiring</a>.</p> ]]></content:encoded>
            <category><![CDATA[Cloudflare Network]]></category>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[AMD]]></category>
            <category><![CDATA[Hardware]]></category>
            <guid isPermaLink="false">1c9Tnv6ewSXOVymWrMDUzF</guid>
            <dc:creator>Chris Howells</dc:creator>
        </item>
        <item>
            <title><![CDATA[Branch predictor: How many "if"s are too many? Including x86 and M1 benchmarks!]]></title>
            <link>https://blog.cloudflare.com/branch-predictor/</link>
            <pubDate>Thu, 06 May 2021 13:00:00 GMT</pubDate>
            <description><![CDATA[ Is it ok to have if clauses that will basically never be run? Surely, there must be some performance cost to that... ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Some time ago I was looking at a hot section in our code and I saw this:</p>
            <pre><code>
	if (debug) {
    	  log("...");
    }
    </code></pre>
            <p>This got me thinking. This code is in a performance critical loop and it looks like a waste - we never run with the "debug" flag enabled<sup>[</sup><a href="#footnotes"><sup>1</sup></a><sup>].</sup> Is it ok to have <code>if</code> clauses that will basically never be run? Surely, there must be some performance cost to that...</p>
    <div>
      <h3>Just how bad is peppering the code with avoidable <code>if</code> statements?</h3>
      <a href="#just-how-bad-is-peppering-the-code-with-avoidable-if-statements">
        
      </a>
    </div>
    <p>Back in the days the general rule was: a fully predictable branch has close to zero CPU cost.</p><p>To what extent is this true? If one branch is fine, then how about ten? A hundred? A thousand? When does adding one more <code>if</code> statement become a bad idea?</p><p>At some point the negligible cost of simple branch instructions surely adds up to a significant amount. As another example, a colleague of mine found this snippet in our production code:</p>
            <pre><code>
const char *getCountry(int cc) {
		if(cc == 1) return "A1";
        if(cc == 2) return "A2";
        if(cc == 3) return "O1";
        if(cc == 4) return "AD";
        if(cc == 5) return "AE";
        if(cc == 6) return "AF";
        if(cc == 7) return "AG";
        if(cc == 8) return "AI";
        ...
        if(cc == 252) return "YT";
        if(cc == 253) return "ZA";
        if(cc == 254) return "ZM";
        if(cc == 255) return "ZW";
        if(cc == 256) return "XK";
        if(cc == 257) return "T1";
        return "UNKNOWN";
}
        </code></pre>
            <p>Obviously, this code could be improved<sup>[</sup><a href="#footnotes"><sup>2</sup></a><sup>]</sup>. But when I thought about it more: <i>should</i> it be improved? Is there an actual performance hit of a code that consists of a series of simple branches?</p>
    <div>
      <h3>Understanding the cost of jump</h3>
      <a href="#understanding-the-cost-of-jump">
        
      </a>
    </div>
    <p>We must start our journey with a bit of theory. We want to figure out if the CPU cost of a branch increases as we add more of them. As it turns out, assessing the cost of a branch is not trivial. On modern processors it takes between one and twenty CPU cycles. There are at least four categories of control flow instructions<sup>[</sup><a href="#footnotes"><sup>3</sup></a><sup>]</sup>: unconditional branch (jmp on x86), call/return, conditional branch (e.g. je on x86) taken and conditional branch not taken. The taken branches are especially problematic: without special care they are inherently costly - we'll explain this in the following section. To bring down the cost, modern CPU's try to predict the future and figure out the branch <b>target</b> before the branch is actually fully executed! This is done in a special part of the processor called the branch predictor unit (BPU).</p><p>The branch predictor attempts to figure out a destination of a branching instruction very early and with very little context. This magic happens <b>before</b> the "decoder" pipeline stage and the predictor has very limited data available. It only has some past history and the address of the current instruction. If you think about it - this is super powerful. Given only current instruction pointer it can assess, with very high confidence, where the target of the jump will be.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1K3IOo5qkOOP0hhRtwu10U/e9997acf855e96044f2684e1adae87b0/pasted-image-0-1.png" />
            
            </figure><p>Source: <a href="https://en.wikipedia.org/wiki/Branch_predictor">https://en.wikipedia.org/wiki/Branch_predictor</a></p><p>The BPU maintains a couple of data structures, but today we'll focus on Branch Target Buffer (BTB). It's a place where the BPU remembers the target instruction pointer of previously taken branches. The whole mechanism is much more complex, take a look a the <a href="http://www.ece.uah.edu/~milenka/docs/VladimirUzelac.thesis.pdf">Vladimir Uzelac's Master thesis</a> for details about branch prediction on CPU's from 2008 era:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1FO1GCWdkQYR5I90qGopuH/9f51e10ca53eafd001f2238896103327/pasted-image-0--1-.png" />
            
            </figure><p>For the scope of this article we'll simplify and focus on the BTB only. We'll try to show how large it is and how it behaves under different conditions.</p>
    <div>
      <h3>Why is branch prediction needed?</h3>
      <a href="#why-is-branch-prediction-needed">
        
      </a>
    </div>
    <p>But first, why is branch prediction used at all? In order to get the best performance, the CPU pipeline must feed a constant flow of instructions. Consider what happens to the multi-stage CPU pipeline on a branch instruction. To illustrate let's consider the following ARM program:</p>
            <pre><code>
	BR label_a;
    X1
    ...
label_a:
 	Y1
    </code></pre>
            <p>Assuming a simplistic CPU model, the operations would flow through the pipeline like this:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6LYtd8rNXEQA2X2pOPwmvd/e9bbdd4d54a72dc78730684252d01a84/3P6PIWN6gPAdYzP8oDgrsaOMKgUmG51zIiFhbm071cZKM276S7vRb5atpTwlKrM1lFHRYsobw8P4e-Z9t1Vb9TGeutpBe2CkMrNGruWO8yb5Qz0vZ6Qn6RbOi5Tp.png" />
            
            </figure><p>In the first cycle the BR instruction is fetched. This is an unconditional branch instruction changing the execution flow of the CPU. At this point it's not yet decoded, but the CPU would like to fetch another instruction already! Without a branch predictor in cycle 2 the fetch unit either has to wait or simply continues to the next instruction in memory, hoping it will be the right one.</p><p>In our example, instruction X1 is fetched even though this isn't the correct instruction to run. In cycle 4, when the branch instruction finishes the execute stage, the CPU will be able to understand the mistake, and roll back the speculated instructions before they have any effect. At this point the fetch unit is updated to correctly get the right instruction - Y1 in our case.</p><p>This situation of losing a number of cycles due to fetching code from an incorrect place is called a "frontend bubble". Our theoretical CPU has a two-cycle frontend bubble when a branch target wasn’t predicted right.</p><p>In this example we see that, although the CPU does the right thing in the end, without good branch prediction it wasted effort on bad instructions. In the past, various techniques have been used to reduce this problem, such as static branch prediction and branch delay slots. But the dominant CPU designs today rely <a href="https://danluu.com/branch-prediction/#one-bit">on <i>dynamic branch prediction</i></a>. This technique is able to mostly avoid the frontend bubble problem, by predicting the correct address of the next instruction even for branches that aren’t fully decoded and executed yet.</p>
    <div>
      <h3>Playing with the BTB</h3>
      <a href="#playing-with-the-btb">
        
      </a>
    </div>
    <p>Today we're focusing on the BTB - a data structure managed by the branch predictor responsible for figuring out a target of a branch. It's important to note that the BTB is distinct from and independent of the system assessing if the branch was taken or not taken. Remember, we want to figure out if a cost of a branch increases as we run more of them.</p><p>Preparing an experiment to stress only the BTB is relatively simple (<a href="https://xania.org/201602/bpu-part-three">based on Matt Godbolt's work</a>). It turns out a sequence of unconditional <code>jmps</code> is totally sufficient. Consider this x86 code:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/259y50RQfLqaFcsT4tljGb/5010158442d4e2afb6ebb3c105ee4e5b/pasted-image-0--2-.png" />
            
            </figure><p>This code stresses the BTB to an extreme - it just consists of a chain of <code>jmp +2</code> statements (i.e. literally jumping to the next instruction). In order to avoid wasting cycles on frontend pipeline bubbles, each taken jump needs a BTB hit. This branch prediction must happen very early in the CPU pipeline, before instruction decode is finished. This same mechanism is needed for any taken branch, whether it's unconditional, conditional or a function call.</p><p>The code above was run inside a test harness that measures how many CPU cycles elapse for each instruction. For example, in this run we're measuring times of dense - every two bytes - 1024 jmp instructions one after another:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3QofFzm1kmqFLuRrFPoyjQ/857bfbfe366720bd480653388f97eac8/pasted-image-0--3-.png" />
            
            </figure><p>We’ll look at the results of experiments like this for a few different CPUs. But in this instance, it was run on a machine with an AMD EPYC 7642. Here, the cold run took 10.5 cycles per jmp, and then all subsequent runs took ~3.5 cycles per jmp. The code is prepared in such a way to make sure it's the BTB that is slowing down the first run. Take a look at the full code, there is quite some magic to warm up the L1 cache and iTLB without priming the BTB.</p><p><b>Top tip 1. On this CPU a branch instruction that is taken but not predicted, costs ~7 cycles more than one that is taken and predicted.</b> Even if the branch was unconditional.</p>
    <div>
      <h3>Density matters</h3>
      <a href="#density-matters">
        
      </a>
    </div>
    <p>To get a full picture we also need to think about the density of jmp instructions in the code. The code above did eight jmps per 16-byte code block. This is a lot. For example, the code below contains one jmp instruction in each block of 16 bytes. Notice that the <code>nop</code> opcodes are jumped over. The block size doesn't change the number of executed instructions, only the code density:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2uenA2zFAkPWQZldVX7gba/8823f9ec4052618dc06c21d0621a6581/pasted-image-0--4-.png" />
            
            </figure><p>Varying the jmp block size might be important. It allows us to control the placement of the jmp opcodes. Remember the BTB is indexed by instruction pointer address. Its value and its alignment might influence the placement in the BTB and help us reveal the BTB layout. Increasing the alignment will cause more nop padding to be added. The sequence of a single measured instruction - jmp in this case - and zero or more nops, I will call "block", and its size "block size". Notice that the larger the block size, the larger the working code size for the CPU. At larger values we might see some performance drop due to exhausting L1 cache space.</p>
    <div>
      <h3>The experiment</h3>
      <a href="#the-experiment">
        
      </a>
    </div>
    <p>Our experiment is crafted to show the performance drop depending on the number of branches, across different working code sizes. Hopefully, we will be able to prove the performance is mostly dependent on the number of blocks - and therefore the BTB size, and not the working code size.</p><p>See the <a href="https://github.com/cloudflare/cloudflare-blog/tree/master/2021-05-branch-prediction">code on GitHub</a>. If you want to see the generated machine code, though, you need to run a special command. It's created procedurally by the code, customized by passed parameters. Here's an example <code>gdb</code> incantation:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7aAKMXz8aruwblN67UvZd7/1eb2aea7cc6e2e3a9c0f6823f60b8f08/pasted-image-0--5-.png" />
            
            </figure><p>Let's bring this experiment forward, what if we took the best times of each run - with a fully primed BTB - for varying values of jmp block sizes and number of blocks - working set size? Here you go:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4ZNeolS38Q90vdHPvehvVa/64e0c16d163d74c05cfbaee6f8d9e15c/pasted-image-0--6-.png" />
            
            </figure><p>This is an astonishing chart. First, it's obvious something happens at the 4096 jmp mark[<a href="#footnotes">4</a>] regardless of how large the jmp block sizes - how many nop's we skip over. Reading it aloud:</p><ul><li><p>On the far left, we see that if the amount of code is small enough - less than 2048 bytes (256 times a block of 8 bytes) - it's possible to hit some kind of uop/L1 cache and get ~1.5 cycles per fully predicted branch. This is amazing.</p></li><li><p>Otherwise, if you keep your hot loop to 4096 branches then, no matter how dense your code is you are likely to see ~3.4 cycles per fully predicted branch</p></li><li><p>Above 4096 branches the branch predictor gives up and the cost of each branch shoots to ~10.5 cycles per jmp. This is consistent with what we saw above - unpredicted branch on flushed BTB took ~10.5 cycles.</p></li></ul><p>Great, so what does it mean? Well, you should avoid branch instructions if you want to avoid branch misses because you have at most 4096 of fast BTB slots. This is not a very pragmatic advice though - it's not like we deliberately put many unconditional <code>jmp</code>s in real code!</p><p>There are a couple of takeaways for the discussed CPU. I repeated the experiment with an always-taken conditional branch sequence and the resulting chart looks almost identical. The only difference being the predicted taken conditional-je instruction being 2 cycles slower than unconditional jmp.</p><p>An entry to BTB is added wherever a branch is "taken" - that is, the jump actually happens. An unconditional "jmp" or always taken conditional branch, will cost a BTB slot. To get best performance make sure to not have more than 4096 taken branches in the hot loop. The good news is that branches never-taken don't take space in the BTB. We can illustrate this with another experiment:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5gd2JKAwYMpgk5obd4E0Hz/29876ce9f45dc01edbb8e3966bcb9903/pasted-image-0--7-.png" />
            
            </figure><p>This boring code is going over not-taken <code>jne</code> followed by two nops (block size=4). Aimed with this test (jne never-taken), the previous one (jmp always-taken) and a conditional branch <code>je</code> always-taken, we can draw this chart:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1F2STBl6iw6OpkwqmIdlR9/1de627e490ddd75816bb3899f99f6ed7/pasted-image-0--8-.png" />
            
            </figure><p>First, without any surprise we can see the conditional 'je always-taken' is getting slightly more costly than the simple unconditional <code>jmp</code>, but only after the 4096 branches mark. This makes sense, the conditional branch is resolved later in the pipeline so the frontend bubble is longer. Then take a look at the blue line hovering near zero. This is the "jne never-taken" line flat at 0.3 clocks / block, no matter how many blocks we run in sequence. The takeaway is clear - you can have as many never-taken branches as you want, without incurring any cost. There isn't any spike at 4096 mark, meaning BTB is not used in this case. It seems the conditional jump not seen before is guessed to be not-taken.</p><p><b>Top tip 2: conditional branches never-taken are basically free</b> - at least on this CPU.</p><p>So far we established that branches always-taken occupy BTB, branches never taken do not. How about other control flow instructions, like the <code>call</code>?</p><p>I haven't been able to find this in the literature, but it seems call/ret also need the BTB entry for best performance. I was able to illustrate this on our AMD EPYC. Let's take a look at this test:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/fHArGj5TWvRM9AEM84NLJ/1951dfe42651b923551d90dddc63964f/pasted-image-0--9-.png" />
            
            </figure><p>This time we'll issue a number of <code>callq</code> instructions followed by <code>ret</code> - both of which should be fully predicted. The experiment is crafted so that each callq calls a unique function, to allow for retq prediction - each one returns to exactly one caller.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/677H5BdxwzZ9B6hbebRFnB/a1ac1602d5efab51152a6219fde87579/pasted-image-0--10-.png" />
            
            </figure><p>This chart confirms the theory: no matter the code density - with the exception of 64-byte block size being notably slower -  the cost of predicted call/ret starts to deteriorate after the 2048 mark. At this point the BTB is filled with call and ret predictions and can't handle any more data. This leads to an important conclusion:</p><p><b>Top tip 3. In the hot code you want to have less than 2K function calls</b> - on this CPU.</p><p>In our test CPU a sequence of fully predicted call/ret takes about 7 cycles, which is about the same as two unconditional predicted <code>jmp</code> opcodes. It's consistent with our results above.</p><p>So far we thoroughly checked AMD EPYC 7642. We started with this CPU because the branch predictor is relatively simple and the charts were easy to read. It turns out more recent CPUs are less clear.</p>
    <div>
      <h3>AMD EPYC 7713</h3>
      <a href="#amd-epyc-7713">
        
      </a>
    </div>
    <p>Newer AMD is more complex than the previous generations. Let's run the two most important experiments. First, the <code>jmp</code> one:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/12g3Zg18eWyHIwyUuf63gj/0cb89d1fc7a8fedbed929aa455e11dbf/pasted-image-0--11-.png" />
            
            </figure><p>For the always-taken branches case we can see a very good, sub 1 cycle, timings when the number of branches doesn't exceed 1024 and the code isn't too dense.</p><p><b>Top tip 4. On this CPU it's possible to get &lt;1 cycle per predicted jmp when the hot loop fits in ~32KiB.</b></p><p>Then there is some noise starting after the 4096 jmps mark. This is followed by a complete drop of speed at about 6000 branches. This is in line with the theory that BTB is 4096 entries long. We can speculate that some other prediction mechanism is successfully kicking in beyond that, and keeps up the performance up the ~6k mark.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4X5KfDDT36u9u2MGb7iu7t/90c4fbf3d04cd386ed6eecae645f25f8/pasted-image-0--12-.png" />
            
            </figure><p>The call/ret chart shows a similar tale, the timings start breaking after 2048 mark, and completely fail to be predicted beyond ~3000.</p>
    <div>
      <h3>Xeon Gold 6262</h3>
      <a href="#xeon-gold-6262">
        
      </a>
    </div>
    <p>The Intel Xeon looks different from the AMD:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7hIriKLopeE26yIor9qGG/9ab0d56fd18cfd4a782b7270845bc66f/pasted-image-0--13-.png" />
            
            </figure><p>Our test shows the predicted taken branch costs 2 cycles. Intel has documented a clock penalty for very dense branching code - this explains the 4-byte block size line hovering at ~3 cycles. The branch cost breaks at the 4096 jmp mark, confirming the theory that the Intel BTB can hold 4096 entries. The 64-byte block size chart looks confusing, but really isn't. The branch cost stays at flat 2 cycles up till the 512 jmp count. Then it increases. This is caused by the internal layout of the BTB which is said to be 8-way associative. It seems with the 64-byte block size we can utilize at most half of the 4096 BTB slots.</p><p><b>Top tip 5. On Intel avoid placing your jmp/call/ret instructions at regular 64-byte intervals.</b></p><p>Then the call/ret chart:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1XU4ofCRG3wfjLZlwsEhBv/2df1b19f6623a26be745caf35c28ee33/pasted-image-0--14-.png" />
            
            </figure><p>Similarly, we can see the branch predictions failing after the 2048 jmp mark - in this experiment one block uses two flow control instructions: call and ret. This again confirms the BTB size of 4K entries. The 64-byte block size is generally slower due to the nop padding but also breaks faster due to the instructions alignment issue. Notice, we haven't seen this effect on AMD.</p>
    <div>
      <h3>Apple Silicon M1</h3>
      <a href="#apple-silicon-m1">
        
      </a>
    </div>
    <p>So far we saw examples of AMD and Intel server grade CPUs. How does an Apple Silicon M1 fit in this picture?</p><p>We expect it to be very different - it's designed for mobile and it's using ARM64 architecture. Let's see our two experiments:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/bJ9lzYsIARltRCkOEJVZZ/6b1b5edcdf00e3c0a3c353fff72c8232/pasted-image-0--15-.png" />
            
            </figure><p>The predicted <code>jmp</code> test shows an interesting story. First, when the code fits 4096 bytes (1024*4 or 512*8, etc) you can expect a predicted <code>jmp</code> to cost 1 clock cycle. This is an excellent score.</p><p>Beyond that, generally, you can expect a cost of 3 clock cycles per predicted jmp. This is also very good. This starts to deteriorate when the working code grows beyond ~200KiB. This is visible with block size 64 breaking at 3072 mark 3072*64=196K, and for block 32 at 6144: 6144*32=196K. At this point the prediction seems to stop working. The documentation indicates that the M1 CPU has 192 KB L1 of instruction cache - our experiment matches that.</p><p>Let's compare the "predicted jmp" with the "unpredicted jmp" chart. Take this chart with a grain of salt, because flushing the branch predictor is notoriously difficult.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2VCtlgVdJkSB3MFuYbR5MQ/31b80611cab5b7a5ec14514dd375e7ea/pasted-image-0--16-.png" />
            
            </figure><p>However, even if we don't trust the flush-bpu code (<a href="https://xania.org/201602/bpu-part-three">adapted from Matt Godbolt</a>), this chart reveals two things. First, the "unpredicted" branch cost seems to be correlated with the branch distance. The longer the branch the costlier it is. We haven't seen such behaviour on x86 CPUs.</p><p>Then there is the cost itself. We saw a predicted sequence of branches cost, and what a supposedly-unpredicted jmp costs. In the first chart we saw that beyond ~192KiB working code, the branch predictor seems to become ineffective. The supposedly-flushed BPU seems to show the same cost. For example, the cost of a 64-byte block size jmp with a small working set size is 3 cycles. A miss is ~8 cycles. For a large working set size both times are ~8 cycles. It seems that the BTB is linked to the L1 cache state. <a href="https://www.realworldtech.com/forum/?threadid=159985&amp;curpostid=160001">Paul A. Clayton suggested</a> a possibility of such a design back in 2016.</p><p><b>Top tip 6. on M1 the predicted-taken branch generally takes 3 cycles and unpredicted but taken has varying cost, depending on jmp length. BTB is likely linked with L1 cache.</b></p><p>The call/ret chart is funny:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/54s7q6CJamAHCjpzDHFm6V/d1db62f4d8ec351ce539709cb6a512cd/pasted-image-0--17-.png" />
            
            </figure><p>Like in the chart before, we can see a big benefit if hot code fits within 4096 bytes (512*4 or 256*8). Otherwise, you can count on 4-6 cycles per call/ret sequence (or, bl/ret as it's known in ARM). The chart shows funny alignment issues. It's unclear what they are caused by. Beware, comparing the numbers in this chart with x86 is unfair, since ARM <code>call</code> operation differs substantially from the x86 variant.</p><p>M1 seems pretty fast, with predicted branches usually at 3 clock cycles. Even unpredicted branches never cost more than 8 ticks in our benchmark. Call+ret sequence for dense code should fit under 5 cycles.</p>
    <div>
      <h3>Summary</h3>
      <a href="#summary">
        
      </a>
    </div>
    <p>We started our journey from a piece of trivial code, and asked a basic question: how costly is  adding a never-taken <code>if</code> branch in the hot portion of code?</p><p>Then we quickly dived in very low level CPU features. By the end of this article, hopefully, an astute reader might get better intuition how a modern branch predictors works.</p><p>On x86 the hot code needs to split the BTB budget between function calls and taken branches. The BTB has only a size of 4096 entries. There are strong benefits in keeping the hot code under 16KiB.</p><p>On the other hand on M1 the BTB seems to be limited by L1 instruction cache. If you're writing super hot code, ideally it should fit 4KiB.</p><p>Finally, can you add this one more <code>if</code> statement? If it's never-taken, it's probably ok. I found no evidence that such branches incur any extra cost. But do avoid always-taken branches and function calls.</p><p><b>Sources</b></p><p>I'm not the first person to investigate how BTB works. I based my experiments on:</p><ul><li><p><a href="http://www.ece.uah.edu/~milenka/docs/VladimirUzelac.thesis.pdf">Vladimir Uzelac thesis</a></p></li><li><p><a href="https://xania.org/201602/bpu-part-three">Matt Godbolt work</a>. The series has 5 articles.</p></li><li><p><a href="https://www.realworldtech.com/forum/?threadid=159985&amp;curpostid=159985">Travis Downs BTB questions</a> on Real World Tech</p></li><li><p><a href="https://stackoverflow.com/questions/38811901/slow-jmp-instruction">various</a> <a href="https://stackoverflow.com/questions/51822731/why-did-intel-change-the-static-branch-prediction-mechanism-over-these-years">stackoverflow</a> <a href="https://stackoverflow.com/questions/38512886/btb-size-for-haswell-sandy-bridge-ivy-bridge-and-skylake">discussions</a>. Especially <a href="https://stackoverflow.com/questions/31280817/what-branch-misprediction-does-the-branch-target-buffer-detect">this one</a> and <a href="https://stackoverflow.com/questions/31642902/intel-cpus-instruction-queue-provides-static-branch-prediction">this</a></p></li><li><p><a href="https://www.agner.org/optimize/microarchitecture.pdf">Agner Fog</a> microarchitecture guide has a good section on branch predictions.</p></li></ul>
    <div>
      <h3>Acknowledgements</h3>
      <a href="#acknowledgements">
        
      </a>
    </div>
    <p>Thanks to <a href="/author/david-wragg/">David Wragg</a> and <a href="https://twitter.com/danluu">Dan Luu</a> for technical expertise and proofreading help.</p>
    <div>
      <h3>PS</h3>
      <a href="#ps">
        
      </a>
    </div>
    <p>Oh, oh. But this is not the whole story! Similar research was the base to the <a href="https://spectreattack.com/spectre.pdf">Spectre v2</a> attack. The attack was exploiting the little known fact that the BPU state was not cleared between context switches. With the correct technique it was possible to train the BPU - in the case of Spectre it was iBTB - and force a privileged piece of code to be speculatively executed. This, combined with a cache side-channel data leak, allowed an attacker to steal secrets from the privileged kernel. Powerful stuff.</p><p>A proposed solution was to avoid using shared BTB. This can be done in two ways: make the indirect jumps to always fail to predict, or fix the CPU to avoid sharing BTB state across isolation domains. This is a long story, maybe for another time...</p><hr /><p><a>Footnotes</a></p><p>1. One historical solution to this specific 'if debug' problem is called "runtime nop'ing". The idea is to modify the code in runtime and patch the never-taken branch instruction with a <code>nop</code>. For example, see the "ISENABLED" discussion on <a href="https://bugzilla.mozilla.org/showbug.cgi?id=370906.">https://bugzilla.mozilla.org/showbug.cgi?id=370906.</a></p><p>2. Fun fact: modern compilers are pretty smart. New gcc (&gt;=11) and older clang (&gt;=3.7) are able to actually optimize it quite a lot. <a href="https://godbolt.org/z/KWYEW3d9s">See for yourself</a>. But, let's not get distracted by that. This article is about low level machine code branch instructions!</p><p>3. This is a simplification. There are of course more control flow instructions, like: software interrupts, syscalls, VMENTER/VMEXIT.</p><p>4. Ok, I'm slightly overinterpreting the chart. Maybe the 4096 jmp mark is due to the 4096 uop cache or some instruction decoder artifact? To prove this spike is indeed BTB related I looked at Intel BPUCLEARS.EARLY and BACLEAR.CLEAR performance counters. Its value is small for block count under 4096 and large for block count greater than 5378. This is strong evidence that the performance drop is indeed caused by the BPU and likely BTB.</p> ]]></content:encoded>
            <category><![CDATA[Deep Dive]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[AMD]]></category>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">2pvX64jHrEfNLMSmJO1Iv4</guid>
            <dc:creator>Marek Majkowski</dc:creator>
        </item>
        <item>
            <title><![CDATA[Why Cloudflare Chose AMD EPYC for Gen X Servers]]></title>
            <link>https://blog.cloudflare.com/technical-details-of-why-cloudflare-chose-amd-epyc-for-gen-x-servers/</link>
            <pubDate>Sun, 01 Mar 2020 13:00:00 GMT</pubDate>
            <description><![CDATA[ Looking back at this week's posts on the design, specifications, and performance of Cloudflare’s Gen X servers using AMD CPUs. Every server can run every service. This architectural decision has helped us achieve higher efficiency across the Cloudflare network.  ]]></description>
            <content:encoded><![CDATA[ <p>From the very beginning Cloudflare used Intel CPU-based servers (and, also, Intel components for things like NICs and SSDs). But we're always interested in optimizing the cost of running our service so that we can provide products at a low cost and high gross margin.</p><p>We're also mindful of events like the <a href="/meltdown-spectre-non-technical/">Spectre and Meltdown</a> vulnerabilities and have been working with outside parties on research into mitigation and exploitation which we hope to publish later this year.</p><p>We looked very seriously at <a href="/arm-takes-wing/">ARM-based CPUs</a> and continue to keep our software up to date for the ARM architecture so that we can use ARM-based CPUs when the requests per watt is interesting to us.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1FIEEXHXXE0TW20DbFc1qG/bd65d80a3f61062de14027374907daf5/gen-x-color-Friday--twitter_2x.png" />
            
            </figure><p>In the meantime, we've deployed AMD's EPYC processors as part of Gen X server platform and for the first time are not using any Intel components at all. This week, we announced details of this tenth generation of servers. Below is a recap of why we're excited about the design, specifications, and performance of our newest hardware.</p>
    <div>
      <h2><a href="/cloudflares-gen-x-servers-for-an-accelerated-future/">Servers for an Accelerated Future</a></h2>
      <a href="#">
        
      </a>
    </div>
    <p>Every server can run every service. This architectural decision has helped us achieve higher efficiency across the Cloudflare network. It has also given us more flexibility to build new software or adopt the newest available hardware.</p><p>Notably, Intel is not inside. We are not using their hardware for any major server components such as the CPU, board, memory, storage, network interface card (or any type of accelerator).</p><p>This time, AMD is inside.</p><p>Compared with our prior server (<a href="/a-tour-inside-cloudflares-g9-servers/">Gen 9</a>), our Gen X server processes as much as 36% more requests while costing substantially less. Additionally, it enables a ~50% decrease in L3 cache miss rate and up to 50% decrease in NGINX p99 latency, powered by a CPU rated at 25% lower TDP (thermal design power) per core.</p>
    <div>
      <h2><a href="/an-epyc-trip-to-rome-amd-is-cloudflares-10th-generation-edge-server-cpu/">Gen X CPU benchmarks</a></h2>
      <a href="#">
        
      </a>
    </div>
    <p>To identify the most efficient CPU for our software stack, we ran several benchmarks for key workloads such as cryptography, compression, regular expressions, and LuaJIT. Then, we simulated typical requests we see, before testing servers in live production to measure requests per watt.    </p><p>Based on our findings, we selected the single socket 48-core AMD 2nd Gen EPYC 7642.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/40QrPSva2FXZVgsZTln51q/2c15c60f27009a1ad459ae390afc49c6/pasted-image-0.png" />
            
            </figure>
    <div>
      <h2><a href="/impact-of-cache-locality/">Impact of Cache Locality</a></h2>
      <a href="#">
        
      </a>
    </div>
    <p>The single AMD EPYC 7642 performed very well during our lab testing, beating our <a href="/a-tour-inside-cloudflares-g9-servers/">Gen 9</a> server with dual Intel Xeon Platinum 6162 with the same total number of cores. Key factors we noticed were its large L3 cache, which led to a low L3 cache miss rate, as well as a higher sustained operating frequency.</p>
    <div>
      <h2><a href="/gen-x-performance-tuning/">Gen X Performance Tuning</a></h2>
      <a href="#">
        
      </a>
    </div>
    <p>Partnering with AMD, we tuned the 2nd Gen EPYC 7642 processor to achieve additional 6% performance. We achieved this by using power determinism and configuring the CPU's Thermal Design Power (TDP).</p>
    <div>
      <h2><a href="/securing-memory-at-epyc-scale/">Securing Memory at EPYC Scale</a></h2>
      <a href="#">
        
      </a>
    </div>
    <p>Finally, we described how we use Secure Memory Encryption (SME), an interesting security feature within the System on a Chip architecture of the AMD EPYC line. We were impressed by how we could achieve RAM encryption without significant decrease in performance. This reduces the worry that any data could be exfiltrated from a stolen server.</p><p>We enjoy designing hardware that improves the security, performance and reliability of our global network, trusted by over 26 million Internet properties.</p><p>Want to help us evaluate new hardware? <a href="https://www.cloudflare.com/careers/">Join us</a>!</p> ]]></content:encoded>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[AMD]]></category>
            <category><![CDATA[Gen X]]></category>
            <category><![CDATA[Cache]]></category>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Security]]></category>
            <guid isPermaLink="false">6UGZUyfF1u3jKKAHkxgDNq</guid>
            <dc:creator>Nitin Rao</dc:creator>
        </item>
        <item>
            <title><![CDATA[Securing Memory at EPYC Scale]]></title>
            <link>https://blog.cloudflare.com/securing-memory-at-epyc-scale/</link>
            <pubDate>Fri, 28 Feb 2020 14:00:00 GMT</pubDate>
            <description><![CDATA[ At Cloudflare, we encrypt data both in transit (on the network) and at rest (on the disk). Both practices address some of the most common vectors used to exfiltrate information and these measures serve to protect sensitive data from attackers but, what about data currently in use? ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Security is a serious business, one that we do not take lightly at Cloudflare. We have <a href="https://www.cloudflare.com/compliance/">invested a lot of effort</a> into ensuring that our services, both external and internal, are protected by meeting or exceeding industry best practices. Encryption is a huge part of our strategy as it is embedded in nearly every process we have. At Cloudflare, we encrypt data both in <a href="/rfc-8446-aka-tls-1-3/">transit</a> (on the network) and at rest (on the disk). Both practices address some of the most common vectors used to exfiltrate information and these measures serve to <a href="https://www.cloudflare.com/learning/security/what-is-information-security/">protect sensitive data</a> from attackers but, what about data currently in use?</p><p>Can encryption or any technology eliminate all threats? No, but as Infrastructure Security, it’s our job to consider worst-case scenarios. For example, what if someone were to steal a server from one of our <a href="https://www.cloudflare.com/network/">data centers</a>? How can we leverage the most reliable, cutting edge, innovative technology to secure all data on that host if it were in the wrong hands? Would it be protected? And, in particular, what about the server’s RAM?</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/F40SGb897EzCafJNfUMxo/9346da5cc95f377fd15c8ebe6d3a7077/mission-impossible-1.png" />
            
            </figure><p>Data in random access memory (RAM) is usually stored in the clear. This can leave data vulnerable to software or hardware probing by an attacker on the system. Extracting data from memory isn’t an easy task but, with the rise of <a href="https://www.snia.org/sites/default/files/SSSI/NVDIMM%20-%20Changes%20are%20Here%20So%20What's%20Next%20-%20final.pdf">persistent memory technologies</a>, additional attack vectors are possible:</p><ul><li><p>Dynamic random-access memory (<a href="https://user.eng.umd.edu/~blj/talks/DRAM-Tutorial-isca2002.pdf">DRAM</a>) interface snooping</p></li><li><p>Installation of hardware devices that access host memory</p></li><li><p><a href="https://en.wikipedia.org/wiki/Cold_boot_attack">Freezing and stealing</a> dual in-line memory module (<a href="https://en.wikipedia.org/wiki/DIMM">DIMMs</a>)</p></li><li><p>Stealing non-volatile dual in-line memory module (<a href="https://en.wikipedia.org/wiki/NVDIMM">NVDIMMs</a>)</p></li></ul><p>So, what about enclaves? Hardware manufacturers have introduced <a href="https://en.wikipedia.org/wiki/Trusted_execution_environment">Trusted Execution Environments</a> (also known as enclaves) to help create security boundaries by isolating software execution at runtime so that sensitive data can be processed in a trusted environment, such as secure area inside an existing processor or <a href="https://en.wikipedia.org/wiki/Trusted_Platform_Module">Trusted Platform Module</a>.</p><p>While this allows developers to shield applications in untrusted environments, it doesn’t effectively address all of the physical system attacks mentioned previously. Enclaves were also meant to run small pieces of code. You <i>could</i> run an <a href="https://www.usenix.org/system/files/conference/osdi14/osdi14-paper-baumann.pdf">entire OS in an enclave</a>, but there are <a href="https://blog.quarkslab.com/overview-of-intel-sgx-part-1-sgx-internals.html">limitations</a> and performance issues in doing so.</p><p>This isn’t meant to bash enclave usage; we just wanted a better solution for encrypting all memory at scale. We expected performance to be compromised, and conducted tests to see just how much.</p>
    <div>
      <h2>Time to get EPYC</h2>
      <a href="#time-to-get-epyc">
        
      </a>
    </div>
    <p>Since we are using <a href="/cloudflares-gen-x-servers-for-an-accelerated-future/">AMD for our tenth generation "Gen X servers"</a>, we found an interesting security feature within the System on a Chip architecture of the AMD EPYC line. Secure Memory Encryption (SME) is an <a href="https://en.wikichip.org/wiki/x86">x86</a> instruction set <a href="https://en.wikichip.org/wiki/x86/extension">extension</a> introduced by AMD and available in the <a href="https://developer.amd.com/sev/">EPYC processor line.</a> SME provides the ability to mark individual pages of memory as encrypted using standard x86 page tables. A page that is marked encrypted will be automatically decrypted when read from DRAM and encrypted when written to DRAM. SME can therefore be used to protect the contents of DRAM from physical attacks on the system.</p><p>Sounds complicated, right? Here’s the secret: It isn’t ?</p>
    <div>
      <h2>Components</h2>
      <a href="#components">
        
      </a>
    </div>
    <p>SME is comprised of two components:</p><ul><li><p><b>AES-128 encryption</b> <b>engine</b>: Embedded in the memory controller. It is responsible for encrypting and decrypting data in main memory when an appropriate key is provided via the Secure Processor.</p></li><li><p><b>AMD Secure Processor (AMD-SP)</b>: An on-die 32-bit <a href="https://developer.arm.com/ip-products/processors/cortex-a/cortex-a5">ARM Cortex A5 CPU</a> that provides cryptographic functionality for secure key generation and key management. Think of this like a mini hardware security module that uses a hardware random number generator to generate the 128-bit key(s) used by the encryption engine.</p></li></ul>
    <div>
      <h2>How It Works</h2>
      <a href="#how-it-works">
        
      </a>
    </div>
    <p>We had two options available to us when it came to enabling SME. The first option, regular SME, requires enabling a model specific register <code>MSR 0xC001_0010[SMEE]</code>. This enables the ability to set a page table entry encryption bit:</p><ul><li><p>0 = memory encryption features are disabled</p></li><li><p>1 = memory encryption features are enabled</p></li></ul><p>After memory encryption is enabled, a physical address bit (C-Bit) is utilized to mark if a memory page is protected. The operating system sets the bit of a physical address to 1 in the page table entry (PTE) to indicate the page should be encrypted. This causes any data assigned to that memory space to be automatically encrypted and decrypted by the AES engine in the memory controller:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4Y55gr55Ypmf0kCFfSBrNN/d52fa52def521555431c16c76d9a1086/enclavng-diagrams_3x.png" />
            
            </figure>
    <div>
      <h3>Becoming More Transparent</h3>
      <a href="#becoming-more-transparent">
        
      </a>
    </div>
    <p>While arbitrarily flagging which page table entries we want encrypted is nice, our objective is to ensure that we are incorporating the full physical protection of SME. This is where the second mode of SME came in, Transparent SME (TSME). In TSME, all memory is encrypted regardless of the value of the encrypt bit on any particular page. This includes both instruction and data pages, as well as the pages corresponding to the page tables themselves.</p><p>Enabling TSME is as simple as:</p><ol><li><p>Setting a BIOS flag:</p></li></ol>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6AqdL0sTjEI4YKjHdwas11/d1f28bfac2bd91a7751fe4fe2aa25109/bios-tsme2.png" />
            
            </figure><p>2. Enabling kernel support with the following flag:</p><p><code>CONFIG_AMD_MEM_ENCRYPT=y</code></p><p>After a reboot you should see the following in <code>dmesg</code>:</p>
            <pre><code>$ sudo dmesg | grep SME
[    2.537160] AMD Secure Memory Encryption (SME) active</code></pre>
            
    <div>
      <h2>Performance Testing</h2>
      <a href="#performance-testing">
        
      </a>
    </div>
    <p>To weigh the pros and cons of implementation against the potential risk of a stolen server, we had to test the performance of enabling TSME. We took a test server that mirrored a production edge metal with the following specs:</p><ul><li><p>Memory: 8 x 32GB 2933MHz</p></li><li><p>CPU: AMD 2nd Gen EPYC 7642 with SMT enabled and running NPS4 mode</p></li><li><p>OS: Debian 9</p></li><li><p>Kernel: <a href="https://lwn.net/Articles/809568/">5.4.12</a></p></li></ul><p>The performance tools we used were:</p><ul><li><p><a href="http://www.cs.virginia.edu/stream/ref.html">STREAM</a></p></li><li><p><a href="http://man7.org/linux/man-pages/man8/cryptsetup.8.html">Cryptsetup</a></p></li><li><p>Benchmarky</p></li></ul>
    <div>
      <h2>Stream</h2>
      <a href="#stream">
        
      </a>
    </div>
    <p>We used a custom STREAM binary with 24 threads, using all available cores, to measure the sustainable memory bandwidth (in MB/s). Four synthetic computational kernels are run, with the output of each kernel being used as an input to the next. The best rates observed are reported for each choice of thread count.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1kwLMDcfqdWZ0dP9dgpbBO/a8ac5a90cd57a212539df64002fd1a04/Stream-SME-On-vs-Off-1.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3C8c6Nfn0cScGA0dt4yTaN/1bf1a1f32cceefac591aab63a1ab1e1c/Stream-Performance-delta-1.png" />
            
            </figure><p>The figures above show 2.6% to 4.2% performance variation, with a mean of 3.7%. These were the highest numbers measured, which fell below an expected performance impact of &gt;5%.</p>
    <div>
      <h2>Cryptsetup</h2>
      <a href="#cryptsetup">
        
      </a>
    </div>
    <p>While cryptsetup is normally used for encrypting disk partitions, it has a benchmarking utility that will report on a host’s cryptographic performance by iterating key derivation functions using memory only:</p><p>Example:</p>
            <pre><code>$ sudo cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1      1162501 iterations per second for 256-bit key
PBKDF2-sha256    1403716 iterations per second for 256-bit key
PBKDF2-sha512    1161213 iterations per second for 256-bit key
PBKDF2-ripemd160  856679 iterations per second for 256-bit key
PBKDF2-whirlpool  661979 iterations per second for 256-bit key</code></pre>
            
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5BC1HclFkbzijWahfsXLxH/67dec2664c6a31625c99613aef6b925e/cryptsetup-benchmark-SME-Off-vs-On-1.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1FoosofQ0iHlQbLAdi8fuS/950d23104a94ad5bd66f15614dd72b49/crypt-Performance-delta-1.png" />
            
            </figure>
    <div>
      <h2>Benchmarky</h2>
      <a href="#benchmarky">
        
      </a>
    </div>
    <p>Benchmarky is a homegrown tool <a href="/author/ivan/">provided by our Performance team</a> to run synthetic workloads against a specific target to evaluate performance of different components. It uses <a href="https://workers.cloudflare.com/">Cloudflare Workers</a> to send requests and read stats on responses. In addition to that, it also reports versions of all important stack components and their CPU usage. Each test runs 256 concurrent clients, grabbing a cached 10kB PNG image from a performance testing endpoint, and calculating the requests per second (RPS).</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2uHw5bMNlZiKFLb3Ks5weQ/37cbcd116f472c6b20a35ede49d26f15/benckmarky-SME-off-and-SME-on-1.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3h5FsuK2Lv5xS3qUwv382A/2161213c7b0fb3715d9ab3eae66d4cc3/bench-Performance-delta-1.png" />
            
            </figure>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>In the majority of test results, performance decreased by a nominal amount, actually less than we expected. AMD’s official <a href="https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf">white paper</a> on SME even states that encryption and decryption of memory through the AES engine does incur a small amount of additional latency for DRAM memory accesses, though dependent on the workload. Across all 11 data points, our average performance drag was only down by .699%. Even at scale, enabling this feature has reduced the worry that <i>any</i> data could be exfiltrated from a stolen server.</p><p>While we wait for other hardware manufacturers to add support for <a href="https://en.wikichip.org/wiki/x86/tme">total memory encryption,</a> we are happy that AMD has set the bar high and is protecting our next generation edge hardware.</p> ]]></content:encoded>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Data Center]]></category>
            <category><![CDATA[Cloudflare Network]]></category>
            <category><![CDATA[Security]]></category>
            <guid isPermaLink="false">8ZqsGZD6Kw9pakjpzsIuP</guid>
            <dc:creator>Derek Chamorro</dc:creator>
            <dc:creator>Brian Bassett</dc:creator>
        </item>
        <item>
            <title><![CDATA[Gen X Performance Tuning]]></title>
            <link>https://blog.cloudflare.com/gen-x-performance-tuning/</link>
            <pubDate>Thu, 27 Feb 2020 14:00:00 GMT</pubDate>
            <description><![CDATA[ We have partnered with AMD to get the best performance out of this processor and today, we are highlighting our tuning efforts that led to an additional 6% performance. Thermal design power (TDP) and dynamic power, amongst others, play a critical role when tuning a system.  ]]></description>
            <content:encoded><![CDATA[ 
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6TT8W5Et00ZvvobGvrgMEY/1424f7ef2b4d6cc216b4a7ababc750ee/image7-3.png" />
            
            </figure><p>We are using AMD 2nd Gen EPYC 7642 for our <a href="/cloudflares-gen-x-servers-for-an-accelerated-future/">tenth generation “Gen X” servers</a>. We found <a href="/an-epyc-trip-to-rome-amd-is-cloudflares-10th-generation-edge-server-cpu/">many aspects of this processor compelling</a> such as its <a href="/impact-of-cache-locality/">increase in performance due to its frequency bump and cache-to-core ratio</a>. We have partnered with AMD to get the best performance out of this processor and today, we are highlighting our tuning efforts that led to an additional 6% performance.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/616TtlNrwVkyeHby6ReKSD/8127c8a658986889c1d54810ecd9433f/image14.png" />
            
            </figure>
    <div>
      <h2>Thermal Design Power &amp; Dynamic Power</h2>
      <a href="#thermal-design-power-dynamic-power">
        
      </a>
    </div>
    <p>Thermal design power (TDP) and dynamic power, amongst others, play a critical role when tuning a system. Many share a common belief that thermal design power is the maximum or average power drawn by the processor. The 48-core <a href="https://www.amd.com/en/products/cpu/amd-epyc-7642">AMD EPYC 7642</a> has a TDP rating of 225W which is just as high as the 64-core <a href="https://www.amd.com/en/products/cpu/amd-epyc-7742">AMD EPYC 7742</a>. It comes to mind that fewer cores should translate into lower power consumption, so why is the AMD EPYC 7642 expected to draw just as much power as the AMD EPYC 7742?</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/420qeX6xoS09gLZaWH9F8p/051cc471d235fce238703d227f65a5f7/image10-2.png" />
            
            </figure><p><i>TDP Comparison between the EPYC 7642, EPYC 7742 and top-end EPYC 7H12</i></p><p>Let’s take a step back and understand that TDP does not always mean the maximum or average power that the processor will draw. At a glance, TDP may provide a good estimate about the processor’s power draw; TDP is really about how much heat the processor is expected to generate. TDP should be used as a guideline for designing cooling solutions with appropriate thermal capacitance. The cooling solution is expected to indefinitely dissipate heat up to the TDP, in turn, this can help the chip designers determine a power budget and create new processors around that constraint. In the case of the AMD EPYC 7642, the extra power budget was spent on retaining all of its 256 MiB L3 cache and the cores to operate at a higher sustained frequency as needed during our peak hours.</p><p>The overall power drawn by the processor depends on many different factors; dynamic or active power establishes the relationship between power and frequency. Dynamic power is a function of capacitance - the chip itself, supply voltage, frequency of the processor, and activity factor. The activity factor is dependent on the characteristics of the workloads running on the processor. Different workloads will have different characteristics. Some examples include <a href="/cloudflare-workers-unleashed/">Cloudflare Workers</a> or <a href="/seamless-remote-work-with-cloudflare-access/">Cloudflare for Teams</a>, the hotspots in these or any other particular programs will utilize different parts of the processor, affecting the activity factor.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/12AEwpVHIGoT9XGcqHo83V/319acd3abb48e14d48d5defd4dc8a0c4/image-7.png" />
            
            </figure>
    <div>
      <h2>Determinism Modes &amp; Configurable TDP</h2>
      <a href="#determinism-modes-configurable-tdp">
        
      </a>
    </div>
    <p>The latest AMD processors continue to implement AMD Precision Boost which opportunistically allows the processor to operate at a higher frequency than its base frequency. How much higher can the frequency go depends on many different factors such as electrical, thermal, and power limitations.</p><p>AMD offers a knob known as determinism modes. This knob affects power and frequency, placing emphasis one over the other depending on the determinism selected. <a href="https://www.amd.com/system/files/2017-06/Power-Performance-Determinism.pdf">There is a white paper</a> posted on AMD's website that goes into the nuanced details of determinism, and remembering how frequency and power are related - this was the simplest definition I took away from the paper:</p><p><b>Performance Determinism</b> - Power is a function of frequency.</p><p><b>Power Determinism</b> - Frequency is a function of power.</p><p>Another knob that is available to us is Configurable Thermal Design Power (cTDP), this knob allows the end-user to reconfigure the factory default thermal design power. The AMD EPYC 7642 is rated at 225W; however, we have been given guidance from AMD that this particular part can be reconfigured up to 240W. As mentioned previously, the cooling solution must support up to the TDP to avoid throttling. We have also done our due diligence and tested that our cooling solution can reliably dissipate up to 240W, even at higher ambient temperatures.</p><p>We gave these two knobs a try and got the results shown in the figures below using 10 KiB web assets over HTTPS <a href="/author/ivan/">provided by our performance team</a> over a sustained period of time to properly heat up the processor. The figures are broken down into the average operating frequencies across all 48 cores, total package power drawn from the socket, and the highest reported die temperature out of the 8 dies that are laid out on the AMD EPYC 7642. Each figure will compare the results we obtained from power and performance determinism, and finally, cTDP at 240W using power determinism.</p><p>Performance determinism clearly emphasized stabilizing operating frequency by matching its frequency to its lowest performing core over time. This mode appears to be ideal for tuners that emphasizes predictability over maximizing the processor’s operating frequency. In other words, the number of cycles that the processor has at its disposal every second should be predictable. This is useful if two or more cores share data dependencies. By allowing the cores to work in unison; this can prevent one core stalling another. Power determinism on the other hand, maximized its power and frequency as much as it can.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2yiJbib8HJNMkMZc7On1K4/19411800792deb9713cc65c943fc232c/image12.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2KXAIrxO2pCwpDAMlHyKW/49769b6a78d78577c13ea0109d4410ac/image11-2.png" />
            
            </figure><p>Heat generated by power can be compounded even further by ambient temperature. All components should stay within safe operating temperature at all times as specified by the vendor’s datasheet. If unsure, please reach out to your vendor as soon as possible. We put the AMD EPYC 7642 through several thermal tests and determined that it will operate within safe operating temperatures. Before diving into the figure below, it is important to mention that our fan speed ramped up over time, preventing the processor from reaching critical temperature; nevertheless, this meant that our cooling solution worked as intended - a combination of fans and a heatsink rated for 240W. We have yet to see the processors throttle in production. The figure below shows the highest temperature of the 8 dies laid out on the AMD EPYC 7642.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/S2zzgzeBBeyhzBXxkU1Zz/8c7880845e49ceec2cf761265724d046/image8-3.png" />
            
            </figure><p>An unexpected byproduct of performance determinism was frequency jitter. It took a longer time for performance determinism to achieve steady-state frequency, which contradicted predictable performance that performance determinism mode was meant to achieve.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6LK2tZgnsa8m86vPQYdjrS/87474e0b887e438d97254fde28b2f8ac/image9-1.png" />
            
            </figure><p>Finally, here are the deltas out from the real world with performance determinism and TDP set to factory default of 225W as the baseline. Deltas under 10% can be influenced by a wide variety of factors especially in production, however, none of our data showed a negative trend. Here are the averages.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2ZT2L9MokepRw2GmZbKuxE/f3facacec8efefc02cf704137f09930e/image-5.png" />
            
            </figure>
    <div>
      <h2>Nodes Per Socket (NPS)</h2>
      <a href="#nodes-per-socket-nps">
        
      </a>
    </div>
    <p>The AMD EPYC 7642 <a href="/impact-of-cache-locality/">physically lays out its 8 dies across 4 different quadrants on a single package</a>. By having such a layout, AMD supports dividing its dies into NUMA domains and this feature is called Nodes Per Socket or NPS. Available NPS options differ model-to-model, the AMD EPYC 7642 supports 4, 2, and 1 node(s) per socket. We thought it might be worth our time exploring this option despite the fact that none of these choices will end up yielding a shared last level cache. We did not observe any significant deltas from the NPS options in terms of performance.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7aTakzcywLXCq9cVbJUapE/99073a5a3e205037b7561c641258091f/image15.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/26jjqqzj8LFJecjFpq8ucU/4306eb572afd428965162fbe454172c4/image13-1.png" />
            
            </figure>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Tuning the processor to yield an additional 6% throughput or requests per second out of the box has been a great start. Some parts will have more rooms for improvement than others.  In production we were able to achieve an additional 2% requests per seconds with power determinism, and we achieved another 4% by reconfiguring the TDP to 240W. We will continue to work with AMD as well as internal teams within Cloudflare to identify additional areas of improvement. If you like the idea of supercharging the Internet on behalf of our customers, then <a href="https://www.cloudflare.com/careers/jobs/">come join us</a>.</p> ]]></content:encoded>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[AMD]]></category>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Gen X]]></category>
            <guid isPermaLink="false">5S0eOaziY4ST5v0PscTOAW</guid>
            <dc:creator>Sung Park</dc:creator>
        </item>
        <item>
            <title><![CDATA[Impact of Cache Locality]]></title>
            <link>https://blog.cloudflare.com/impact-of-cache-locality/</link>
            <pubDate>Wed, 26 Feb 2020 12:00:00 GMT</pubDate>
            <description><![CDATA[ Our Gen X servers process more requests per second per core than our previous fleet. The AMD 2nd Gen EPYC 7642 processor’s large L3 cache minimizes L3 cache misses, and the time-savings add up quickly. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>In the past, we didn't have the opportunity to evaluate as many CPUs as we do today. The hardware ecosystem was simple – Intel had consistently delivered industry leading processors. Other vendors could not compete with them on both performance and cost. Recently it all changed: AMD has been challenging the status quo with their 2nd Gen EPYC processors.</p><p>This is not the first time that Intel has been challenged; previously <a href="/arm-takes-wing/">there was Qualcomm</a>, and we worked with AMD and considered their 1st Gen EPYC processors and based on the original Zen architecture, but ultimately, <a href="/a-tour-inside-cloudflares-g9-servers/">Intel prevailed</a>. AMD did not give up and unveiled their 2nd Gen EPYC processors codenamed Rome based on the latest Zen 2 architecture.</p><blockquote><p>Playing with some new fun kit. <a href="https://twitter.com/hashtag/epyc?src=hash&amp;ref_src=twsrc%5Etfw">#epyc</a> <a href="https://t.co/1No8Cmfzwl">pic.twitter.com/1No8Cmfzwl</a></p><p>— Matthew Prince ? (@eastdakota) <a href="https://twitter.com/eastdakota/status/1192898039003766785?ref_src=twsrc%5Etfw">November 8, 2019</a></p></blockquote><p>This made many improvements over its predecessors. Improvements include a die shrink from 14nm to 7nm, a doubling of the top end core count from 32 to 64, and a larger L3 cache size. Let’s emphasize again on the size of that L3 cache, which is 32 MiB L3 cache per Core Complex Die (CCD).</p><p>This time around, we have taken steps to understand our workloads at the hardware level through the use of hardware performance counters and profiling tools. Using these specialized CPU registers and profilers, we collected data on the AMD 2nd Gen EPYC and Intel Skylake-based Xeon processors in a lab environment, then validated our observations in production against other generations of servers from the past.</p>
    <div>
      <h2>Simulated Environment</h2>
      <a href="#simulated-environment">
        
      </a>
    </div>
    <p>CPU Specifications</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/42MpuiHDcFmNWT8c5GOh96/3666d84667b56b645e29aec5cfafdfdd/image-3.png" />
            
            </figure><p>We evaluated several Intel Cascade Lake and AMD 2nd Gen EPYC processors, trading off various factors between power and performance; the AMD EPYC 7642 CPU came out on top. The majority of Cascade Lake processors have 1.375 MiB L3 cache per core shared across all cores, a common theme that started with Skylake. On the other hand, the 2nd Gen EPYC processors start at 4 MiB per core. The AMD EPYC 7642 is a unique SKU since it has 256 MiB of L3 cache. Having a cache this large or approximately 5.33 MiB sitting right next to each core means that a program will spend fewer cycles fetching data from RAM with the capability to have more data readily available in the L3 cache.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7FVYxpe6TeVh26fV12eeBw/a285e437f90b2ac809811bb3645b1130/Infrastructure-before_2x.png" />
            
            </figure><p><i>Before (Intel)</i></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/zMlvsRWnuL6SwUUPyLHBu/13d459bee2cf7d0c195bb74b18c49555/Infrastructure-after-_2x--1-.png" />
            
            </figure><p><i>After (AMD)</i></p><p>Traditional cache layout has also changed with the introduction of 2nd Gen EPYC, a byproduct of AMD using a multi-chip module (MCM) design. The 256 MiB L3 cache is formed by 8 individual dies or Core Complex Die (CCD) that is formed by 2 Core Complexes (CCX) with each CCX containing 16 MiB of L3 cache.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5oqKl2iToZamCbBNQBH2uj/ba9b72846f7f81c92e0ccf705f3be9c1/image6.png" />
            
            </figure><p><i>Core Complex (CCX) - Up to four cores</i></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6p5FRRU9VZTMWhkdNH7g4/acb4ff79d8916a20278f8c50e21c53bb/image9.png" />
            
            </figure><p><b>Core Complex Die (CCD) - Created by combining two CCXs</b></p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2IyMxh74THzCubUs6H3SY1/a031494b9f0783406ef653b3e99ad598/image1-2.png" />
            
            </figure><p><i>AMD 2nd Gen EPYC 7642 - Created with 8x CCDs plus an I/O die in the center</i></p>
    <div>
      <h3>Methodology</h3>
      <a href="#methodology">
        
      </a>
    </div>
    <p>Our production traffic shares many characteristics of a sustained workload which typically does not induce large variation in operating frequencies nor enter periods of idle time. We picked out a simulated traffic pattern that closely resembled our production traffic behavior which was the Cached 10KiB png via HTTPS. We were interested in assessing the CPU’s maximum throughput or requests per second (RPS), one of our key metrics. With that being said, we did not disable Intel Turbo Boost or AMD Precision Boost, nor matched the frequencies clock-for-clock while measuring for requests per second, instructions retired per second (IPS), L3 cache miss rate, and sustained operating frequency.</p>
    <div>
      <h3>Results</h3>
      <a href="#results">
        
      </a>
    </div>
    <p>The 1P AMD 2nd Gen EPYC 7642 powered server took the lead and processed 50% more requests per second compared to our Gen 9’s 2P Intel Xeon Platinum 6162 server.</p><p>We are running a sustained workload, so we should end up with a sustained operating frequency that is higher than base clock. The AMD EPYC 7642 operating frequency or the number cycles that the processor had at its disposal was approximately 20% greater than the Intel Xeon Platinum 6162, so frequency alone was not enough to explain the 50% gain in requests per second.</p><p>Taking a closer look, the number of instructions retired over time was far greater on the AMD 2nd Gen EPYC 7642 server, thanks to its low L3 cache miss rate.</p>
    <div>
      <h3>Production Environment</h3>
      <a href="#production-environment">
        
      </a>
    </div>
    <p>CPU Specifications</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7lji8wRNR827IKHgDE3asr/3180fa701066cee223dde822b313d8ec/image-2.png" />
            
            </figure>
    <div>
      <h3>Methodology</h3>
      <a href="#methodology">
        
      </a>
    </div>
    <p>Our most predominant bottleneck appears to be the cache memory and we saw significant improvement in requests per second as well as <a href="/an-epyc-trip-to-rome-amd-is-cloudflares-10th-generation-edge-server-cpu/">time to process a request</a> due to low L3 cache miss rate. The data we present in this section was collected at a point of presence that spanned between Gen 7 to Gen 9 servers. We also collected data from a secondary region to gain additional confidence that the data we present here was not unique to one particular environment. Gen 9 is the baseline just as we have done in the previous section.</p><p>We put the 2nd Gen EPYC-based Gen X into production with hopes that the results would mirror closely to what we have previously seen in the lab. We found that the requests per second did not quite align with the results we had hoped, but the AMD EPYC server still outperformed all previous generations including outperforming the Intel Gen 9 server by 36%.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4V8uzcFfnFwUIH0leecLnm/232bd88ceb2216efa4fae242a085a140/image8.png" />
            
            </figure><p>Sustained operating frequency was nearly identical to what we have seen back in the lab.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3DhckmjQqo7b9JtllouvVL/19b3fda2e8a5a277c511269f4bc7a148/image10.png" />
            
            </figure><p>Due to the lower than expected requests per second, we also saw lower instructions retired over time and higher L3 cache miss rate but maintained a lead over Gen 9, with 29% better performance.</p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>The single AMD EPYC 7642 performed very well during our lab testing, beating our Gen 9 server with dual Intel Xeon Platinum 6162 with the same total number of cores. Key factors we noticed were its large L3 cache, which led to a low L3 cache miss rate, as well as a higher sustained operating frequency. The AMD 2nd Gen EPYC 7642 did not have as big of an advantage in production, but nevertheless still outperformed all previous generations. The observation we made in production was based on a PoP that could have been influenced by a number of other factors such as but not limited to ambient temperature, timing, and other new products that will shape our traffic patterns in the future such as <a href="/webassembly-on-cloudflare-workers/">WebAssembly on Cloudflare Workers</a>. The AMD EPYC 7642 opens up the possibility for our upcoming Gen X server to maintain the same core count while processing more requests per second than its predecessor.</p><p>Got a passion for hardware? I think we should get in touch. We are always looking for talented and curious individuals to <a href="https://www.cloudflare.com/careers/departments/">join our team</a>. The data presented here would not have been possible if it was not for the teamwork between many different individuals within Cloudflare. As a team, we strive to work together to create highly performant, reliable, and secure systems that will form the pillars of our rapidly growing <a href="https://www.cloudflare.com/network/">network</a> that spans 200 cities in more than 90 countries and we are just getting started.</p> ]]></content:encoded>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Data Center]]></category>
            <category><![CDATA[Cloudflare Network]]></category>
            <category><![CDATA[Partners]]></category>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">2QRJzUFnyzSRaIXLggtDqr</guid>
            <dc:creator>Sung Park</dc:creator>
        </item>
        <item>
            <title><![CDATA[An EPYC trip to Rome: AMD is Cloudflare's 10th-generation Edge server CPU]]></title>
            <link>https://blog.cloudflare.com/an-epyc-trip-to-rome-amd-is-cloudflares-10th-generation-edge-server-cpu/</link>
            <pubDate>Tue, 25 Feb 2020 14:00:00 GMT</pubDate>
            <description><![CDATA[ As we looked at production ready systems to power our Gen X solution, we’re moving on from Gen 9's 48-core setup of dual socket Intel Xeon Platinum 6162's to a 48-core single socket AMD EPYC 7642. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>More than 1 billion unique IP addresses pass through the <a href="/tag/cloudflare-network/">Cloudflare Network</a> each day, serving on average 11 million HTTP requests per second and operating within 100ms of 95% of the Internet-connected population globally. Our network spans 200 cities in more than 90 countries, and our engineering teams have built an extremely <a href="/tag/speed-and-reliability/">fast and reliable infrastructure</a>.</p><p>We’re extremely proud of our work and are determined to help make the Internet a <a href="https://www.fastcompany.com/most-innovative-companies/2019/sectors/security">better and more secure place</a>. Cloudflare engineers who are involved with hardware get down to servers and their components to understand and select the best hardware to maximize the performance of our stack.</p><p>Our software stack is compute intensive and is very much CPU bound, driving our engineers to work continuously at optimizing Cloudflare’s performance and reliability at all layers of our stack. With the server, a straightforward solution for increasing computing power is to have more CPU cores. The more cores we can include in a server, the more output we can expect. This is important for us since the diversity of our products and customers has grown over time with increasing demand that requires our servers to do more. To help us drive compute performance, we needed to increase core density and that's what we did. Below is the processor detail for servers we’ve deployed since 2015, including the core counts:</p><table><tr><td><p>---</p></td><td><p><b>Gen 6</b></p></td><td><p><b>Gen 7</b></p></td><td><p><b>Gen 8</b></p></td><td><p><b>Gen 9</b></p></td></tr><tr><td><p>Start of service</p></td><td><p>2015</p></td><td><p>2016</p></td><td><p>2017</p></td><td><p>2018</p></td></tr><tr><td><p>CPU</p></td><td><p>Intel Xeon E5-2630 v3</p></td><td><p>Intel Xeon E5-2630 v4</p></td><td><p>Intel Xeon Silver 4116</p></td><td><p>Intel Xeon Platinum 6162</p></td></tr><tr><td><p>Physical Cores</p></td><td><p>2 x 8</p></td><td><p>2 x 10</p></td><td><p>2 x 12</p></td><td><p>2 x 24</p></td></tr><tr><td><p>TDP</p></td><td><p>2 x 85W</p></td><td><p>2 x 85W</p></td><td><p>2 x 85W</p></td><td><p>2 x 150W</p></td></tr><tr><td><p>TDP per Core</p></td><td><p>10.65W</p></td><td><p>8.50W</p></td><td><p>7.08W</p></td><td><p>6.25W</p></td></tr></table><p>In 2018, we made a big jump in total number of cores per server with <a href="/a-tour-inside-cloudflares-g9-servers/">Gen 9</a>. Our physical footprint was reduced by 33% compared to Gen 8, giving us increased capacity and computing power per rack. Thermal Design Power (TDP aka typical power usage) are mentioned above to highlight that we've also been more power efficient over time. Power efficiency is important to us: first, because we'd like to be as <a href="/a-carbon-neutral-north-america/">carbon friendly</a> as we can; and second, so we can better utilize our provisioned power supplied by the data centers. But we know we can do better.</p><p>Our main defining metric is Requests per Watt. We can increase our Requests per Second number with more cores, but we have to stay within our power budget envelope. We are constrained by the data centers’ power infrastructure which, along with our selected power distribution units, leads us to power cap for each server rack. Adding servers to a rack obviously adds more power draw increasing power consumption at the rack level. Our Operational Costs significantly increase if we go over a rack’s power cap and have to provision another rack. What we need is more compute power inside the same power envelope which will drive a higher (better) Requests per Watt number – our key metric.</p><p>As you might imagine, we look at power consumption carefully in the design stage. From the above you can see that it’s not worth the time for us to deploy more power-hungry CPUs if TDP per Core is higher than our current generation which would hurt our Requests per Watt metric. As we started looking at production ready systems to power our Gen X solution, we took a long look at what is available to us in the market today, and we’ve made our decision. We’re moving on from Gen 9's 48-core setup of dual socket <a href="https://ark.intel.com/content/www/us/en/ark/products/136869/intel-xeon-platinum-6162-processor-33m-cache-1-90-ghz.html">Intel® Xeon® Platinum 6162</a>'s to a 48-core single socket <a href="https://www.amd.com/en/products/cpu/amd-epyc-7642">AMD EPYC™ 7642</a>.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6Ub4NDKC4KKIMsXY2cFPJW/2bb5250e410aa4c75cad9651ab1b84f7/1.jpg" />
            
            </figure><p>                                      Gen X server setup with single socket 48-core AMD EPYC 7642.</p><table><tr><td><p><b>---</b></p></td><td><p><b>Intel</b></p></td><td><p><b>AMD</b></p></td></tr><tr><td><p>CPU</p></td><td><p>Xeon Platinum 6162</p></td><td><p>EPYC 7642</p></td></tr><tr><td><p>Microarchitecture</p></td><td><p>“Skylake”</p></td><td><p>“Zen 2”</p></td></tr><tr><td><p>Codename</p></td><td><p>“Skylake SP”</p></td><td><p>“Rome”</p></td></tr><tr><td><p>Process</p></td><td><p>14nm</p></td><td><p>7nm</p></td></tr><tr><td><p>Physical Cores</p></td><td><p>2 x 24</p></td><td><p>48</p></td></tr><tr><td><p>Frequency</p></td><td><p>1.9 GHz</p></td><td><p>2.4 GHz</p></td></tr><tr><td><p>L3 Cache / socket</p></td><td><p>24 x 1.375MiB</p></td><td><p>16 x 16MiB</p></td></tr><tr><td><p>Memory / socket</p></td><td><p>6 channels, up to DDR4-2400</p></td><td><p>8 channels, up to DDR4-3200</p></td></tr><tr><td><p>TDP</p></td><td><p>2 x 150W</p></td><td><p>225W</p></td></tr><tr><td><p>PCIe / socket</p></td><td><p>48 lanes</p></td><td><p>128 lanes</p></td></tr><tr><td><p>ISA</p></td><td><p>x86-64</p></td><td><p>x86-64</p></td></tr></table><p>From the specs, we see that with the AMD chip we get to keep the same amount of cores and lower TDP. Gen 9's TDP per Core was 6.25W, Gen X's will be 4.69W... That's a 25% decrease. With higher frequency, and perhaps going to a more simplified setup of single socket, we can speculate that the AMD chip will perform better. We're walking through a series of tests, simulations, and live production results in the rest of this blog to see how much better AMD performs.</p><p>As a side note before we go further, TDP is a simplified metric from the manufacturers’ datasheets that we use in the early stages of our server design and CPU selection process. A quick Google search leads to thoughts that AMD and Intel define TDP differently, which basically makes the spec unreliable. Actual CPU power draw, and more importantly server system power draw, are what we really factor in our final decisions.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4ue5oOlAdewYkerMSsEPWN/5cf921da1bc31eccd575af6670af66d3/2.png" />
            
            </figure>
    <div>
      <h3>Ecosystem Readiness</h3>
      <a href="#ecosystem-readiness">
        
      </a>
    </div>
    <p>At the beginning of our journey to choose our next CPU, we got a variety of processors from different vendors that could fit well with our software stack and services, which are written in C, LuaJIT, and Go. More details about benchmarking for our stack were explained when we benchmarked <a href="/arm-takes-wing/">Qualcomm's ARM® chip in the past</a>. We're going to go through the same suite of tests as Vlad's blog this time around since it is a quick and easy "sniff test". This allows us to test a bunch of CPUs within a manageable time period before we commit to spend more engineering effort and need to apply our software stack.</p><p>We tried a variety of CPUs with different number of cores, sockets, and frequencies. Since we're explaining how we chose the AMD EPYC 7642, all the graphs in this blog focus on how AMD compares with our <a href="/a-tour-inside-cloudflares-g9-servers/">Gen 9's Intel Xeon Platinum 6162 CPU</a> as a baseline.</p><p>Our results correspond to server node for both CPUs tested; meaning the numbers pertain to 2x 24-core processors for Intel, and 1x 48-core processor for AMD – a two socket Intel based server and a one socket AMD EPYC powered server. Before we started our testing, we changed the Cloudflare lab test servers’ BIOS settings to match our production server settings. This gave us CPU frequencies yields for AMD at 3.03 Ghz and Intel at 2.50 Ghz on average with very little variation. With gross simplification, we expect that with the same amount of cores AMD would perform about 21% better than Intel. Let’s start with our crypto tests.</p>
    <div>
      <h3>Cryptography</h3>
      <a href="#cryptography">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3AZYQDj2nhVofkFNuK7fhb/dea112fd9ae2b2e91514b62e21d242d6/3.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2OpcfNqi2hraQrS8fZV0Lw/29fcc9dcf3ec73400a8fe784a12b26f5/4.png" />
            
            </figure><p>Looking promising for AMD. In public key cryptography, it does 18% better. Meanwhile, for symmetric key, AMD loses on AES-128-GCM, but it’s comparable overall.</p>
    <div>
      <h3>Compression</h3>
      <a href="#compression">
        
      </a>
    </div>
    <p>We do a lot of compression at the edge to save bandwidth and help deliver content faster. We go through both zlib and brotli libraries written in C. All tests are done on <a href="/">blog.cloudflare.com</a> HTML file in memory.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3IVKryfCIXY2c6vXt8KsPc/eab9765ff8650fc9fbe97a82cf89f0cf/5.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2ycU6O5cbLREXNJV29sPDI/4472bc4ae36cfedae67535d08e5e10f8/6.png" />
            
            </figure><p>AMD wins by an average of 29% using gzip across all qualities. It does even better with brotli with tests lower than quality 7, which we use for dynamic compression. There’s a throughput cliff starting brotli-9 which <a href="/arm-takes-wing/">Vlad’s explanation</a> is that Brotli consumes lots of memory and thrashes cache. Nevertheless, AMD wins by a healthy margin.</p><p>A lot of our services are written in Go. In the following graphs we’re redoing the crypto and compression tests in Go along with RegExp on 32KB strings and the strings' library.</p>
    <div>
      <h3>Go Cryptography</h3>
      <a href="#go-cryptography">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1JRYfDXEC61iGL6Ds7LjL1/16b8980b2b2cf5bdda22769d0dad5fa6/7.png" />
            
            </figure>
    <div>
      <h3>Go Compression</h3>
      <a href="#go-compression">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5U6GEnTLU1VVvqbZtJZ1df/0e3a0fa77bbb3ce709e36503e9eaba66/Screen-Shot-2020-02-24-at-14.37.27.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3YQTrE7SfEiCXjivU7NXXf/c5b22a8a38b2eb48c0658d4b9b3a1f63/9.png" />
            
            </figure>
    <div>
      <h3>Go Regexp</h3>
      <a href="#go-regexp">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1ZQn6rtg7fE6IJ3wNgpCf/9886faae1855b658347fccfe72802a0a/10.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/vvUuNzVuRrgGqVrGOxagJ/720667e78cb5b34eda7f4ca0d445bd9f/11.png" />
            
            </figure>
    <div>
      <h3>Go Strings</h3>
      <a href="#go-strings">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3BY6NTdgjUWGiDBwC0NMNv/8943902a6f047eb8d2f9079e9b1e432b/12.png" />
            
            </figure><p>AMD performs better in all of our Go benchmarks except for ECDSA P256 Sign losing by 38%, which is peculiar since with the test in C it does 24% better. It’s worth investigating what’s going on here. Other than that, AMD doesn’t win by as much of a margin, but it still proves to be better.</p>
    <div>
      <h3>LuaJIT</h3>
      <a href="#luajit">
        
      </a>
    </div>
    <p>We rely a lot on LuaJIT in our stack. As <a href="/arm-takes-wing/">Vlad said</a>, it’s the glue that holds Cloudflare together. We’re glad to show that AMD wins here as well.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4VM41wrmwYIpaJSvR70ztl/95f5f48fad6f48034422ea69b62c73b6/13.png" />
            
            </figure><p>Overall our tests show a single EPYC 7642 to be more competitive than two Xeon Platinum 6162. While there are a couple of tests where AMD loses out such as OpenSSL AES-128-GCM and Go OpenSSL ECDSA-P256 Sign, AMD wins in all the others. By scanning quickly and treating all tests equally, AMD does on average 25% better than Intel.</p>
    <div>
      <h3>Performance Simulations</h3>
      <a href="#performance-simulations">
        
      </a>
    </div>
    <p>After our ‘sniff’ tests, we put our servers through another series of emulations which apply synthetic workloads simulating our edge software stack. Here we are simulating workloads of scenarios with different types of requests we see in production. Types of requests vary from asset size, whether they go through HTTP or HTTPS, <a href="https://www.cloudflare.com/learning/ddos/glossary/web-application-firewall-waf/">WAF</a>, Workers, or one of many additional variables. Below shows the throughput comparison between the two CPUs of the types of requests we see most typically.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2Rj1NqqXfYroVsefnGQQgS/c598bbf7b324ab6944236e91d5f5e28a/14.png" />
            
            </figure><p>The results above are ratios using Gen 9's Intel CPUs as the baseline normalized at 1.0 on the X-axis. For example, looking at simple requests of 10KiB assets over HTTPS, we see that AMD does 1.50x better than Intel in Requests per Second. On average for the tests shown on the graph above, AMD performs 34% better than Intel. Considering that the TDP for the single AMD EPYC 7642 is 225W, when compared to two Intel's being 300W, we're looking at AMD delivering up to 2.0x better Requests per Watt vs. the Intel CPUs!</p><p>By this time, we were already leaning heavily toward a single socket setup with AMD EPYC 7642 as our CPU for Gen X. We were excited to see exactly how well AMD EPYC servers would do in production, so we immediately shipped a number of the servers out to some of our data centers.</p>
    <div>
      <h3>Live Production</h3>
      <a href="#live-production">
        
      </a>
    </div>
    <p>Step one of course was to get all our test servers set up for a production environment. All of our machines in the fleet are loaded with the same processes and services which makes for a great apples-to-apples comparison.  Like data centers everywhere, we have multiple generations of servers deployed, and we deploy our servers in clusters such that each cluster is pretty homogeneous by server generation. In some environments this can lead to varying utilization curves between clusters.  This is not the case for us. Our engineers have optimized CPU utilization across all server generations so that no matter if the machine's CPU has 8 cores or 24 cores, CPU usage is generally the same.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2CiOx8dprb9NuYH2kUrZQ/ef686808c946d6cc55aa2983dc50c839/15.png" />
            
            </figure><p>As you can see above and to illustrate our ‘similar CPU utilization’ comment, there is no significant difference in CPU usage between Gen X AMD powered servers and Gen 9 Intel based servers. This means both test and baseline servers are equally loaded. Good. This is exactly what we want to see with our setup, to have a fair comparison. The 2 graphs below show the comparative number of requests processed at the CPU single core and all core (server) level.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/18XOFPOFmKWcIuheu6HWl8/e84fa7ff38c6c3f39115b60882a7c106/16.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/rwWBZrTmfJvIs7Em9aCXT/19945cb240e37ca3ba61853b3e72bf5b/17.png" />
            
            </figure><p>We see that AMD does on average about 23% more requests. That's really good! We talked a lot about bringing more muscle in the <a href="/a-tour-inside-cloudflares-g9-servers/">Gen 9 blog</a>. We have the same number of cores, yet AMD does more work, and does it with less power. Just by looking at the specs for number of cores and TDP in the beginning, it's really nice to see that AMD also delivers significantly more performance with better power efficiency.</p><p>But as we mentioned earlier, TDP isn’t a standardized spec across manufacturers so let’s look at real power usage below. Measuring server power consumption along with requests per second (RPS) yields the graph below:</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3DnPzngVCU8da71wGJUleo/b132d4256abe8c60809cf7b2c6d27ea4/18.png" />
            
            </figure><p>Observing our servers request rate over their power consumption, the AMD Gen X server performs 28% better. While we could have expected more out of AMD since its TDP is 25% lower, keep in mind that TDP is very ambiguous. In fact, we saw that AMD actual power draw ran nearly at spec TDP with it's much higher than base frequency; Intel was far from it. Another reason why TDP is becoming a less reliable estimate of power draw. Moreover, CPU is just one component contributing to the overall power of the system. Let’s remind that Intel CPUs are integrated in a multi-node system as described in the <a href="/a-tour-inside-cloudflares-g9-servers/">Gen 9 blog</a>, while AMD is in a regular 1U form-factor machine. That actually doesn’t favor AMD since multi-node systems are designed for high density capabilities at lower power per node, yet it still outperformed the Intel system on a power per node basis anyway.</p><p>Through the majority of comparisons from the datasheets, test simulations, and live production performance, the 1P AMD EPYC 7642 configuration performed significantly better than the 2P Intel Xeon 6162. We’ve seen in some environments that AMD can do up to 36% better in live production, and we believe we can achieve that consistently with some optimization on both our hardware and software.</p><p>So that's it. AMD wins.</p><p>The additional graphs below show the median and p99 NGINX processing mostly on-CPU time latencies between the two CPUs throughout 24 hours. On average, AMD processes about 25% faster. At p99, it does about 20-50% depending on the time of day.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/Fty1XuK9w4yupvRyHzLmu/0f1e8bc02e8f04d0c33752f6ff67fd98/19.png" />
            
            </figure>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3yWj3MsDnro619KjtJwVAW/0868d32c8aa3f5c594b8e660e608eb6c/20.png" />
            
            </figure>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>Hardware and Performance engineers at Cloudflare do significant research and testing to figure out the best server configuration for our customers. Solving big problems like this is why <a href="https://www.fastcompany.com/best-workplaces-for-innovators/2019">we love working here</a>, and we're also helping to solve yours with our services like <a href="/introducing-cloudflare-workers/">serverless</a> edge compute and the array of security solutions such as <a href="/magic-transit-network-functions/">Magic Transit</a>, <a href="/argo-tunnel/">Argo Tunnel</a>, and <a href="/unmetered-mitigation/">DDoS protection</a>. All of our servers on the Cloudflare Network are designed to make our products work reliably, and we strive to make each new generation of our server design better than its predecessor. We believe the AMD EPYC 7642 is the answer for our Gen X's processor question.</p><p>With <a href="https://developers.cloudflare.com/workers/">Cloudflare Workers</a>, developers have enjoyed deploying their applications to our <a href="/tag/cloudflare-network/">Network</a>, which is ever expanding across the globe. We’ve been proud to empower our customers by letting them focus on writing their code while we are managing the security and reliability in the cloud. We are now even more excited to say that their work will be deployed on our Gen X servers powered by 2nd Gen AMD EPYC processors.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6yI4yio6UovXiaJi79a78l/d248e04fd2b5c98c68b7312af953c54f/21.jpg" />
            
            </figure><p>Expanding Rome to a data center near you</p><p>Thanks to AMD, using the EPYC 7642 allows us to increase our capacity and expand into more cities easier. Rome wasn’t built in one day, but it will be <a href="/scaling-the-cloudflare-global/">very close to many of you</a>.</p><p>In the last couple of years, we've been experimenting with many Intel and AMD x86 chips along with ARM CPUs. We look forward to having these CPU manufacturers partner with us for future generations so that together we can help build a better Internet.</p> ]]></content:encoded>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Cloudflare Network]]></category>
            <category><![CDATA[Data Center]]></category>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[Partners]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <guid isPermaLink="false">7dSLKQwG5XrggG5HDcZm1x</guid>
            <dc:creator>Rob Dinh</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare’s Gen X: 
Servers for an Accelerated Future]]></title>
            <link>https://blog.cloudflare.com/cloudflares-gen-x-servers-for-an-accelerated-future/</link>
            <pubDate>Mon, 24 Feb 2020 13:00:00 GMT</pubDate>
            <description><![CDATA[ We designed and built Cloudflare’s network to be able to grow capacity quickly and inexpensively; to allow every server, in every city, to run every service; and to allow us to shift customers and traffic across our network efficiently. ]]></description>
            <content:encoded><![CDATA[ <p></p><blockquote><p><i>“Every server can run every service.”</i></p></blockquote><p>We designed and built Cloudflare’s network to be able to grow capacity quickly and inexpensively; to allow every server, in every city, to run every service; and to allow us to shift customers and traffic across our network efficiently. We deploy standard, commodity hardware, and our product developers and customers do not need to worry about the underlying servers. Our software automatically manages the deployment and execution of our developers’ code and our customers’ code across our network. Since we manage the execution and prioritization of code running across our network, we are both able to optimize the performance of our highest tier customers and effectively leverage idle capacity across our network.</p><p>An alternative approach might have been to run several fragmented networks with specialized servers designed to run specific features, such as the <a href="https://www.cloudflare.com/waf/">Firewall</a>, <a href="https://www.cloudflare.com/ddos/">DDoS protection</a> or <a href="https://workers.cloudflare.com/">Workers</a>. However, we believe that approach would have resulted in wasted idle resources and given us less flexibility to build new software or adopt the newest available hardware. And a single optimization target means we can provide security and performance at the same time.</p><p>We use Anycast to route a web request to the nearest Cloudflare data center (from among <a href="https://www.cloudflare.com/network/">200 cities</a>), improving performance and maximizing the surface area to fight attacks.</p><p>Once a datacenter is selected, we use Unimog, Cloudflare’s custom load balancing system, to dynamically balance requests across diverse generations of servers. We load balance at different layers: between cities, between physical deployments located across a city, between external Internet ports, between internal cables, between servers, and even between logical CPU threads within a server.</p><p>As demand grows, we can scale out by simply adding new servers, points of presence (PoPs), or cities to the global pool of available resources. If any server component has a hardware failure, it is gracefully de-prioritized or removed from the pool, to be batch repaired by our operations team. This architecture has enabled us to have no dedicated Cloudflare staff at any of the 200 cities, instead relying on help for infrequent physical tasks from the ISPs (or data centers) hosting our equipment.</p>
    <div>
      <h3>Gen X: Intel Not Inside</h3>
      <a href="#gen-x-intel-not-inside">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2cA2rKV0dU3II6avmDY7BS/fba1453ea9bc827e399f57971ce871af/AMD_EPYC-39.jpg" />
            
            </figure><p>We recently turned up our tenth generation of servers, “Gen X”, already deployed across major US cities, and in the process of being shipped worldwide. Compared with our prior server (<a href="/a-tour-inside-cloudflares-g9-servers/">Gen 9</a>), it processes as much as 36% more requests while costing substantially less. Additionally, it enables a ~50% decrease in L3 cache miss rate and up to 50% decrease in NGINX p99 latency, powered by a CPU rated at 25% lower TDP (thermal design power) per core.</p><p>Notably, for the first time, Intel is not inside. We are not using their hardware for any major server components such as the CPU, board, memory, storage, network interface card (or any type of accelerator). Given how critical Intel is to our industry, this would until recently have been unimaginable, and is in contrast with <a href="/a-tour-inside-cloudflares-g9-servers/">prior</a> <a href="/a-tour-inside-cloudflares-latest-generation-servers/">generations</a> which made extensive use of their hardware.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3uCBtfJ5jawcCdsdyipghO/0d99e66b8db30d4c872d2a540cf9072c/AMD2.png" />
            
            </figure><p><i>Intel-based Gen 9 server</i></p><p>This time, AMD is inside.</p><p>We were particularly impressed by the 2nd Gen AMD EPYC processors because they proved to be far more efficient for our customers’ workloads. Since the pendulum of technology leadership swings back and forth between providers, we wouldn’t be surprised if that changes over time. However, we were happy to adapt quickly to the components that made the most sense for us.</p>
    <div>
      <h3>Compute</h3>
      <a href="#compute">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3qvmFWlrsejJpb9NEG6ZqU/d830111b48ee0ed930132e88660063ba/pasted-image-0.png" />
            
            </figure><p>CPU efficiency is very important to our server design. Since we have a compute-heavy workload, our servers are typically limited by the CPU before other components. Cloudflare’s software stack scales quite well with additional cores. So, we care more about core-count and power-efficiency than dimensions such as clock speed.</p><p>We selected the AMD EPYC 7642 processor in a single-socket configuration for Gen X. This CPU has 48-cores (96 threads), a base clock speed of 2.4 GHz, and an L3 cache of 256 MB. While the rated power (225W) may seem high, it is lower than the combined TDP in our Gen 9 servers and we preferred the performance of this CPU over lower power variants. Despite AMD offering a higher core count option with 64-cores, the performance gains for our software stack and usage weren’t compelling enough.</p><p>We have deployed the AMD EPYC 7642 in half a dozen Cloudflare data centers; it is considerably more powerful than a dual-socket pair of <a href="/a-tour-inside-cloudflares-g9-servers/">high-core count Intel processors</a> (Skylake as well as Cascade Lake) we used in the last generation.</p><p>Readers of our blog might remember our excitement around ARM processors. We even ported the entirety of our software stack to run on ARM, just as it does with x86, and have been maintaining that ever since even though it calls for slightly more work for our software engineering teams. We did this leading up to the launch of <a href="/arm-takes-wing/">Qualcomm’s Centriq server CPU</a>, which eventually got shuttered. While none of the off-the-shelf ARM CPUs available this moment are interesting to us, we remain optimistic about high core count offerings launching in 2020 and beyond, and look forward to a day when our servers are a mix of x86 (Intel and AMD) and ARM.</p><p>We aim to replace servers when the efficiency gains enabled by new equipment outweigh their cost.</p><p>The performance we’ve seen from the AMD EPYC 7642 processor has encouraged us to accelerate replacement of multiple generations of Intel-based servers.</p><p>Compute is our largest investment in a server. Our heaviest workloads, from the Firewall to <a href="/cloud-computing-without-containers/">Workers</a> (our serverless offering), often require more compute than other server resources. Also, the average size in kilobytes of a web request across our network tends to be small, influenced in part by the relative popularity of APIs and mobile applications. Our approach to server design is very different than traditional <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/">content delivery networks</a> engineered to deliver large object video libraries, for whom servers focused on storage might make more sense, and re-architecting to offer serverless is prohibitively capital intensive.</p><p>Our Gen X server is intentionally designed with an “empty” PCIe slot for a potential add on card, if it can perform some functions more efficiently than the primary CPU. Would that be a GPU, FPGA, SmartNIC, custom ASIC, TPU or something else? We’re intrigued to explore the possibilities.</p><p>In accompanying blog posts over the next few days, our hardware engineers will describe how AMD 7642 performed against the benchmarks we care about. We are thankful for their hard work.</p>
    <div>
      <h2>Memory, Storage &amp; Network</h2>
      <a href="#memory-storage-network">
        
      </a>
    </div>
    <p>Since we are typically limited by CPU, Gen X represented an opportunity to grow components such as RAM and SSD more slowly than compute.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/26Sxt3ggFdoQ0GzKF3EGss/368a3e0d940daae20b6feeb5a3e4fba2/AMD_EPYC-13.jpg" />
            
            </figure><p>For memory, we continued to use 256GB of RAM, as in our prior generation, but rated higher at 2933MHz. For storage, we continue to have ~3TB, but moved to 3x1TB form factor using NVME flash (instead of SATA) with increased available IOPS and higher endurance, which enables <a href="https://www.usenix.org/conference/vault20/presentation/korchagin">full disk encryption using LUKS without penalty</a>. For the network card, we continue to use Mellanox 2x25G NIC.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5ss6eIWw5bu2PmPfE000Wi/131a3644d28be05b4d00a113bc9565ea/AMD_EPYC-5.jpg" />
            
            </figure><p>We moved from our multi-node chassis back to a simple 1U form factor, designed to be lighter and less error prone during operational work at the data center. We also added multiple new ODM partners to diversify how we manufacture our equipment and to take advantage of additional global warehousing.</p>
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7idOzt8cy7gwxh6oeOSpI5/302f275f840d028cbd2b0bb6a1a351cc/AMD_EPYC-7.jpg" />
            
            </figure>
    <div>
      <h3>Network Expansion</h3>
      <a href="#network-expansion">
        
      </a>
    </div>
    
            <figure>
            
            <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7kEiqTtyNgUY66Rh34MpuG/42da64e77acad6084872058580ed2d89/AMD_EPYC-35.jpg" />
            
            </figure><p>Our newest generation of servers give us the flexibility to continue to build out our network even closer to every user on Earth. We’re proud of the hard work from across engineering teams on Gen X, and are grateful for the support of our partners. Be on the lookout for more blogs about these servers in the coming days.</p> ]]></content:encoded>
            <category><![CDATA[Hardware]]></category>
            <category><![CDATA[Cloudflare Network]]></category>
            <category><![CDATA[Data Center]]></category>
            <category><![CDATA[Partners]]></category>
            <category><![CDATA[Speed & Reliability]]></category>
            <category><![CDATA[EPYC]]></category>
            <category><![CDATA[AMD]]></category>
            <guid isPermaLink="false">5NWs1t95pGWDeOMVAkbQ4S</guid>
            <dc:creator>Nitin Rao</dc:creator>
            <dc:creator>John Graham-Cumming</dc:creator>
        </item>
    </channel>
</rss>