šŸ‘ØšŸ»ā€šŸ’» Thanks for reading! This blog has been archived and won't have content updates. You can follow my latest work at trujillo.io.
CHROMABITS

Eduardo Trujillo
3 minutes

Iā€™ve recently been dealing with slow endpoints on a PHP application written using Laravel. Normally, I would use XDebug, which is the go-to PHP debugging tool, capture performance information of the affected code paths, and load the results into a tool like PHPStorm, which has a built-in UI for analyzing the captures. This seemed a bit tedious to me due to having to manually open each file, so I decided to go and look for other options, and that led me to XHProf, which is a tool specific for profiling built by Facebook. It looked promising so I decided to give it a try.

Like XDebug, XHProf needs its own extension to work. Luckily, the extension is built-in on HHVM, so I didnā€™t had to compile anything (well, besides HHVM itself) to get started.

After capturing a couple of runs, I was able to identify the bottlenecks on the endpoints, thanks to the callgraphs, which are rendered by the XHProf UI and point out in red the functions that consumed most of the time during the request or session.

The UI is not very visually appealing, but it definitely gets the job done. I was able to quickly lookup runs which definitely takes less time than loading individual XDebug captures into PHPStorm.

Additionally, being able to enable the profiling programatically reduces the amount of noise when you want to focus on a specific section of your code.

Below, I include a quick How-To on using XHProf within Laravel applications:

Getting started

Install the XHProf package using Composer:

NOTE: There are many XHProf packages out there. Some are maintained, others are abandoned. The most up-to-date seems to be phacility/xhprof, however it does not include a composer.json file. lox/xhprof is a fork of that same repository, but it also includes a composer.json file.

composer require lox/xhprof

Then add a middleware class to your project that enables profiling while a request is being handled. Its also possible to enable XHProf earlier in the application lifecycle, if you are interested in profiling the framework booting process.

Hereā€™s an example of said middleware:

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use XHProfRuns_Default;

/**
 * Class XhprofMiddleware.
 *
 * XHProf is a useful profiling tool built by Facebook. This middleware allows
 * developers to profile specific requests by appending `xhprof=true` to any
 * query.
 *
 * Results will be stored on `/tmp` and can be visualized using the XHProf UI.
 *
 * @author Eduardo Trujillo <ed@chromabits.com>
 * @package App\Http\Middleware
 */
class XhprofMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param Request $request
     * @param Closure $next
     *
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // We will only profile requests if the proper flag is set on the query
        // of the request. You may further customize this to be disabled on
        // production releases of your application.
        if ($request->query->get('xhprof') !== 'true') {
            return $next($request);
        }

        xhprof_enable();

        $result = $next($request);

        $xhprofData = xhprof_disable();
        $xhprofRuns = new XHProfRuns_Default('/tmp');

        $runId = $xhprofRuns->save_run($xhprofData, 'xhprof_laravel');

        // We will attach the XHProf run ID as part of the response header.
        // This is a lot better than modifying the actual response body.
        $result->headers->set('X-Xhprof-Run-Id', $runId);

        return $result;
    }
}

Then, load the middleware into the application by adding it to your Kernel.php file.

Capturing runs and visualizing

The middleware above is setup to enable profiling whenever xhprof=true is set on the request query. This means that setting this flag on any request to your application should trigger profiing for that request.

All runs will be stored on /tmp by default. To help with looking up results, the middleware will also add a HTTP header to the response with the ID of the run.

XHProf UI while examining a capture

Results can be inspected by hand, however it is generally more useful to use the built-in ā€œUIā€ which is capable of generating callgraphs and showing the timing of all functions called.

With HHVM, a web server for the UI can be launched from the root of a project:

hhvm -m server -d hhvm.server.type=proxygen \
 -d hhvm.server.source_root=$(pwd)/vendor/lox/xhprof/xhprof_html \
 -d hhvm.server.port=8001 \
 -d hhvm.server.default_document=index.php

Eduardo Trujillo
4 minutes

For the past few months, Iā€™ve been using Fedora as my main OS on my laptop, a 2014-ish MacBook Pro. OSX is not bad, but it does not have native support for things like Docker.

I still have my OSX partition setup in case I need something that I canā€™t do on Linux (like updating the firmware or enabling/disabling the startup sound).

These are some of notes Iā€™ve collected along the way:

Writing the ISO to a USB stick

If you are installing Fedora on a MBP, you are probably running OSX initially. How do you write the ISO image into a USB stick and make it bootable?

Iā€™ve found that Ubuntuā€™s guide on the topic is the easiest one to follow and works with the Fedora image too.

Hereā€™s a quick summary:

hdiutil convert -format UDRW -o ~/path/to/target.img ~/path/to/fedora.iso
diskutil unmountDisk /dev/diskN
sudo dd if=~/path/to/target.img of=/dev/diskN bs=1m
diskutil eject /dev/diskN

See below on how to boot into the live image.

Dual-booting is possible without any additional software

Some guides for installing Linux on MacBooks point you to installing UEFI software like rEFInd. I would consider this an optional step since the laptopā€™s firmware has an OS selection screen built-in.

For both, booting the live image and picking which OS to boot, all you have to do is hold down the alt key while the laptop is booting and pick what you want to boot. If you formatted the USB stick correctly, Fedora should be an option.

TIP: You can setup a firmware password to protect the OS selection screen (just like it would on a PC).

Going online (wireless-ly)

Like on other laptops on Linux, the wireless card needs some drivers before you can use it.

On Fedora, the MacBook cardā€™s driver is available under the akmod-wl package. However, you will first need to enable the RPM fusion repositories (both free and non-free).

The easiest way to do this is to use a Thunderbolt Ethernet adapter or to tether your phone. Otherwise, you will porbably need to copy a couple of RPMs.

TIP: On some cases, the kernel-headers package will have a different version from the current kernel in your system. This will prevent akmod from compiling the module. You should run dnf upgrade if that happens.

After restarting, the module should be compiled and you should be able to connect to an access point.

Turning off that red light

After booting Fedora (or any other Linux distribution), you will most likely notice that there is an odd red light coming out your laptopā€™s headphone jack. This is normal. The headphone jack on MacBooks has a S/PDIF port built-in.

The reason why the light is on while using Linux is that, by default, Linux does not enable power saving mode on the audio card. However, its very easy to enable it:

# As root:
echo 1 > /sys/module/snd_hda_intel/parameters/power_save

Additional power saving toggles can be found using powertop.

Go to sleep

For some reason, something keeps waking up the laptop after you press the power button or close the lid. Having you laptop turn on inside your bag is not fun!

The workaround seems to disable a couple of wakeup triggers:

# As root:
echo LID0 > /proc/acpi/wakeup
echo XHC1 > /proc/acpi/wakeup

The side effect being that your laptop wonā€™t turn on automatically when you open the lid, however, you can now safely put it in your bag.

The webcam

The only piece of hardware that youā€™ll find that does not work on Linux is the webcam. This is due to the fact that the drivers for it are not open source.

There is, however, an ongoing effort to build/reverse-engineer a driver for Linux.

As a systemd unit

I wrote a small unit file that will fix the red light and wake up issues at boot time:

[Unit]
Description=Improve MacBook setup

[Service]
Type=oneshot
ExecStart=/bin/bash -c "echo 1 > /sys/module/snd_hda_intel/parameters/power_save && echo LID0 > /proc/acpi/wakeup && echo XHC1 > /proc/acpi/wakeup"

[Install]
WantedBy=multi-user.target

Save this file as /etc/systemd/system/mbp.service and run systemctl daemon-reload && systemctl enable mbp to load the unit on every boot.


Eduardo Trujillo
4 minutes

The last time I wrote a post about my blog was around two years ago. At that type, I was riding on the Node.js hype train, so I was excited to rewrite the engine my blog was running on in JavaScript.

Fast forward to today, and now this blog is just a bunch of statically generated HTML files and images served by an Nginx server.

So what happened?

Side projects. Lots of them.

My blog used to be the go-to hobby project to work on after school. It served as a platform for me to learn about different languages, security practices, and how to structure web applications.

Though, once I got my CS degree, I started working a full-time developer, and, as part of the job, I started learning a lot and writing libraries to make said job easier.

After a while, I had many go-to projects that I could work on during my free time. Working on a project now meant also considering the opportunity cost of not working on other projects, and the blog routinely kept loosing this battle.

However, every now and then, the blog got some attention. Letā€™s take a look:

Timeline:

  • Pre-2014: Create a CMS from scratch in PHP and use it run a blog and a few other sites.
  • 2014: Jump on the node.js hype train and rebuild a simpler CMS in Javascript while keeping compatibility with the original database schema.
  • Late 2014-Early 2015: Port the views to React.js code while also making the server use isomorphic Javascript.
  • 2015: Extract the backend code into a separate Go API, while also building a Kubernetes cluster to run the front-end and backend containers, plus a small Redis instance for API rate-limitting.

Out of all the things I tried, there was one ā€œfeatureā€ that I kept pushing back: A UI to write articles. My blog might have had bleeding-edge JS, an API, and a solid infrastructure, but it still lacked content.

Donā€™t get me wrong; These were really fun to implement and set up, and I learned things that I later applied to other projects. However, the high friction (posting articles over MySQL) kept getting in the way of content, which is kind of the centerpiece.

Given the reduce availability, I decided to knock down the walls obstructing content, and going for something simpler.

Enter: Hakyll

Jekyll is a very popular tool for generating static sites. It is used by GitHub pages and many blogs out there. However, it is not the only one: Thereā€™s Octopress, Hugo, GitBook, and a lot more.

One that caught my eye in particular was Hakyll. It is a very similar tool, written in Haskell, a purely functional language.

Letā€™s also mention that itā€™s 2015, and that thereā€™s another hype train going around. This time its about Functional Programming.

So, I decided ā€œif Iā€™m going to create a statically-generated blog, why not do it in style?ā€œ. I jumped on another train and started writing my new blog using Hakyll.

feelsgoodman.jpg

Hakyll did not disappoint. It is a really fast alternative to Jekyll that also happens to be very extensible using plain Haskell code. This were my favorite bits on working with it:

  • You are not bound to just creating a blog, you can customize the compilation process to create many different kinds of collections and pages.
  • It backed by Pandoc, meaning that it supports reading posts in many file types, and also rendering them in other formats (like PDFs) besides just HTML.
  • Itā€™s a Haskell script that gets compiled into an executable!
  • It does not require you to know too much about functional programming concepts.
Hakyll is simple and fast, but it's speed and extensibility are the killer features.

In less than a week of working with Hakyll, I had a new blog setup with my previous posts, a projects mini-wiki, and a sweet new design. However, this is probably because I already had some experience with Haskell and the Gulp/SCSS combo.

If you want to take a peek under the hood, the code used for generating this blog can be found on my Phabricator instance. Iā€™m hoping to write a follow-up post on some of the custom snippets in it.

By the way:

  • Always keep your posts in a portable format (like Markdown)! It will make it easier to migrate your posts to other blog engines or static site generators.
  • If you are choosing which static site generator to use, make sure it has good support for syntax highlighting.
  • If you are trying out Hakyll, consider using stack instead of just cabal. You can easily setup a Hakyll project by using their template.
  • Support for LaTeX is also a good thing to look for: 1+2āˆ’Ī©=x+y+z21 + 2 - \Omega = x + y + z^2

ā€¦or you can find more in the archives.

CHROMABITS
Copyright Ā© 2015-2021 - Eduardo Trujillo
Except where otherwise noted, content on this site is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) license.
Site generated using Gatsby.