<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Leon Brocard</title>
    <description>The latest articles on Forem by Leon Brocard (@acme).</description>
    <link>https://forem.com/acme</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1053902%2Fb6eddc38-5620-4c8d-820e-d9c8ba57788e.png</url>
      <title>Forem: Leon Brocard</title>
      <link>https://forem.com/acme</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/acme"/>
    <language>en</language>
    <item>
      <title>Profiling Fastly Compute applications</title>
      <dc:creator>Leon Brocard</dc:creator>
      <pubDate>Thu, 23 Jan 2025 10:06:47 +0000</pubDate>
      <link>https://forem.com/acme/profiling-fastly-compute-applications-35ip</link>
      <guid>https://forem.com/acme/profiling-fastly-compute-applications-35ip</guid>
      <description>&lt;p&gt;As a member of the Fastly Solutions Engineering team, I care deeply about web performance. I work with our customers to configure their services and use Fastly features to make their web applications fast. While I generally use browser developer tools to investigate performance, how can we investigate performance on Fastly Compute, our serverless platform that lets you easily build the best experiences for your users?&lt;/p&gt;

&lt;p&gt;Fastly Compute is an advanced edge computing system that runs your code, in your favorite language, on our global edge network. Security and portability are provided by compiling your code to WebAssembly (Wasm), a portable compilation target for programming languages. We run your code using Wasmtime, a fast and secure runtime for WebAssembly from the Bytecode Alliance project.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Setting up the environment&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s step through an example. Fastly Compute provides language tooling for JavaScript, Go, and Rust. I wrote a Rust application using the Fastly Rust SDK that generates a picture of a part of the Julia set, a mathematical function that can be quite pretty:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4s1qa37sahg1mn8wiy4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4s1qa37sahg1mn8wiy4.png" alt="A pretty fractal" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To run this on Fastly Compute, the Fastly CLI invokes the Rust compiler to compile the Rust code to the Wasm platform rather than my laptop’s platform. To run this on your laptop, use &lt;/p&gt;

&lt;p&gt;&lt;code&gt;fastly compute serve&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Generating these pretty images takes a few hundred milliseconds — that seems a little slow. How can I find out what is the slow part? The engineer’s tool of choice is a profiler. I could separate the Rust code out and use Rust’s standard profiling tools. However, the performance on my laptop’s platform might not represent the performance on Wasm.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Capturing performance data&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;It’s best to profile applications in a way that is as similar to production as possible, so we’ll use the cross-platform Wasmtime guest profiler. The “guest” part of the name indicates that it is profiles inside the Wasm process. To serve and profile from your laptop, use &lt;/p&gt;

&lt;p&gt;&lt;code&gt;fastly compute serve --profile-guest&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Every 50 microseconds Compute notes down the function call stack (that is, which function are we in and which function called it) and then after the HTTP response is sent, it writes the captured profile to a file. The file is in a format supported by the Firefox profiler. Captured profiles can be viewed by dragging and dropping them onto &lt;a href="https://profiler.firefox.com/" rel="noopener noreferrer"&gt;https://profiler.firefox.com/&lt;/a&gt;, which processes the profiles using your browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Analyzing profiler output&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The initial view from the Firefox profiler shows a number of tabs and the call tree, which is split up by function names. Some of these are from the Rust runtime, from my application, and from libraries that my application uses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcx1rwcez0mp1y6lixynw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcx1rwcez0mp1y6lixynw.png" alt="Profiler call tree" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The guest profiler took 7,922 samples. The entry point of my application is the highlighted &lt;code&gt;ecp_example_fractal::main&lt;/code&gt; function and 100% of the samples had it in the function call stack, as indicated by the Total (samples) column. However, the &lt;code&gt;Self&lt;/code&gt; column indicates that none of the samples were in the &lt;code&gt;main&lt;/code&gt; function itself: all of the work is being done in other functions.&lt;/p&gt;

&lt;p&gt;The key parts of the application are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;image::buffer_::ImageBuffer::from_fn()&lt;/code&gt;, a Rust image library, which runs a function for every pixel. The function took 345 sampling intervals, while the call stack originating from this function took 3900 sampling intervals.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;colorous::gradient::Gradient::eval_rational&lt;/code&gt;, a Rust colour scheme library, which assigns a nice colour to each pixel
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;brotli::enc::writer::CompressorWriterCustomIo&lt;/code&gt;, a Rust library to compress the response using Brotli
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;image::dynimage::DynamicImage::write_to&lt;/code&gt;, the same Rust image library which encodes the image using the PNG format.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another way of visualizing the Self count is the flame graph tab:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibforbsng5re9rl60b5m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibforbsng5re9rl60b5m.png" alt="Profiler flame graph" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a good way of seeing the relative amount of time being spent by these functions. By seeing what stacks are above the main function, we can see that the application spends most of its time generating the image (the image:: stacks), picking the pretty colours (the colorous:: stacks) and compressing the image as Brotli (the brotli:: stacks).&lt;/p&gt;

&lt;p&gt;One more way of visualizing what functions are on the call stack is the stack chart tab:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpbn95ptj216xultljcze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpbn95ptj216xultljcze.png" alt="Profile stack chart" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By seeing what stacks are below the main function, we can see that half the time, the call stack has functions for generating the image and half the time is compressing the image as Brotli.&lt;/p&gt;

&lt;p&gt;Wait a second: I’m already compressing this image in the image-specific PNG format, so there is no point in compressing it again using general-purpose Brotli! Compressing assets is best practice, but double compression is a waste of time. I must have copied and pasted that bit of code from another project. If I remove the Brotli compression then the application generates the same images but runs three times faster. This updated flame graph shows that the application now spends most of its time generating the image and the rest encoding the image: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnvgb5ri0ysusiwv0ha4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnvgb5ri0ysusiwv0ha4.png" alt="After flame graph" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Use the guest profiler via the &lt;code&gt;fastly compute serve --profile-guest&lt;/code&gt; command to optimize your Compute applications and make them even faster.&lt;/p&gt;

&lt;p&gt;If you’re just getting started with Fastly Compute, check out our learning resources. If you’re new to Fastly, creating an account is free and easy. Sign up to get started instantly!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Demystifying the HTTP Host header</title>
      <dc:creator>Leon Brocard</dc:creator>
      <pubDate>Wed, 28 Jun 2023 12:43:35 +0000</pubDate>
      <link>https://forem.com/fastly/demystifying-the-http-host-header-dg8</link>
      <guid>https://forem.com/fastly/demystifying-the-http-host-header-dg8</guid>
      <description>&lt;p&gt;The HTTP host header is a small, important part of our modern web. It is used more than you might think in Fastly. In this post, we’ll dig into the history of the header and show how crucial it is to serving content stored in an object store through Fastly.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it started: single domain hosting
&lt;/h2&gt;

&lt;p&gt;When the web was growing up, some early assumptions worked well. As we’ll see, some of our assumptions had to change.&lt;/p&gt;

&lt;p&gt;Let’s work through an example. It’s 1996. Gina G’s “Ooh Aah... Just a Little Bit” is playing on the radio. Real physical computers, which were probably beige, ran web servers on port 80. Thus, each server could only serve content for a single domain. You open up Netscape Navigator and browse to &lt;a href="http://www.example.com"&gt;www.example.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The browser resolves &lt;a href="//www.example.com"&gt;www.example.com&lt;/a&gt;, connects to port 80 of the server, and sends the few characters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET / HTTP/1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The web server listens on port 80, receives the request and sends back an HTML response. Success!&lt;/p&gt;

&lt;h2&gt;
  
  
  The web took off: virtual hosting
&lt;/h2&gt;

&lt;p&gt;As the global hypertext dream came true in practice, there was a lot of success. So much success that the limitation of only one domain per server became a problem. The &lt;code&gt;Host&lt;/code&gt; request header is introduced.&lt;/p&gt;

&lt;p&gt;Let’s work through an example. It’s 1997. The Cardigan’s “Lovefool” is playing on the radio. A real computer, which is now a sleek black, runs a pretend computer which in turn runs a web server. You open up Netscape Communicator and browse to &lt;a href="http://www.example.com"&gt;www.example.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The browser resolves &lt;a href="http://www.example.com"&gt;www.example.com&lt;/a&gt;, connects to port 80 of the server and sends the few characters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET / HTTP/1.1
Host: www.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The web server listens on port 80, receives the request, pays attention to the Host request header and sends back an appropriate HTML response.&lt;/p&gt;

&lt;p&gt;The effect of this is that the web server can use the Host header to direct your request to one of many websites hosted on the same machine. It's no longer necessary to have one IP address per website. And thank goodness, because we didn't have anywhere near enough IP addresses for that!&lt;/p&gt;

&lt;h2&gt;
  
  
  TLS
&lt;/h2&gt;

&lt;p&gt;As the web grew, ecommerce started taking off. Sending credit card numbers and other sensitive data in plain text across the network became a problem. We needed to encrypt content in transit across the web. The Secure Sockets Layer (SSL) provided secure communications between web browsers and web servers and led to the Transport Layer Security (TLS) protocol.&lt;/p&gt;

&lt;p&gt;It’s 1999. Britney Spears’ “...Baby One More Time” is playing on the radio and our web server is now run by something of indeterminate colour by a mass hosting company. You open up Internet Explorer 5 and browse to &lt;a href="//www.example.com"&gt;www.example.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before the browser and server get to speak HTTP, they first participate in a  TLS conversation. The browser connects to port 443. As part of the TLS Server Name Indication extension, the browser indicates the name of the server it is contacting. The secure web server directs your request to one of many web servers.&lt;/p&gt;

&lt;p&gt;After TLS is negotiated, the HTTP conversation continues over the secure connection. Sensitive information is no longer carried in plain text across the network and the Dot-com boom happens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Today
&lt;/h2&gt;

&lt;p&gt;It’s today. As we speak, hypertext spans the globe and we now listen to radio using HTTP. Every request sends a &lt;code&gt;Host&lt;/code&gt; request header (for HTTP/1.1 requests) or an &lt;code&gt;:authority&lt;/code&gt; pseudo-header (for HTTP/2 and HTTP/3 requests).&lt;/p&gt;

&lt;p&gt;Fastly’s powerful edge cloud platform enables developers to build exceptional websites and apps. We sit in between our customers’ customers and our customers' servers (origins). It’s common to modify the request &lt;code&gt;Host&lt;/code&gt; header in the Fastly layer as your origins might have a different naming convention to your public domains.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="http://www.example.com"&gt;www.example.com&lt;/a&gt; might be the public domain, whereas the real service might run on production.example.com.&lt;/p&gt;

&lt;p&gt;This simple case is easy to configure. For a Fastly Delivery or Compute service, you can &lt;a href="https://docs.fastly.com/en/guides/specifying-an-override-host#overriding-a-host-at-the-origin-level"&gt;specify an override host on the origin&lt;/a&gt;. For a Fastly Compute service, use &lt;code&gt;override_host&lt;/code&gt; in &lt;code&gt;&lt;a href="https://developer.fastly.com/reference/compute/fastly-toml/#backends"&gt;fastly.toml &lt;/a&gt;&lt;/code&gt;for development. For production, &lt;a href="https://developer.fastly.com/learning/tools/cli/"&gt;the Fastly CLI &lt;/a&gt;sets the override by default when adding a backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Object stores
&lt;/h2&gt;

&lt;p&gt;While running physical servers and software used to be the only way to go, many of our customers use on-demand central cloud computing platforms. In particular, object stores such as Amazon S3 and Google Cloud Storage are great for storing images, assets and even static websites. Having Fastly in front of these provides supreme global performance.&lt;/p&gt;

&lt;p&gt;These object stores live on different domains so we need to modify the &lt;code&gt;Host&lt;/code&gt; header as the request travels through Fastly.&lt;/p&gt;

&lt;p&gt;For Amazon S3, the simplest way to access a bucket is to use &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-bucket-intro.html"&gt;Virtual-hosted–style access&lt;/a&gt;. The override host name should be in the format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;BUCKET NAME&amp;gt;.s3.&amp;lt;REGION-CODE&amp;gt;.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Google Cloud Storage, the simplest way to access a bucket is similar. The override host name should be in the format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;BUCKET NAME&amp;gt;.storage.googleapis.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have a lot of useful information about these settings on &lt;a href="https://developer.fastly.com/learning/integrations/backends/#overriding-the-host-header"&gt;Overriding the Host header&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;As before, for a Fastly Delivery service, you can specify an override host on the origin. For a Fastly Compute service, use &lt;code&gt;override_host&lt;/code&gt; in &lt;a href="https://developer.fastly.com/reference/compute/fastly-toml/#backends"&gt;fastly.toml&lt;/a&gt; for development. For production, &lt;a href="https://developer.fastly.com/learning/tools/cli/"&gt;the Fastly CLI &lt;/a&gt;sets the override by default when adding a backend.&lt;/p&gt;

&lt;p&gt;Don’t forget to secure access to your buckets using a &lt;a href="https://docs.fastly.com/en/guides/amazon-s3#using-an-amazon-s3-private-bucket"&gt;signed AWS authorization header&lt;/a&gt; or a &lt;a href="https://docs.fastly.com/en/guides/google-cloud-storage#using-gcs-with-private-objects"&gt;Google Cloud HMAC authentication&lt;/a&gt;. Enable &lt;a href="https://developer.fastly.com/learning/concepts/shielding/"&gt;shielding&lt;/a&gt; to reduce latency and the number of requests made to the object store.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We’ve traveled through time and demystified the HTTP Host header, a small part of the large web.&lt;/p&gt;

</description>
      <category>http</category>
      <category>web</category>
    </item>
  </channel>
</rss>
