Crystal's metaprogramming macros to build a Sinatra-like DSL for the Crystal language.
The DSL doesn't stock blocks to be invoked later on, but rather produces actual
methods using macros (
match and the sugar
post, etc.) where special
) are replaced as
:param segments are replaced to
Eventually methods look like:
get "/posts" | def match_GET__SLASH_posts get "/posts.xml" | def match_GET__SLASH_posts_DOT_xml
Please read dsl.cr for more details.
Eventually a call method is generated. It iterates over the class methods,
selects the generated
match_* methods and generates a big
transforming the method names back to regular expressions, and eventually
calling the method with matched data (if any).
Please read application.cr for more details.
require "http/server" require "artanis" class App < Artanis::Application get "/" do "ROOT" end get "/forbidden" do 403 end get "/posts/:id.:format" do p params["id"] p params["format"] "post" end get "/posts/:post_id/comments/:id(.:format)" do |post_id, id, format| p params["format"]? 200 end end server = HTTP::Server.new(9292) do |context| App.call(context) end puts "Listening on http://0.0.0.0:9292" server.listen
Running wrk against the above example (pointless hello world) gives the following results (TL;DR 12µs per request):
$ wrk -c 1000 -t 2 -d 5 http://localhost:9292/fast Running 5s test @ http://localhost:9292/fast 2 threads and 1000 connections Thread Stats Avg Stdev Max +/- Stdev Latency 12.26ms 14.48ms 423.28ms 99.05% Req/Sec 41.17k 2.93k 48.65k 76.00% 409663 requests in 5.01s, 25.79MB read Requests/sec: 81722.08 Transfer/sec: 5.14MB
A better benchmark is available in
test/dsl_bench.cr which monitors some
limits of the generated Crystal code, like going over all routes to find nothing
takes an awful lot of time, since it must build/execute a regular expression
against EVERY routes to eventually... find nothing.
$ crystal run --release test/dsl_bench.cr get root: 0.84 µs get param: 1.51 µs get params (block args): 2.18 µs get many params: 3.75 µs get many params (block args): 2.59 µs not found (method): 0.73 µs not found (path): 15.93 µs
Keep in mind these numbers tell nothing about reality. They only measure how
fast the generated
Application.call(request) method is in predefined cases.
Licensed under the MIT License