20. • Force URL encoding with PURI
Pitfall (1/3) of Drakma
(drakma:http-request
(format nil “http://b.hatena.ne.jp/search/tag?q=~A”
tag))
tag = “lisp” => OK
tag = “scheme” => OK
tag = “clojure” => OK
tag = “common lisp” => PURI:URI-PARSE-ERROR
21. • Force URL encoding with PURI
Pitfall (1/3) of Drakma
(drakma:http-request
(format nil “http://b.hatena.ne.jp/search/tag?q=~A”
(drakma:url-encode tag :utf-8)))
tag = “lisp” => OK
tag = “scheme” => OK
tag = “clojure” => OK
tag = “common lisp” => “common+lisp”
22. • Force URL encoding with PURI
Pitfall (1/3) of Drakma
(drakma:http-request
(format nil “http://b.hatena.ne.jp/search/tag?q=~A”
(drakma:url-encode tag :utf-8)))
tag = “lisp” => OK
tag = “scheme” => OK
tag = “clojure” => OK
tag = “common lisp” => “common+lisp”
tag = “AKB48” => OK
tag = “乃木坂46” => "%E4%B9%83%E6%9C%A8%E5%9D%8246"
23. • Force URL encoding with PURI
Pitfall (1/3) of Drakma
(drakma:http-request
(format nil “http://b.hatena.ne.jp/search/tag?q=~A”
(drakma:url-encode tag :utf-8))
:preserve-uri t)
tag = “lisp” => OK
tag = “scheme” => OK
tag = “clojure” => OK
tag = “common lisp” => OK
tag = “AKB48” => OK
tag = “乃木坂46” => OK
25. • Poor language support with flexi-streams
Pitfall (2/3) of Drakma
(drakma:http-request “http://www.hatena.ne.jp/”)
(drakma:http-request “http://www.google.co.jp/”)
26. • Poor language support with flexi-streams
Pitfall (2/3) of Drakma
(drakma:http-request “http://www.hatena.ne.jp/”)
;; => body as UTF-8 string
(drakma:http-request “http://www.google.co.jp/”)
;; => body as byte vector
WARNING: Problems determining charset (falling back to binary):
:SHIFT_JIS is not known to be a name for an external format.
28. • Tend to forget error handling
Pitfall (3/3) of Drakma
(let* ((body (drakma:http-request “http://cliki.net”))
(parsed-html (plump:parse body)))
…)
29. • Tend to forget error handling
Pitfall (3/3) of Drakma
(let* ((body (drakma:http-request “http://cliki.net”))
(parsed-html (plump:parse body)))
…)
It fails if the HTTP response code is 4xx or 5xx.
30. • Tend to forget error handling
Pitfall (3/3) of Drakma
(multiple-value-bind (body status)
(drakma:http-request “http://cliki.net”)
(unless (= status 200)
(error “An HTTP request failed (Code=~D)”
status))
(let ((parsed-html (plump:parse body)))
…))
Raise an error unless the status is not 200
31. • Tend to forget error handling
Pitfall (3/3) of Drakma
(multiple-value-bind (body status)
(drakma:http-request “http://cliki.net”)
(unless (= status 200)
(error “An HTTP request failed (Code=~D)”
status))
(let ((parsed-html (plump:parse body)))
…))
Raise an error unless the status is not 200
Want to retry???
32. • Tend to forget error handling
Pitfall (3/3) of Drakma
(block nil
(tagbody
retry
(multiple-value-bind (body status)
(drakma:http-request "http://cliki.net/")
(unless (= status 200)
(go retry))
(return body))))
With Auto-Retrying
33. • Tend to forget error handling
Pitfall (3/3) of Drakma
(block nil
(let ((times 5))
(tagbody
retry
(multiple-value-bind (body status)
(drakma:http-request "http://cliki.net/")
(unless (= status 200)
(when (= times 0)
(error "An HTTP request failed. (Code=~D)”
status))
(decf times)
(go retry))
(return body)))))
Retry only 5 times
50. Benchmark
Sending GET request 30 times to Local Server
(lower is better)
0
0.009
0.018
0.026
0.035
Drakma Dexador
w/out conneciton-pool
0.024s
51. Benchmark
Sending GET request 30 times to Local Server
(lower is better)
0
0.009
0.018
0.026
0.035
Drakma Dexador
w/out conneciton-pool
0.013s
0.024s
52. Sending GET request 30 times to Local Server
(lower is better)
0
0.009
0.018
0.026
0.035
Drakma Dexador
w/out conneciton-pool
0.013s
0.024s
Benchmark
x1.8 faster!
53. Sending GET request 30 times to Local Server
(lower is better)
0
0.009
0.018
0.026
0.035
Drakma Dexador
w/out conneciton-pool
0.013s
0.024s
Benchmark
x1.8 faster!????
55. Benchmark
Sending GET request 30 times to Remote Server
(lower is better)
0
0.15
0.3
0.45
0.6
Drakma Dexador
w/out conneciton-pool
0.505s
56. Benchmark
Sending GET request 30 times to Remote Server
(lower is better)
0
0.15
0.3
0.45
0.6
Drakma Dexador
w/out conneciton-pool
0.396s
0.505s
57. Benchmark
Sending GET request 30 times to Remote Server
(lower is better)
0
0.15
0.3
0.45
0.6
Drakma Dexador
w/out conneciton-pool
0.396s
0.505s x1.2 faster
58. Benchmark
Sending GET request 30 times to Remote Server
(lower is better)
0
0.15
0.3
0.45
0.6
Drakma Dexador
w/out conneciton-pool
0.396s
0.505s 0.0036 sec/req
59. Benchmark
Sending GET request 30 times to Remote Server
(lower is better)
0
0.15
0.3
0.45
0.6
Drakma Dexador
w/out conneciton-pool
0.396s
0.505s 0.0036 sec/req
Too trivial improvement…
68. • Reuse connections once established
(Implicit) Connection-pooling
;; Establish a new connection
(dex:get “http://lisp.org/index.html“)
;; Reuse the above connection
(dex:get “http://lisp.org/index.html“)
69. • Reuse connections once established
(Implicit) Connection-pooling
;; Establish a new connection
(dex:get “http://lisp.org/index.html“)
;; Reuse the above connection
(dex:get “http://lisp.org/index.html“)
0.727 sec
0.380 sec
71. Benchmark
Sending GET request 30 times to Local Server
(lower is better)
0
0.006
0.012
0.018
0.024
Drakma Dexador
w/out conneciton-pool
Dexador
w/ connection-pool
0.013s
0.024s
72. Benchmark
Sending GET request 30 times to Local Server
(lower is better)
0
0.006
0.012
0.018
0.024
Drakma Dexador
w/out conneciton-pool
Dexador
w/ connection-pool
0.005s
0.013s
0.024s
73. Benchmark
Sending GET request 30 times to Local Server
(lower is better)
0
0.006
0.012
0.018
0.024
Drakma Dexador
w/out conneciton-pool
Dexador
w/ connection-pool
0.005s
0.013s
0.024s
x4.8 faster!
74. Benchmark
Sending GET request 30 times to Remote Server
(lower is better)
0
0.15
0.3
0.45
0.6
Drakma Dexador
w/out conneciton-pool
Dexador
w/ connection-pool
0.396s
0.505s
75. Benchmark
Sending GET request 30 times to Remote Server
(lower is better)
0
0.15
0.3
0.45
0.6
Drakma Dexador
w/out conneciton-pool
Dexador
w/ connection-pool
0.219s
0.396s
0.505s
76. Benchmark
Sending GET request 30 times to Remote Server
(lower is better)
0
0.15
0.3
0.45
0.6
Drakma Dexador
w/out conneciton-pool
Dexador
w/ connection-pool
0.219s
0.396s
0.505s Still x2.3 faster!
77. • It’s pretty common to request to the same
host multiple times
• Can expect some performance
improvements in real applications
In real applications
79. • Still BETA (v0.9.7)
• Stabilizing. More performance
improvements are secondary importance.
• Bug reports are welcome
• Tested with SBCL, CCL, ABCL and ECL
on Travis CI
Status