source: code/trunk/vendor/github.com/valyala/fasthttp/README.md@ 145

Last change on this file since 145 was 145, checked in by Izuru Yakumo, 22 months ago

Updated the Makefile and vendored depedencies

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 30.3 KB
Line 
1# fasthttp [![GoDoc](https://godoc.org/github.com/valyala/fasthttp?status.svg)](http://godoc.org/github.com/valyala/fasthttp) [![Go Report](https://goreportcard.com/badge/github.com/valyala/fasthttp)](https://goreportcard.com/report/github.com/valyala/fasthttp)
2
3![FastHTTP – Fastest and reliable HTTP implementation in Go](https://github.com/fasthttp/docs-assets/raw/master/banner@0.5.png)
4
5Fast HTTP implementation for Go.
6
7# fasthttp might not be for you!
8fasthttp was design for some high performance edge cases. **Unless** your server/client needs to handle **thousands of small to medium requests per seconds** and needs a consistent low millisecond response time fasthttp might not be for you. **For most cases `net/http` is much better** as it's easier to use and can handle more cases. For most cases you won't even notice the performance difference.
9
10
11## General info and links
12
13Currently fasthttp is successfully used by [VertaMedia](https://vertamedia.com/)
14in a production serving up to 200K rps from more than 1.5M concurrent keep-alive
15connections per physical server.
16
17[TechEmpower Benchmark round 19 results](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=plaintext)
18
19[Server Benchmarks](#http-server-performance-comparison-with-nethttp)
20
21[Client Benchmarks](#http-client-comparison-with-nethttp)
22
23[Install](#install)
24
25[Documentation](https://godoc.org/github.com/valyala/fasthttp)
26
27[Examples from docs](https://godoc.org/github.com/valyala/fasthttp#pkg-examples)
28
29[Code examples](examples)
30
31[Awesome fasthttp tools](https://github.com/fasthttp)
32
33[Switching from net/http to fasthttp](#switching-from-nethttp-to-fasthttp)
34
35[Fasthttp best practices](#fasthttp-best-practices)
36
37[Tricks with byte buffers](#tricks-with-byte-buffers)
38
39[Related projects](#related-projects)
40
41[FAQ](#faq)
42
43## HTTP server performance comparison with [net/http](https://golang.org/pkg/net/http/)
44
45In short, fasthttp server is up to 10 times faster than net/http.
46Below are benchmark results.
47
48*GOMAXPROCS=1*
49
50net/http server:
51```
52$ GOMAXPROCS=1 go test -bench=NetHTTPServerGet -benchmem -benchtime=10s
53BenchmarkNetHTTPServerGet1ReqPerConn 1000000 12052 ns/op 2297 B/op 29 allocs/op
54BenchmarkNetHTTPServerGet2ReqPerConn 1000000 12278 ns/op 2327 B/op 24 allocs/op
55BenchmarkNetHTTPServerGet10ReqPerConn 2000000 8903 ns/op 2112 B/op 19 allocs/op
56BenchmarkNetHTTPServerGet10KReqPerConn 2000000 8451 ns/op 2058 B/op 18 allocs/op
57BenchmarkNetHTTPServerGet1ReqPerConn10KClients 500000 26733 ns/op 3229 B/op 29 allocs/op
58BenchmarkNetHTTPServerGet2ReqPerConn10KClients 1000000 23351 ns/op 3211 B/op 24 allocs/op
59BenchmarkNetHTTPServerGet10ReqPerConn10KClients 1000000 13390 ns/op 2483 B/op 19 allocs/op
60BenchmarkNetHTTPServerGet100ReqPerConn10KClients 1000000 13484 ns/op 2171 B/op 18 allocs/op
61```
62
63fasthttp server:
64```
65$ GOMAXPROCS=1 go test -bench=kServerGet -benchmem -benchtime=10s
66BenchmarkServerGet1ReqPerConn 10000000 1559 ns/op 0 B/op 0 allocs/op
67BenchmarkServerGet2ReqPerConn 10000000 1248 ns/op 0 B/op 0 allocs/op
68BenchmarkServerGet10ReqPerConn 20000000 797 ns/op 0 B/op 0 allocs/op
69BenchmarkServerGet10KReqPerConn 20000000 716 ns/op 0 B/op 0 allocs/op
70BenchmarkServerGet1ReqPerConn10KClients 10000000 1974 ns/op 0 B/op 0 allocs/op
71BenchmarkServerGet2ReqPerConn10KClients 10000000 1352 ns/op 0 B/op 0 allocs/op
72BenchmarkServerGet10ReqPerConn10KClients 20000000 789 ns/op 2 B/op 0 allocs/op
73BenchmarkServerGet100ReqPerConn10KClients 20000000 604 ns/op 0 B/op 0 allocs/op
74```
75
76*GOMAXPROCS=4*
77
78net/http server:
79```
80$ GOMAXPROCS=4 go test -bench=NetHTTPServerGet -benchmem -benchtime=10s
81BenchmarkNetHTTPServerGet1ReqPerConn-4 3000000 4529 ns/op 2389 B/op 29 allocs/op
82BenchmarkNetHTTPServerGet2ReqPerConn-4 5000000 3896 ns/op 2418 B/op 24 allocs/op
83BenchmarkNetHTTPServerGet10ReqPerConn-4 5000000 3145 ns/op 2160 B/op 19 allocs/op
84BenchmarkNetHTTPServerGet10KReqPerConn-4 5000000 3054 ns/op 2065 B/op 18 allocs/op
85BenchmarkNetHTTPServerGet1ReqPerConn10KClients-4 1000000 10321 ns/op 3710 B/op 30 allocs/op
86BenchmarkNetHTTPServerGet2ReqPerConn10KClients-4 2000000 7556 ns/op 3296 B/op 24 allocs/op
87BenchmarkNetHTTPServerGet10ReqPerConn10KClients-4 5000000 3905 ns/op 2349 B/op 19 allocs/op
88BenchmarkNetHTTPServerGet100ReqPerConn10KClients-4 5000000 3435 ns/op 2130 B/op 18 allocs/op
89```
90
91fasthttp server:
92```
93$ GOMAXPROCS=4 go test -bench=kServerGet -benchmem -benchtime=10s
94BenchmarkServerGet1ReqPerConn-4 10000000 1141 ns/op 0 B/op 0 allocs/op
95BenchmarkServerGet2ReqPerConn-4 20000000 707 ns/op 0 B/op 0 allocs/op
96BenchmarkServerGet10ReqPerConn-4 30000000 341 ns/op 0 B/op 0 allocs/op
97BenchmarkServerGet10KReqPerConn-4 50000000 310 ns/op 0 B/op 0 allocs/op
98BenchmarkServerGet1ReqPerConn10KClients-4 10000000 1119 ns/op 0 B/op 0 allocs/op
99BenchmarkServerGet2ReqPerConn10KClients-4 20000000 644 ns/op 0 B/op 0 allocs/op
100BenchmarkServerGet10ReqPerConn10KClients-4 30000000 346 ns/op 0 B/op 0 allocs/op
101BenchmarkServerGet100ReqPerConn10KClients-4 50000000 282 ns/op 0 B/op 0 allocs/op
102```
103
104## HTTP client comparison with net/http
105
106In short, fasthttp client is up to 10 times faster than net/http.
107Below are benchmark results.
108
109*GOMAXPROCS=1*
110
111net/http client:
112```
113$ GOMAXPROCS=1 go test -bench='HTTPClient(Do|GetEndToEnd)' -benchmem -benchtime=10s
114BenchmarkNetHTTPClientDoFastServer 1000000 12567 ns/op 2616 B/op 35 allocs/op
115BenchmarkNetHTTPClientGetEndToEnd1TCP 200000 67030 ns/op 5028 B/op 56 allocs/op
116BenchmarkNetHTTPClientGetEndToEnd10TCP 300000 51098 ns/op 5031 B/op 56 allocs/op
117BenchmarkNetHTTPClientGetEndToEnd100TCP 300000 45096 ns/op 5026 B/op 55 allocs/op
118BenchmarkNetHTTPClientGetEndToEnd1Inmemory 500000 24779 ns/op 5035 B/op 57 allocs/op
119BenchmarkNetHTTPClientGetEndToEnd10Inmemory 1000000 26425 ns/op 5035 B/op 57 allocs/op
120BenchmarkNetHTTPClientGetEndToEnd100Inmemory 500000 28515 ns/op 5045 B/op 57 allocs/op
121BenchmarkNetHTTPClientGetEndToEnd1000Inmemory 500000 39511 ns/op 5096 B/op 56 allocs/op
122```
123
124fasthttp client:
125```
126$ GOMAXPROCS=1 go test -bench='kClient(Do|GetEndToEnd)' -benchmem -benchtime=10s
127BenchmarkClientDoFastServer 20000000 865 ns/op 0 B/op 0 allocs/op
128BenchmarkClientGetEndToEnd1TCP 1000000 18711 ns/op 0 B/op 0 allocs/op
129BenchmarkClientGetEndToEnd10TCP 1000000 14664 ns/op 0 B/op 0 allocs/op
130BenchmarkClientGetEndToEnd100TCP 1000000 14043 ns/op 1 B/op 0 allocs/op
131BenchmarkClientGetEndToEnd1Inmemory 5000000 3965 ns/op 0 B/op 0 allocs/op
132BenchmarkClientGetEndToEnd10Inmemory 3000000 4060 ns/op 0 B/op 0 allocs/op
133BenchmarkClientGetEndToEnd100Inmemory 5000000 3396 ns/op 0 B/op 0 allocs/op
134BenchmarkClientGetEndToEnd1000Inmemory 5000000 3306 ns/op 2 B/op 0 allocs/op
135```
136
137*GOMAXPROCS=4*
138
139net/http client:
140```
141$ GOMAXPROCS=4 go test -bench='HTTPClient(Do|GetEndToEnd)' -benchmem -benchtime=10s
142BenchmarkNetHTTPClientDoFastServer-4 2000000 8774 ns/op 2619 B/op 35 allocs/op
143BenchmarkNetHTTPClientGetEndToEnd1TCP-4 500000 22951 ns/op 5047 B/op 56 allocs/op
144BenchmarkNetHTTPClientGetEndToEnd10TCP-4 1000000 19182 ns/op 5037 B/op 55 allocs/op
145BenchmarkNetHTTPClientGetEndToEnd100TCP-4 1000000 16535 ns/op 5031 B/op 55 allocs/op
146BenchmarkNetHTTPClientGetEndToEnd1Inmemory-4 1000000 14495 ns/op 5038 B/op 56 allocs/op
147BenchmarkNetHTTPClientGetEndToEnd10Inmemory-4 1000000 10237 ns/op 5034 B/op 56 allocs/op
148BenchmarkNetHTTPClientGetEndToEnd100Inmemory-4 1000000 10125 ns/op 5045 B/op 56 allocs/op
149BenchmarkNetHTTPClientGetEndToEnd1000Inmemory-4 1000000 11132 ns/op 5136 B/op 56 allocs/op
150```
151
152fasthttp client:
153```
154$ GOMAXPROCS=4 go test -bench='kClient(Do|GetEndToEnd)' -benchmem -benchtime=10s
155BenchmarkClientDoFastServer-4 50000000 397 ns/op 0 B/op 0 allocs/op
156BenchmarkClientGetEndToEnd1TCP-4 2000000 7388 ns/op 0 B/op 0 allocs/op
157BenchmarkClientGetEndToEnd10TCP-4 2000000 6689 ns/op 0 B/op 0 allocs/op
158BenchmarkClientGetEndToEnd100TCP-4 3000000 4927 ns/op 1 B/op 0 allocs/op
159BenchmarkClientGetEndToEnd1Inmemory-4 10000000 1604 ns/op 0 B/op 0 allocs/op
160BenchmarkClientGetEndToEnd10Inmemory-4 10000000 1458 ns/op 0 B/op 0 allocs/op
161BenchmarkClientGetEndToEnd100Inmemory-4 10000000 1329 ns/op 0 B/op 0 allocs/op
162BenchmarkClientGetEndToEnd1000Inmemory-4 10000000 1316 ns/op 5 B/op 0 allocs/op
163```
164
165
166## Install
167
168```
169go get -u github.com/valyala/fasthttp
170```
171
172
173## Switching from net/http to fasthttp
174
175Unfortunately, fasthttp doesn't provide API identical to net/http.
176See the [FAQ](#faq) for details.
177There is [net/http -> fasthttp handler converter](https://godoc.org/github.com/valyala/fasthttp/fasthttpadaptor),
178but it is better to write fasthttp request handlers by hand in order to use
179all of the fasthttp advantages (especially high performance :) ).
180
181Important points:
182
183* Fasthttp works with [RequestHandler functions](https://godoc.org/github.com/valyala/fasthttp#RequestHandler)
184instead of objects implementing [Handler interface](https://golang.org/pkg/net/http/#Handler).
185Fortunately, it is easy to pass bound struct methods to fasthttp:
186
187 ```go
188 type MyHandler struct {
189 foobar string
190 }
191
192 // request handler in net/http style, i.e. method bound to MyHandler struct.
193 func (h *MyHandler) HandleFastHTTP(ctx *fasthttp.RequestCtx) {
194 // notice that we may access MyHandler properties here - see h.foobar.
195 fmt.Fprintf(ctx, "Hello, world! Requested path is %q. Foobar is %q",
196 ctx.Path(), h.foobar)
197 }
198
199 // request handler in fasthttp style, i.e. just plain function.
200 func fastHTTPHandler(ctx *fasthttp.RequestCtx) {
201 fmt.Fprintf(ctx, "Hi there! RequestURI is %q", ctx.RequestURI())
202 }
203
204 // pass bound struct method to fasthttp
205 myHandler := &MyHandler{
206 foobar: "foobar",
207 }
208 fasthttp.ListenAndServe(":8080", myHandler.HandleFastHTTP)
209
210 // pass plain function to fasthttp
211 fasthttp.ListenAndServe(":8081", fastHTTPHandler)
212 ```
213
214* The [RequestHandler](https://godoc.org/github.com/valyala/fasthttp#RequestHandler)
215accepts only one argument - [RequestCtx](https://godoc.org/github.com/valyala/fasthttp#RequestCtx).
216It contains all the functionality required for http request processing
217and response writing. Below is an example of a simple request handler conversion
218from net/http to fasthttp.
219
220 ```go
221 // net/http request handler
222 requestHandler := func(w http.ResponseWriter, r *http.Request) {
223 switch r.URL.Path {
224 case "/foo":
225 fooHandler(w, r)
226 case "/bar":
227 barHandler(w, r)
228 default:
229 http.Error(w, "Unsupported path", http.StatusNotFound)
230 }
231 }
232 ```
233
234 ```go
235 // the corresponding fasthttp request handler
236 requestHandler := func(ctx *fasthttp.RequestCtx) {
237 switch string(ctx.Path()) {
238 case "/foo":
239 fooHandler(ctx)
240 case "/bar":
241 barHandler(ctx)
242 default:
243 ctx.Error("Unsupported path", fasthttp.StatusNotFound)
244 }
245 }
246 ```
247
248* Fasthttp allows setting response headers and writing response body
249in an arbitrary order. There is no 'headers first, then body' restriction
250like in net/http. The following code is valid for fasthttp:
251
252 ```go
253 requestHandler := func(ctx *fasthttp.RequestCtx) {
254 // set some headers and status code first
255 ctx.SetContentType("foo/bar")
256 ctx.SetStatusCode(fasthttp.StatusOK)
257
258 // then write the first part of body
259 fmt.Fprintf(ctx, "this is the first part of body\n")
260
261 // then set more headers
262 ctx.Response.Header.Set("Foo-Bar", "baz")
263
264 // then write more body
265 fmt.Fprintf(ctx, "this is the second part of body\n")
266
267 // then override already written body
268 ctx.SetBody([]byte("this is completely new body contents"))
269
270 // then update status code
271 ctx.SetStatusCode(fasthttp.StatusNotFound)
272
273 // basically, anything may be updated many times before
274 // returning from RequestHandler.
275 //
276 // Unlike net/http fasthttp doesn't put response to the wire until
277 // returning from RequestHandler.
278 }
279 ```
280
281* Fasthttp doesn't provide [ServeMux](https://golang.org/pkg/net/http/#ServeMux),
282but there are more powerful third-party routers and web frameworks
283with fasthttp support:
284
285 * [fasthttp-routing](https://github.com/qiangxue/fasthttp-routing)
286 * [router](https://github.com/fasthttp/router)
287 * [lu](https://github.com/vincentLiuxiang/lu)
288 * [atreugo](https://github.com/savsgio/atreugo)
289 * [Fiber](https://github.com/gofiber/fiber)
290 * [Gearbox](https://github.com/gogearbox/gearbox)
291
292 Net/http code with simple ServeMux is trivially converted to fasthttp code:
293
294 ```go
295 // net/http code
296
297 m := &http.ServeMux{}
298 m.HandleFunc("/foo", fooHandlerFunc)
299 m.HandleFunc("/bar", barHandlerFunc)
300 m.Handle("/baz", bazHandler)
301
302 http.ListenAndServe(":80", m)
303 ```
304
305 ```go
306 // the corresponding fasthttp code
307 m := func(ctx *fasthttp.RequestCtx) {
308 switch string(ctx.Path()) {
309 case "/foo":
310 fooHandlerFunc(ctx)
311 case "/bar":
312 barHandlerFunc(ctx)
313 case "/baz":
314 bazHandler.HandlerFunc(ctx)
315 default:
316 ctx.Error("not found", fasthttp.StatusNotFound)
317 }
318 }
319
320 fasthttp.ListenAndServe(":80", m)
321 ```
322
323* net/http -> fasthttp conversion table:
324
325 * All the pseudocode below assumes w, r and ctx have these types:
326 ```go
327 var (
328 w http.ResponseWriter
329 r *http.Request
330 ctx *fasthttp.RequestCtx
331 )
332 ```
333 * r.Body -> [ctx.PostBody()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.PostBody)
334 * r.URL.Path -> [ctx.Path()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.Path)
335 * r.URL -> [ctx.URI()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.URI)
336 * r.Method -> [ctx.Method()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.Method)
337 * r.Header -> [ctx.Request.Header](https://godoc.org/github.com/valyala/fasthttp#RequestHeader)
338 * r.Header.Get() -> [ctx.Request.Header.Peek()](https://godoc.org/github.com/valyala/fasthttp#RequestHeader.Peek)
339 * r.Host -> [ctx.Host()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.Host)
340 * r.Form -> [ctx.QueryArgs()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.QueryArgs) +
341 [ctx.PostArgs()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.PostArgs)
342 * r.PostForm -> [ctx.PostArgs()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.PostArgs)
343 * r.FormValue() -> [ctx.FormValue()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.FormValue)
344 * r.FormFile() -> [ctx.FormFile()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.FormFile)
345 * r.MultipartForm -> [ctx.MultipartForm()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.MultipartForm)
346 * r.RemoteAddr -> [ctx.RemoteAddr()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.RemoteAddr)
347 * r.RequestURI -> [ctx.RequestURI()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.RequestURI)
348 * r.TLS -> [ctx.IsTLS()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.IsTLS)
349 * r.Cookie() -> [ctx.Request.Header.Cookie()](https://godoc.org/github.com/valyala/fasthttp#RequestHeader.Cookie)
350 * r.Referer() -> [ctx.Referer()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.Referer)
351 * r.UserAgent() -> [ctx.UserAgent()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.UserAgent)
352 * w.Header() -> [ctx.Response.Header](https://godoc.org/github.com/valyala/fasthttp#ResponseHeader)
353 * w.Header().Set() -> [ctx.Response.Header.Set()](https://godoc.org/github.com/valyala/fasthttp#ResponseHeader.Set)
354 * w.Header().Set("Content-Type") -> [ctx.SetContentType()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.SetContentType)
355 * w.Header().Set("Set-Cookie") -> [ctx.Response.Header.SetCookie()](https://godoc.org/github.com/valyala/fasthttp#ResponseHeader.SetCookie)
356 * w.Write() -> [ctx.Write()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.Write),
357 [ctx.SetBody()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.SetBody),
358 [ctx.SetBodyStream()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.SetBodyStream),
359 [ctx.SetBodyStreamWriter()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.SetBodyStreamWriter)
360 * w.WriteHeader() -> [ctx.SetStatusCode()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.SetStatusCode)
361 * w.(http.Hijacker).Hijack() -> [ctx.Hijack()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.Hijack)
362 * http.Error() -> [ctx.Error()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.Error)
363 * http.FileServer() -> [fasthttp.FSHandler()](https://godoc.org/github.com/valyala/fasthttp#FSHandler),
364 [fasthttp.FS](https://godoc.org/github.com/valyala/fasthttp#FS)
365 * http.ServeFile() -> [fasthttp.ServeFile()](https://godoc.org/github.com/valyala/fasthttp#ServeFile)
366 * http.Redirect() -> [ctx.Redirect()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.Redirect)
367 * http.NotFound() -> [ctx.NotFound()](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.NotFound)
368 * http.StripPrefix() -> [fasthttp.PathRewriteFunc](https://godoc.org/github.com/valyala/fasthttp#PathRewriteFunc)
369
370* *VERY IMPORTANT!* Fasthttp disallows holding references
371to [RequestCtx](https://godoc.org/github.com/valyala/fasthttp#RequestCtx) or to its'
372members after returning from [RequestHandler](https://godoc.org/github.com/valyala/fasthttp#RequestHandler).
373Otherwise [data races](http://blog.golang.org/race-detector) are inevitable.
374Carefully inspect all the net/http request handlers converted to fasthttp whether
375they retain references to RequestCtx or to its' members after returning.
376RequestCtx provides the following _band aids_ for this case:
377
378 * Wrap RequestHandler into [TimeoutHandler](https://godoc.org/github.com/valyala/fasthttp#TimeoutHandler).
379 * Call [TimeoutError](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.TimeoutError)
380 before returning from RequestHandler if there are references to RequestCtx or to its' members.
381 See [the example](https://godoc.org/github.com/valyala/fasthttp#example-RequestCtx-TimeoutError)
382 for more details.
383
384Use this brilliant tool - [race detector](http://blog.golang.org/race-detector) -
385for detecting and eliminating data races in your program. If you detected
386data race related to fasthttp in your program, then there is high probability
387you forgot calling [TimeoutError](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.TimeoutError)
388before returning from [RequestHandler](https://godoc.org/github.com/valyala/fasthttp#RequestHandler).
389
390* Blind switching from net/http to fasthttp won't give you performance boost.
391While fasthttp is optimized for speed, its' performance may be easily saturated
392by slow [RequestHandler](https://godoc.org/github.com/valyala/fasthttp#RequestHandler).
393So [profile](http://blog.golang.org/profiling-go-programs) and optimize your
394code after switching to fasthttp. For instance, use [quicktemplate](https://github.com/valyala/quicktemplate)
395instead of [html/template](https://golang.org/pkg/html/template/).
396
397* See also [fasthttputil](https://godoc.org/github.com/valyala/fasthttp/fasthttputil),
398[fasthttpadaptor](https://godoc.org/github.com/valyala/fasthttp/fasthttpadaptor) and
399[expvarhandler](https://godoc.org/github.com/valyala/fasthttp/expvarhandler).
400
401
402## Performance optimization tips for multi-core systems
403
404* Use [reuseport](https://godoc.org/github.com/valyala/fasthttp/reuseport) listener.
405* Run a separate server instance per CPU core with GOMAXPROCS=1.
406* Pin each server instance to a separate CPU core using [taskset](http://linux.die.net/man/1/taskset).
407* Ensure the interrupts of multiqueue network card are evenly distributed between CPU cores.
408 See [this article](https://blog.cloudflare.com/how-to-achieve-low-latency/) for details.
409* Use the latest version of Go as each version contains performance improvements.
410
411
412## Fasthttp best practices
413
414* Do not allocate objects and `[]byte` buffers - just reuse them as much
415 as possible. Fasthttp API design encourages this.
416* [sync.Pool](https://golang.org/pkg/sync/#Pool) is your best friend.
417* [Profile your program](http://blog.golang.org/profiling-go-programs)
418 in production.
419 `go tool pprof --alloc_objects your-program mem.pprof` usually gives better
420 insights for optimization opportunities than `go tool pprof your-program cpu.pprof`.
421* Write [tests and benchmarks](https://golang.org/pkg/testing/) for hot paths.
422* Avoid conversion between `[]byte` and `string`, since this may result in memory
423 allocation+copy. Fasthttp API provides functions for both `[]byte` and `string` -
424 use these functions instead of converting manually between `[]byte` and `string`.
425 There are some exceptions - see [this wiki page](https://github.com/golang/go/wiki/CompilerOptimizations#string-and-byte)
426 for more details.
427* Verify your tests and production code under
428 [race detector](https://golang.org/doc/articles/race_detector.html) on a regular basis.
429* Prefer [quicktemplate](https://github.com/valyala/quicktemplate) instead of
430 [html/template](https://golang.org/pkg/html/template/) in your webserver.
431
432
433## Tricks with `[]byte` buffers
434
435The following tricks are used by fasthttp. Use them in your code too.
436
437* Standard Go functions accept nil buffers
438```go
439var (
440 // both buffers are uninitialized
441 dst []byte
442 src []byte
443)
444dst = append(dst, src...) // is legal if dst is nil and/or src is nil
445copy(dst, src) // is legal if dst is nil and/or src is nil
446(string(src) == "") // is true if src is nil
447(len(src) == 0) // is true if src is nil
448src = src[:0] // works like a charm with nil src
449
450// this for loop doesn't panic if src is nil
451for i, ch := range src {
452 doSomething(i, ch)
453}
454```
455
456So throw away nil checks for `[]byte` buffers from you code. For example,
457```go
458srcLen := 0
459if src != nil {
460 srcLen = len(src)
461}
462```
463
464becomes
465
466```go
467srcLen := len(src)
468```
469
470* String may be appended to `[]byte` buffer with `append`
471```go
472dst = append(dst, "foobar"...)
473```
474
475* `[]byte` buffer may be extended to its' capacity.
476```go
477buf := make([]byte, 100)
478a := buf[:10] // len(a) == 10, cap(a) == 100.
479b := a[:100] // is valid, since cap(a) == 100.
480```
481
482* All fasthttp functions accept nil `[]byte` buffer
483```go
484statusCode, body, err := fasthttp.Get(nil, "http://google.com/")
485uintBuf := fasthttp.AppendUint(nil, 1234)
486```
487
488* String and `[]byte` buffers may converted without memory allocations
489```go
490func b2s(b []byte) string {
491 return *(*string)(unsafe.Pointer(&b))
492}
493
494func s2b(s string) (b []byte) {
495 bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
496 sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
497 bh.Data = sh.Data
498 bh.Cap = sh.Len
499 bh.Len = sh.Len
500 return b
501}
502```
503
504### Warning:
505This is an **unsafe** way, the result string and `[]byte` buffer share the same bytes.
506
507**Please make sure not to modify the bytes in the `[]byte` buffer if the string still survives!**
508
509## Related projects
510
511 * [fasthttp](https://github.com/fasthttp) - various useful
512 helpers for projects based on fasthttp.
513 * [fasthttp-routing](https://github.com/qiangxue/fasthttp-routing) - fast and
514 powerful routing package for fasthttp servers.
515 * [http2](https://github.com/dgrr/http2) - HTTP/2 implementation for fasthttp.
516 * [router](https://github.com/fasthttp/router) - a high
517 performance fasthttp request router that scales well.
518 * [fastws](https://github.com/fasthttp/fastws) - Bloatless WebSocket package made for fasthttp
519 to handle Read/Write operations concurrently.
520 * [gramework](https://github.com/gramework/gramework) - a web framework made by one of fasthttp maintainers
521 * [lu](https://github.com/vincentLiuxiang/lu) - a high performance
522 go middleware web framework which is based on fasthttp.
523 * [websocket](https://github.com/fasthttp/websocket) - Gorilla-based
524 websocket implementation for fasthttp.
525 * [websocket](https://github.com/dgrr/websocket) - Event-based high-performance WebSocket library for zero-allocation
526 websocket servers and clients.
527 * [fasthttpsession](https://github.com/phachon/fasthttpsession) - a fast and powerful session package for fasthttp servers.
528 * [atreugo](https://github.com/savsgio/atreugo) - High performance and extensible micro web framework with zero memory allocations in hot paths.
529 * [kratgo](https://github.com/savsgio/kratgo) - Simple, lightweight and ultra-fast HTTP Cache to speed up your websites.
530 * [kit-plugins](https://github.com/wencan/kit-plugins/tree/master/transport/fasthttp) - go-kit transport implementation for fasthttp.
531 * [Fiber](https://github.com/gofiber/fiber) - An Expressjs inspired web framework running on Fasthttp
532 * [Gearbox](https://github.com/gogearbox/gearbox) - :gear: gearbox is a web framework written in Go with a focus on high performance and memory optimization
533
534
535## FAQ
536
537* *Why creating yet another http package instead of optimizing net/http?*
538
539 Because net/http API limits many optimization opportunities.
540 For example:
541 * net/http Request object lifetime isn't limited by request handler execution
542 time. So the server must create a new request object per each request instead
543 of reusing existing objects like fasthttp does.
544 * net/http headers are stored in a `map[string][]string`. So the server
545 must parse all the headers, convert them from `[]byte` to `string` and put
546 them into the map before calling user-provided request handler.
547 This all requires unnecessary memory allocations avoided by fasthttp.
548 * net/http client API requires creating a new response object per each request.
549
550* *Why fasthttp API is incompatible with net/http?*
551
552 Because net/http API limits many optimization opportunities. See the answer
553 above for more details. Also certain net/http API parts are suboptimal
554 for use:
555 * Compare [net/http connection hijacking](https://golang.org/pkg/net/http/#Hijacker)
556 to [fasthttp connection hijacking](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.Hijack).
557 * Compare [net/http Request.Body reading](https://golang.org/pkg/net/http/#Request)
558 to [fasthttp request body reading](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.PostBody).
559
560* *Why fasthttp doesn't support HTTP/2.0 and WebSockets?*
561
562 [HTTP/2.0 support](https://github.com/fasthttp/http2) is in progress. [WebSockets](https://github.com/fasthttp/websockets) has been done already.
563 Third parties also may use [RequestCtx.Hijack](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.Hijack)
564 for implementing these goodies.
565
566* *Are there known net/http advantages comparing to fasthttp?*
567
568 Yes:
569 * net/http supports [HTTP/2.0 starting from go1.6](https://http2.golang.org/).
570 * net/http API is stable, while fasthttp API constantly evolves.
571 * net/http handles more HTTP corner cases.
572 * net/http can stream both request and response bodies
573 * net/http can handle bigger bodies as it doesn't read the whole body into memory
574 * net/http should contain less bugs, since it is used and tested by much
575 wider audience.
576
577* *Why fasthttp API prefers returning `[]byte` instead of `string`?*
578
579 Because `[]byte` to `string` conversion isn't free - it requires memory
580 allocation and copy. Feel free wrapping returned `[]byte` result into
581 `string()` if you prefer working with strings instead of byte slices.
582 But be aware that this has non-zero overhead.
583
584* *Which GO versions are supported by fasthttp?*
585
586 Go 1.15.x. Older versions won't be supported.
587
588* *Please provide real benchmark data and server information*
589
590 See [this issue](https://github.com/valyala/fasthttp/issues/4).
591
592* *Are there plans to add request routing to fasthttp?*
593
594 There are no plans to add request routing into fasthttp.
595 Use third-party routers and web frameworks with fasthttp support:
596
597 * [fasthttp-routing](https://github.com/qiangxue/fasthttp-routing)
598 * [router](https://github.com/fasthttp/router)
599 * [gramework](https://github.com/gramework/gramework)
600 * [lu](https://github.com/vincentLiuxiang/lu)
601 * [atreugo](https://github.com/savsgio/atreugo)
602 * [Fiber](https://github.com/gofiber/fiber)
603 * [Gearbox](https://github.com/gogearbox/gearbox)
604
605 See also [this issue](https://github.com/valyala/fasthttp/issues/9) for more info.
606
607* *I detected data race in fasthttp!*
608
609 Cool! [File a bug](https://github.com/valyala/fasthttp/issues/new). But before
610 doing this check the following in your code:
611
612 * Make sure there are no references to [RequestCtx](https://godoc.org/github.com/valyala/fasthttp#RequestCtx)
613 or to its' members after returning from [RequestHandler](https://godoc.org/github.com/valyala/fasthttp#RequestHandler).
614 * Make sure you call [TimeoutError](https://godoc.org/github.com/valyala/fasthttp#RequestCtx.TimeoutError)
615 before returning from [RequestHandler](https://godoc.org/github.com/valyala/fasthttp#RequestHandler)
616 if there are references to [RequestCtx](https://godoc.org/github.com/valyala/fasthttp#RequestCtx)
617 or to its' members, which may be accessed by other goroutines.
618
619* *I didn't find an answer for my question here*
620
621 Try exploring [these questions](https://github.com/valyala/fasthttp/issues?q=label%3Aquestion).
Note: See TracBrowser for help on using the repository browser.