
Echo: A fast HTTP router and micro framework in Go - Spiritus
https://github.com/labstack/echo
======
conradk
I don't understand why people keep reinventing routers even though routing
doesn't take much time anyways, especially in a compiled language like Go.

Most APIs seems to respond within 20 to 200ms. Even if you take 1ms to route
stuff, what's the point in spending so much time in trying to optimize routing
instead of SQL queries, cache layers or developer productivity with a nice ORM
? Trying to squeeze nanoseconds out seems pointless to me at the moment,
especially since newcomers to Go end up seeing 20 different routers and might
not know where to start.

I'm genuinely wondering.

~~~
rodgerd
It's particularly jarring for me given that whenever there's a post about
someone moving away from Amazon and seeing significant performance and/or cost
benefits the HN zeitgeist tends to be rubbishing it as too much work for the
benefit, but endlessly re-solving the same problems over and over in software
for much smaller gains tends to be wildly applauded.

~~~
pekk
If 80% of posters on a thread about diets say vegetarian is healthier, and 80%
of posters on a thread about fun recommend riding a motorcycle, it doesn't
follow that there is a single HN zeitgeist saying both things. A simpler
explanation is that there are two groups which speak up in different
situations. Those groups don't necessarily overlap much.

------
manucorporat
I didn't want to release this today... but there we go. Gin will also be a
zero allocation http router.

[https://github.com/gin-gonic/gin/issues/249](https://github.com/gin-
gonic/gin/issues/249)

~~~
nixarn
Awesome! Gin is really the best go webframework at the moment. Fast, easy to
use and is being maintained and improved upon!

------
bgentry
Interesting approach. I guess there are use cases where the small number of
allocs of some of the other routers is enough to cause problems.

I'll definitely stick to httprouter as my default starting point, though. The
params interface is much nicer, and it's pretty damn good with performance and
allocation count:
[https://github.com/julienschmidt/httprouter](https://github.com/julienschmidt/httprouter)

~~~
bigdubs
We're also using httprouter and so far have been pretty happy with it. The
lack of middleware isn't really an issue, you can inline the key stuff (Gzip,
logging) yourself from other sources.

~~~
misframer
It isn't too difficult to add basic middleware support. We actually wrote a
tiny framework[0] around httprouter for that to use on our API servers. It
works pretty well.

[0]
[https://github.com/VividCortex/siesta](https://github.com/VividCortex/siesta)

------
tlb
It is interesting and surprising how many allocations per request other
frameworks do, from 100s to 10000s.

They're sort of cheating by having a pool, and sort of punting with things
like "// MaxParam sets the maximum allowed path parameters. Default is 5..."

~~~
adrusi
How is that cheating? That's just how you program without allocations.

~~~
tlb
Pool allocations are still allocations. If you look at the implementation for
Pool.get, it works a lot like malloc:

[http://golang.org/src/sync/pool.go](http://golang.org/src/sync/pool.go)

I've programmed without pools or allocations, where everything had statically
allocated storage. Both for microcontroller firmware, and telephony software.
It's noticeably harder.

------
AYBABTME
I'm curious what they did different than httprouter to remove the allocations,
or if they trick the benchmark tool by reusing memory with a pool.

~~~
brildum
Looks like its using a `sync.Pool` to amortize allocations.

[https://github.com/labstack/echo/blob/master/echo.go#L17](https://github.com/labstack/echo/blob/master/echo.go#L17)

~~~
AYBABTME
I noticed that, I didn't verify where it was used. It's smart, although it
cheats the benchmark... kind of. =P

I'm always suspicious of usages of `sync.Pool`, it's easy to reuse things that
aren't reset properly and end up with subtle coupling between requests.

------
mmgutz
It would have been nice if the library conformed to http.Handler. That has
nothing to do with routing yet whenever a new router comes out, it's non-
idiomatic. I'll take free performance anyday but not if I have to rewrite
code.

------
jrobn
I'm curious as to why they chose to use a separate echo.Context. Why not
create a type with an embedded io.ReaderCloser and a map[string]interface{}.
Then replace the req.Body (it's a io.ReaderCloser) with the custom type. You
could then write methods that take a http.Request to add/delete/modify the
piggy backing context field. No need to have a Context type in your handlers.

------
bkeroack
It appears to be storing routes in a tree structure allocated via struct
literals in router setup. I'm imagining that if performance is relying on them
always being on the stack, that would be an implementation detail of the Go
runtime and may change.

Looks like a decent implementation, but aesthetically I dislike monolithic
"frameworks" (eg: "echo.New()"). The "Go way" is to write small composable
libraries, not opaque frameworks. Gorilla would have been a good model to draw
inspiration from.

~~~
detaro
> I'm imagining that if performance is relying on them always being on the
> stack

In which case can it make a performance difference if memory is on the stack
or somewhere else in memory?

------
jjbiotech
What do you mean by zero memory allocation? The title seems contradictory. You
have to allocate at least some memory for a program to run.

Do you mean it doesn't allocate any memory per request, it just uses pre
allocated memory?

~~~
gilini
Yeah, seems like a sensationalist title tbh. The project README doesn't giving
any info to support that claim as well.

It doesn't make any sense.

~~~
_ak
The benchmark section in the README clearly shows the echo router to be the
only one of all benchmarked routers that has exactly 0 allocations per
request.

