[ANN] Fast HTTP package - fasthttp

8,856 views
Skip to first unread message

Aliaksandr Valialkin

unread,
Nov 22, 2015, 9:17:56 AM11/22/15
to golang-nuts
Hi all,

If you think net/http server is slow, try fasthttp , which is up to 10x faster (on synthetic benchmarks of course :) It is only up to 3x faster than net/http under real-world load in production). I added fasthttp to TechEmpower benchmarks (see the pull request) and it shows up to 4x better performance than go-raw on plaintext benchmark when running on my computer.

Below are net/http vs fasthttp server performance comparisons for GOMAXPROCS=1 and GOMAXPROCS=4:

GOMAXPROCS=1

net/http:

$ GOMAXPROCS=1 go test -bench=NetHTTPServerGet -benchmem
PASS
BenchmarkNetHTTPServerGet1ReqPerConn              100000             21211 ns/op            2407 B/op         30 allocs/op
BenchmarkNetHTTPServerGet2ReqPerConn              100000             15682 ns/op            2373 B/op         24 allocs/op
BenchmarkNetHTTPServerGet10ReqPerConn             200000              9957 ns/op            2103 B/op         19 allocs/op
BenchmarkNetHTTPServerGet10000ReqPerConn          200000              8243 ns/op            2034 B/op         18 allocs/op
BenchmarkNetHTTPServerGet1ReqPerConn1KClients      50000             23474 ns/op            2704 B/op         30 allocs/op
BenchmarkNetHTTPServerGet2ReqPerConn1KClients     100000             18124 ns/op            2539 B/op         24 allocs/op
BenchmarkNetHTTPServerGet10ReqPerConn1KClients    100000             11815 ns/op            2689 B/op         19 allocs/op
BenchmarkNetHTTPServerGet10KReqPerConn1KClients   200000              9106 ns/op            2034 B/op         18 allocs/op


fasthttp:

$ GOMAXPROCS=1 go test -bench=kServerGet -benchmem
PASS
BenchmarkServerGet1ReqPerConn                     500000              2495 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet2ReqPerConn                    1000000              1925 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet10ReqPerConn                   1000000              1300 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet10KReqPerConn                  1000000              1140 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet1ReqPerConn1KClients            500000              2460 ns/op               1 B/op          0 allocs/op
BenchmarkServerGet2ReqPerConn1KClients           1000000              1962 ns/op               1 B/op          0 allocs/op
BenchmarkServerGet10ReqPerConn1KClients          1000000              1340 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet10KReqPerConn1KClients         1000000              1180 ns/op               0 B/op          0 allocs/op


GOMAXPROCS=4

net/http:

$ GOMAXPROCS=4 go test -bench=NetHTTPServerGet -benchmem
PASS
BenchmarkNetHTTPServerGet1ReqPerConn-4                    200000              5929 ns/op            2434 B/op         30 allocs/op
BenchmarkNetHTTPServerGet2ReqPerConn-4                    300000              4153 ns/op            2399 B/op         24 allocs/op
BenchmarkNetHTTPServerGet10ReqPerConn-4                   500000              2751 ns/op            2118 B/op         19 allocs/op
BenchmarkNetHTTPServerGet10000ReqPerConn-4                500000              2398 ns/op            2037 B/op         18 allocs/op
BenchmarkNetHTTPServerGet1ReqPerConn1KClients-4           200000              5979 ns/op            2494 B/op         30 allocs/op
BenchmarkNetHTTPServerGet2ReqPerConn1KClients-4           300000              4582 ns/op            2457 B/op         24 allocs/op
BenchmarkNetHTTPServerGet10ReqPerConn1KClients-4          300000              3589 ns/op            2537 B/op         19 allocs/op
BenchmarkNetHTTPServerGet10KReqPerConn1KClients-4         500000              2465 ns/op            2036 B/op         18 allocs/op


fasthttp:

$ GOMAXPROCS=4 go test -bench=kServerGet -benchmem
PASS
BenchmarkServerGet1ReqPerConn-4                          2000000              1094 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet2ReqPerConn-4                          2000000               707 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet10ReqPerConn-4                         3000000               417 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet10KReqPerConn-4                        5000000               351 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet1ReqPerConn1KClients-4                 2000000               916 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet2ReqPerConn1KClients-4                 2000000               655 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet10ReqPerConn1KClients-4                3000000               404 ns/op               0 B/op          0 allocs/op
BenchmarkServerGet10KReqPerConn1KClients-4               5000000               359 ns/op               0 B/op          0 allocs/op



Fasthttp has the following features:

    * Optimized for speed. Easily handles more than 100K qps and more than 1M
      concurrent keep-alive connections on modern hardware.
    * Optimized for low memory usage.
    * Server supports requests' pipelining. Multiple requests may be read from
      a single network packet and multiple responses may be sent in a single
      network packet. This may be useful for highly loaded REST services.
    * Server provides the following anti-DoS limits:

        * The number of concurrent connections.
        * The number of concurrent connections per client IP.
        * The number of requests per connection.
        * Request read timeout.
        * Response write timeout.
        * Maximum request header size.
        * Maximum request execution time.

    * The following additional info is exposed to request handler:

        * Server address. May be useful if server listens to multiple TCP ports or unix sockets.
        * Per-request logger.
        * Unique request id.
        * Request start time.
        * Connection start time.
        * Request sequence number for the current connection.

    * Fasthttp API is designed with the ability to extend existing
      implementations or to write custom http implementations from scratch.

andrewc...@gmail.com

unread,
Nov 22, 2015, 5:16:54 PM11/22/15
to golang-nuts
Looks really cool, thanks! Perhaps you should write an article about writing optimized go code :), your gorpc looks interesting too.

tacod...@gmail.com

unread,
Nov 22, 2015, 5:46:02 PM11/22/15
to golang-nuts, andrewc...@gmail.com
Maybe you could improve the standard library's net/http package with you knowledge?

Op zondag 22 november 2015 23:16:54 UTC+1 schreef andrewc...@gmail.com:

Klaus Post

unread,
Nov 23, 2015, 4:42:03 AM11/23/15
to golang-nuts
Hi!

Very nice package!

Maybe a documentation section on "Switching from net.http" would help adopters.

It seems to be a drop-in replacement for http, which is very nice, but there isn't any information on what (if anything) to be aware of when switching.


/Klaus

Brad Fitzpatrick

unread,
Nov 23, 2015, 1:45:09 PM11/23/15
to Aliaksandr Valialkin, golang-nuts
Looking at the docs, it's a little overwhelming:

But starting with the first method, 

Why is that exported to users? And why don't you just use the language feature which is built in and faster? (http://play.golang.org/p/oVFHGxcArD)





--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Медер Бакиров

unread,
Nov 26, 2015, 6:19:23 PM11/26/15
to golang-nuts, val...@gmail.com
Dear Aliaksandr Valialkin,

Any update on this?


Thanks! 

вторник, 24 ноября 2015 г., 0:45:09 UTC+6 пользователь bradfitz написал:

569...@gmail.com

unread,
Nov 26, 2015, 11:59:55 PM11/26/15
to golang-nuts
Looks amazing! The annoying this is that I won't be able to help myself but switch over to using this, which puts me another day behind schedule :)

Could you please add graceful restart as per: https://github.com/facebookgo/grace/blob/master/gracehttp/http.go ?

If not I can probably make a folk of gracehttp which works with fasthttp, but it would be nice if it were made as part of the fasthttp package with the same optimizations.

Aliaksandr Valialkin

unread,
Nov 28, 2015, 4:38:57 PM11/28/15
to andrewc...@gmail.com, golang-nuts
On Mon, Nov 23, 2015 at 12:16 AM, <andrewc...@gmail.com> wrote:
Looks really cool, thanks! Perhaps you should write an article about writing optimized go code :), your gorpc looks interesting too.


There is a section named Fasthttp best practicies - see https://github.com/valyala/fasthttp#fasthttp-best-practicies . TL;DR profile your code :)

As for gorpc, unfortunately its' API suffers the same problem as net/http API - it wasn't designed with 'minimize memory allocations' in mind. While it is well optimized on the wire level, it has quite big GC overhead. I'm planning to create fastrpc, which should have API similar to fasthttp, so it should be much faster than gorpc :)


--
Best Regards,

Aliaksandr

Aliaksandr Valialkin

unread,
Nov 28, 2015, 4:41:33 PM11/28/15
to tacod...@gmail.com, golang-nuts, andrewc...@gmail.com
On Mon, Nov 23, 2015 at 12:45 AM, <tacod...@gmail.com> wrote:
Maybe you could improve the standard library's net/http package with you knowledge?

I tried before starting fasthttp, but without significant success. The main problem is in the net/http API, which wasn't designed with 'minimize memory allocations' in mind. So the only way to optimize net/http is to create new API from scratch such as fasthttp :)

--
Best Regards,

Aliaksandr

Aliaksandr Valialkin

unread,
Nov 28, 2015, 4:46:22 PM11/28/15
to Klaus Post, golang-nuts
On Mon, Nov 23, 2015 at 11:42 AM, Klaus Post <klau...@gmail.com> wrote:
Hi!

Very nice package!

Maybe a documentation section on "Switching from net.http" would help adopters.

Yes, this is on my radar - see TODO.
 

It seems to be a drop-in replacement for http, which is very nice, but there isn't any information on what (if anything) to be aware of when switching.
 
Unfortunately fasthttp isn't drop-in replacement for net/http. It has different API due to performance reasons. See the FAQ for details.

Aliaksandr Valialkin

unread,
Nov 28, 2015, 4:48:37 PM11/28/15
to Brad Fitzpatrick, golang-nuts
On Mon, Nov 23, 2015 at 8:44 PM, Brad Fitzpatrick <brad...@golang.org> wrote:
Looking at the docs, it's a little overwhelming:

But starting with the first method, 

Why is that exported to users? And why don't you just use the language feature which is built in and faster? (http://play.golang.org/p/oVFHGxcArD)

I wasn't aware of append([]byte, string...) trick :) Now AppendBytesStr is left for backwards compatibility only.

--
Best Regards,

Aliaksandr

Aliaksandr Valialkin

unread,
Nov 28, 2015, 5:14:11 PM11/28/15
to Медер Бакиров, golang-nuts
On Fri, Nov 27, 2015 at 1:19 AM, Медер Бакиров <bak...@gmail.com> wrote:
Dear Aliaksandr Valialkin,

Any update on this?

I was busy ramping up fasthttp functionality on this week. See the commit log for details. Random highlights are:

* connection hijacking (API is better than in net/http);
* multipart/form-data support;
* additional anti-DoS limits;
* improved client code and bugfixes;
* microoptimizations all over the code.
Yes:

> I'm kinda shocked. The structure on It's own is not really good you should split the parser from everything.

Yet another functional programming guru? Theory is usually far from practice. I prefer writing simple code for my needs instead of spending months on 'perfect design', which has high probability to fail under own complexity in the future.

> There are by far not enough tests.

Agreed. I try writing as much tests as possible, but sometimes laziness wins :(

> I don't see any Rfc comment and so on. Implementing Http these days is not that easy.

Show me at least one http server or client with perfect support for all http-related RFCs. I'm unaware of such beasts. Fasthttp supports widely used http subset. And this subset will grow in the future.

> You basicly read the entire body. So I can just fill your server with gigabytes of garbage. Even when a client does not send a cookie to authenticate itself as valid user your reader still reads the whole body.

This has been addressed in the commit 1 and commit 2.

> Also when I see it right you don't support comma splitted header values. Also header must support \t(HT) or SP not only SP. That's only to name abit from Http RFC ... It is huge.

Show me such a crazy http client, which uses this RFC garbage and fasthttp will support this soon :)


Aliaksandr

Aliaksandr Valialkin

unread,
Nov 28, 2015, 5:24:29 PM11/28/15
to 569...@gmail.com, golang-nuts
On Fri, Nov 27, 2015 at 6:59 AM, <569...@gmail.com> wrote:
Looks amazing! The annoying this is that I won't be able to help myself but switch over to using this, which puts me another day behind schedule :)

Could you please add graceful restart as per: https://github.com/facebookgo/grace/blob/master/gracehttp/http.go ?

I don't know good API for graceful restart, but you can implement it yourself. Something like the following:

for {
    s := createServerFromUpdatedSettings()
    ln := createListenerFromUpdatedSettings()
    go func() {
        waitForRestartSignal()
        ln.Close()
    }()
    if err := s.Serve(ln); err != nil {
        log.Fatalf("fatal error in server: %s", err)
    }
}

Try also reuseport listener . With this listener you can just start new process listening on the same address and gracefully shutdown old process, i.e. Listener.Stop() and wait until all the currently executed requests are finished.


--
Best Regards,

Aliaksandr

Aliaksandr Valialkin

unread,
Dec 1, 2015, 12:11:43 PM12/1/15
to golang-nuts


On Monday, November 23, 2015 at 11:42:03 AM UTC+2, Klaus Post wrote:

Maybe a documentation section on "Switching from net.http" would help adopters.

 
See the initial documentation about switching from net/http to fasthttp at https://github.com/valyala/fasthttp#switching-from-nethttp-to-fasthttp .

Konstantin Khomoutov

unread,
Dec 1, 2015, 12:36:02 PM12/1/15
to Aliaksandr Valialkin, Медер Бакиров, golang-nuts
On Sun, 29 Nov 2015 00:13:56 +0200
Aliaksandr Valialkin <val...@gmail.com> wrote:

[...]
> *> Also when I see it right you don't support comma splitted header
> values. Also header must support \t(HT) or SP not only SP. That's
> only to name abit from Http RFC ... It is huge.*
>
> Show me such a crazy http client, which uses this RFC garbage and
> fasthttp will support this soon :)

The same approach to RFCs brought us Internet Explorer 6 through 10 (or
something).

Aliaksandr Valialkin

unread,
Dec 1, 2015, 1:51:49 PM12/1/15
to Konstantin Khomoutov, Медер Бакиров, golang-nuts

On Tue, Dec 1, 2015 at 7:35 PM, Konstantin Khomoutov <flat...@users.sourceforge.net> wrote:
> *> Also when I see it right you don't support comma splitted header
> values. Also header must support \t(HT) or SP not only SP. That's
> only to name abit from Http RFC ... It is huge.*
>
> Show me such a crazy http client, which uses this RFC garbage and
> fasthttp will support this soon :)

The same approach to RFCs brought us Internet Explorer 6 through 10 (or
something).

Then blind adherence to (RFC) standards gave us such monsters as SOAP and CORBA :)

Note that good standards don't appear out of blue. They usually appear after the technology has been used (and tested) in production for several years. Such standards usually contain 'common practice' for the given technology. Probably, HTML5 and HTTP/2.0 are good examples of such standards.

--
Best Regards,

Aliaksandr

Aliaksandr Valialkin

unread,
Feb 26, 2016, 11:33:57 AM2/26/16
to golang-nuts
Just FYI - fasthttp results in TechEmpower Web Frameworks Benchmarks round 12.

dvsb...@gmail.com

unread,
Mar 27, 2016, 3:58:23 PM3/27/16
to golang-nuts
How to use http/template with fasthttp ?
Can you give an example ?

I have a template text gets between the <pre> ... </pre> and displayed as text

t, err := template.ParseFiles("templates/index.html")
t.ExecuteTemplate(ctx, "index", nil)

Aliaksandr Valialkin

unread,
Mar 28, 2016, 2:19:31 PM3/28/16
to dvsb...@gmail.com, golang-nuts
This should work - see the end of fortuneHandler function for details. Don't forget setting Content-Type to 'text/html'.

dvsb...@gmail.com

unread,
Apr 4, 2016, 2:33:01 PM4/4/16
to golang-nuts
Thank you. Variant works with the name template
...
ctx.SetContentType("text/html; charset=utf-8")
if err := tmpl.ExecuteTemplate(ctx, "index", nil); err != nil {
log.Fatalf("Error executing fortune: %s", err)
}
Reply all
Reply to author
Forward
0 new messages