00:00:08.290
I am happy to announce the second speaker, Luca Guidi. He is the author of Hanami and a core team member of dry-rb.
00:00:12.190
Luca has made a significant impact in the open-source community and somehow manages to build amazing projects without working on weekends. At least a year ago, he wrote about taking time to rest during workdays and contributing to open source.
00:00:21.730
He has a wonderful blog at lucaability.com, where I learned that he's exploring techno music and meditating. He uses OKRs to track both his professional and personal goals.
00:00:29.619
By the way, I'm a fan of OKRs as well. I utilize this approach for my personal and professional development.
00:00:36.010
Luca has spoken at many conferences, and this year, he mentioned meeting Matt for the first time this February in Paris after years of collaboration.
00:00:48.070
His journey with Ruby and Hanami started back in 2016 when we had a meetup dedicated to Hanami, and it was a memorable event.
00:00:57.640
Recently, the Hanami team announced Hanami API, a minimal, extremely fast framework. Let's take a closer look at what's inside together with Luca.
00:01:09.400
Luca, it's your turn. I had to say this was the best presentation ever. Thank you, Anna. Thank you for the kind words, and thank you everyone for having me.
00:01:18.050
I want to talk about Hanami API, which is a small micro framework that I would like to introduce today. First things first, my name is Luca Guidi, and as mentioned earlier, you can find my website and GitHub links in my bio.
00:01:40.510
I work remotely from Rome as a back-end architect at Toptal. Before I start, I want to explain why I created Hanami API.
00:01:49.999
There are basically two main reasons. The first one is that we are in the process of rewriting most parts of Hanami, including the router. The old version 1.0 was based on an outdated mounting library, so I had to rewrite it.
00:02:08.600
The first alpha version of the new router was released over a year ago, and after comparing benchmarks, Jeremy helped me realize how poor the performance was on that version.
00:02:29.540
As a result, I did another rewrite, which yielded significantly better performance. Thanks to Jeremy for helping me pinpoint and resolve those performance issues.
00:02:40.330
I realized this wouldn't just benefit me; the community at large could also benefit from improved performance in Hanami and other open-source projects like dry and rom.
00:03:00.059
I want to make something that the community can reuse rather than just something I add to my own garden.
00:03:17.659
In general, when you look into a router, you typically need to build something that is low-level. So, I decided to wrap it into a DSL, allowing people to create a simple product: you install the gem, write a file, and have a tiny, focused HTTP endpoint.
00:03:35.350
The second reason for creating Hanami API relates to improving the adoption of Hanami. I understand that Hanami is a large framework, and there is a business risk involved for companies when considering a switch.
00:03:51.840
Considering how popular Rails is in our community, if we can offer something with very low friction to adopt—like a single gem for a small HTTP endpoint or service—then companies might be more willing to explore Hanami.
00:04:09.190
This reduced risk allows them to understand the philosophy behind Hanami without fully committing initially. From there, they can explore other aspects of it or related libraries that integrate well.
00:04:27.570
Those are the two main reasons why I decided to create this gem DSL, ensuring developers have something that is low-risk and ready to go.
00:04:45.541
Now, let’s have a look at the syntax, which is described here in this slide. You begin by including the gem, and then you create a superclass from which you inherit.
00:05:05.610
You define routes, and there are two ways to define them. The first option is the classic Hanami style, where you specify the HTTP verb, the relative path, and the action.
00:05:23.080
The new addition inspired by Sinatra allows using a block syntax to handle routes. You can also mount any rack application, so for requests starting with a certain path, they will be routed to that application.
00:05:43.070
Another interesting feature is that you can scope routes, which acts as a prefix, allowing you to group and organize your routes without repetition.
00:06:01.590
You can also scope rack middleware, meaning only requests targeting the API will use specific middlewares while others will not.
00:06:20.919
This scoping mechanism is similar to variable visibility in programming, allowing for more organized and controlled use of middlewares and routes.
00:06:41.290
Moreover, the last line of the code reflects that it behaves like any other Hanami gem. You create objects, handle responses, and manage requests as needed.
00:07:00.540
The features of this micro-framework include obtaining parameters from requests, managing response statuses, headers, and body.
00:07:18.410
You have control over the request execution flow for redirection, rendering content, and handling mounted applications.
00:07:37.870
I wanted to keep it minimal and not bloat the framework with unnecessary features, providing developers with only what they need to get started.
00:07:55.880
Now let's discuss performance, as this rewrite was oriented towards improving it. I utilized the Jeremy benchmark tool to measure performance.
00:08:15.410
For those who are not familiar, Jeremy wrote a benchmark tool called '10k', which compares Ruby frameworks and generates apps with 10,000 routes.
00:08:32.290
It measures various metrics, including memory consumption and request handling performance.
00:08:48.790
The first important metric is memory usage, where lower memory consumption indicates a more lightweight framework.
00:09:07.839
According to the benchmarks, Hanami API ranks second for memory usage among various frameworks.
00:09:21.460
For fulfilling requests, the benchmark executes 20,000 requests targeting the last route to measure the worst-case scenario.
00:09:37.140
We noted that to complete benchmarks, frameworks like Sinatra took far longer under certain conditions, indicating outliers in the data.
00:09:54.890
Zooming in on the performance comparisons confirms that Hanami API delivers excellent results, confirming its competitiveness.
00:10:12.830
The bottom line is that while Rails is often preferred for larger web apps and Sinatra for small endpoints, there is a growing ecosystem of highly performant HTTP frameworks.
00:10:31.059
This push for performance demonstrates that developers are seeking alternatives beyond the conventional options.
00:10:48.290
Now, let's delve into the implementation details and some performance improvements I’ve focused on.
00:11:04.330
Instead of going through the minutiae of code, let me explain it with a visual analogy. Many people are familiar with the game Guess Who.
00:11:21.669
In the game, you have 24 characters, and you need to identify the correct one. If you look at them sequentially, that represents the worst-case scenario for searching.
00:11:38.290
This demonstrates inefficiency; in contrast to a manual search, approaching it with direct questions improves efficiency.
00:11:52.820
The goal is to limit the amount of data being scanned, which leads to faster searches.
00:12:09.460
In programming terms, the ideal scenario would be constant-time access, where the data structure allows immediate access to the target value.
00:12:23.640
To achieve this, I revised the data structure used to store routes, transitioning from a list to a more efficient structure.
00:12:37.830
Previously, to find the last of 1,000 routes, I had to scan through all of them. By using a tree structure, the lookup time significantly decreases.
00:13:01.840
This change led to improved performance, further validated by benchmarking.
00:13:15.050
Additionally, I partitioned the tree rather than using a single large data set. This led to faster lookups by reducing the amount of data being processed.
00:13:31.140
The second improvement addresses the difference between fixed and variable paths. Fixed paths, such as '/dashboard', are quicker to resolve than paths with variable parameters.
00:13:44.230
Variable paths require additional computation, making them less performant since they involve matching against conditions at runtime.
00:14:06.410
Using a partitioning strategy helps route requests efficiently, similar to organizing a bookshelf by genre.
00:14:23.170
This view of maintaining smaller trees within those partitions allows for faster searches.
00:14:37.370
Ultimately, these improvements lead to the conclusion that utilizing optimized data structures can have a significant positive impact on HTTP routing performance.
00:14:53.560
When looking at the benchmarks, we observe substantial reductions in execution time and memory usage post-revision.
00:15:13.560
In conclusion, I want to address a common question: is Ruby still worth learning in 2023?
00:15:26.890
My answer is that the present state of Ruby is bright, and I am excited about its future. Thank you all for your time!
00:15:45.590
Thank you!
00:15:51.890
Walk down, it's your turn to ask questions.
00:15:54.890
There is one topic I’d like to discuss. Thank you for an incredible talk.
00:16:10.890
The first question is about the comparison between Hanami and Roda. In what use cases would you recommend using Hanami, and in which situations would Roda be a better fit?
00:16:30.890
In my opinion, both frameworks serve similar markets, although Roda might offer more features that I have intentionally excluded.
00:16:50.890
My suggestion is not to take my word alone but to install both gems, read their documentation, and evaluate which one aligns better with your use case.
00:17:10.890
The next question is about Hanami API and its use in practical applications. If someone only needs a single endpoint, what would you recommend?
00:17:30.890
For just one endpoint, you might think about creating something trivial, but consider the built-in facilities available in Hanami API.
00:17:50.890
Using Hanami gives you utility out of the box, with features for params handling, JSON parsing, etc., making it more efficient.
00:18:10.890
Additionally, you can leverage the advanced features from Hanami actions, saving development overhead and benefiting from a proven library.
00:18:30.890
It’s advisable to utilize an established framework to avoid reinventing the wheel, especially when the framework already has proven functionality.
00:18:50.890
Thank you for your interesting presentation!