[erlang-questions] Cowboy (Erlang) VS Haskell (Warp)

Loïc Hoguin <>
Wed Jun 26 16:48:36 CEST 2013


They are not short lived. Spawning unsupervised processes is only fine 
if you spawn the process to do exactly one thing and that thing cannot 
get the process stuck (otherwise you got an invisible leak). And you say 
it yourself, your processes do keep-alive. So they can be open for quite 
a while.

Now if a request handler gets stuck for one reason or another, and the 
process is supervised, it takes about 5 minutes to find what's wrong 
because the OTP tools and libraries do all the work for you in figuring 
it out. You don't have to think, you already know how to deal with issues.

If the process isn't supervised, you cut yourself from most of the 
documented tools and techniques, for example none of your processes will 
show up in observer. You also force your users to figure out the 
alternative ways to debug things instead of what they use everywhere 
else (see Fred's posts [1] and [2]). You have to write custom code to 
extract metrics, logging will work in unexpected ways, etc. And the 
worse part is that you essentially reimplemented a supervisor in your 
Elli server process.

Yesterday I was debugging an issue and found out file:consult/1 calls 
were getting stuck (bug report incoming, still testing things). If I was 
using Elli, I would have cursed your name many times because of all the 
time I'd have lost trying to understand how to debug this thing.

Following OTP principles is one of Cowboy's most important feature, and 
this will soon be improved again by making even request processes 
special processes that you can debug like you would a gen_server. At 
this point everything will be a special process. This is especially 
important since the Web continues moving toward long-running connections 
with Websocket, SPDY and HTTP/2.0.

[1] http://ferd.ca/poll-results-erlang-maintenance.html
[2] 
http://ferd.ca/code-janitor-nobody-s-dream-everyone-s-job-and-how-erlang-can-help.html

On 06/26/2013 11:23 AM, Knut Nesheim wrote:
> I'm a bit curious to your comments about unsupervised processes in Elli
> and Elli not following the OTP principles. Why do you think unsupervised
> request processes is a bad thing? They are short-lived and you cannot
> restart them in any meaningful way.
>
> It is true that Elli does not hook any of the processes it creates into
> a supervisor. As a user of Elli, you include the Elli "server" inside
> your supervision tree. This server starts linked acceptor processes
> which accepts a new connection, then handles the request (and
> keep-alive) before they die and the Elli server starts a new acceptor.
> If any of these processes exits abnormally, Elli knows about it. If you
> wish to find these processes to debug something, you can use
> elli:get_acceptors(ElliPid) or process_info(ElliPid, links). Mochiweb
> and Yaws does more or less the same.
>
> Knut
>
>
> On Tue, Jun 25, 2013 at 10:06 PM, Loïc Hoguin <
> <mailto:>> wrote:
>
>     You'd also end up with tons of unsupervised processes, which isn't a
>     good thing when you want to see what's wrong in your production
>     system later on (something I last did today and do quite regularly
>     when consulting). That's the biggest difference between the two,
>     Cowboy follows OTP principles, elli doesn't. Unfortunately
>     supervision does have a cost when you need to accept many
>     short-lived processes quickly, but we have done a lot of work in
>     Ranch to reduce that cost as much as possible. You could always
>     replace Ranch with something that doesn't supervise if you really
>     need to optimize to death, but so far even the handful of companies
>     that I know that use it for ad bidding and other high frequency
>     purposes haven't had the need to do that.
>
>     In short: removing supervision only looks good on benchmarks.
>
>
>     On 06/25/2013 09:52 PM, okeuday wrote:
>
>         When I use their benchmark here:
>         https://github.com/yesodweb/__benchmarks
>         <https://github.com/yesodweb/benchmarks>
>         (as mentioned here:
>         http://www.yesodweb.com/blog/__2011/03/preliminary-warp-__cross-language-benchmarks
>         <http://www.yesodweb.com/blog/2011/03/preliminary-warp-cross-language-benchmarks>)
>         to test elli, here:
>         https://github.com/knutin/elli
>
>         I get 99000 req/s.  The (httperf) test of CloudI's http_req erlang
>         service using cowboy gives 13358 req/s.  cowboy has more
>         features, so
>         that can explain the extra average latency which limits throughput.
>
>         If you want to understand why their benchmark isn't decent, read
>         this:
>         http://www.mnot.net/blog/2011/__05/18/http_benchmark_rules
>         <http://www.mnot.net/blog/2011/05/18/http_benchmark_rules>
>
>         So, if you want something faster in Erlang, you could use ellis,
>         however, keep in mind their testing isn't long enough to be
>         meaningful
>         (due to garbage collection and other impacts on performance).
>
>
>         On Tuesday, June 25, 2013 10:38:25 AM UTC-7, BM Kim wrote:
>
>              Damian Dobroczyński <qoocku <at> gmail.com
>         <http://gmail.com> <http://gmail.com>> writes:
>
>               >
>               > W dniu 25.06.2013 13 <tel:25.06.2013%2013>:51, BM Kim pisze:
>               > > Hi folks,
>               > >
>               > > First of all, I want to apologise for my poor english
>         skills,
>               > > since english is not my first language, but I'll try
>         my best
>               > > to formulate my quesions as clear as possible.
>               > >
>               > > Second, I've just begun to learn erlang, so if I'm asking
>               > > obvious "noob" questions I apologise for that too in
>         advance...
>               > >
>               > > Anywho, now to my actual question:
>               > >
>               > > I am planning to write a high-performance server
>         application in
>              erlang,
>               > > which will primarily handle HTTP requests. After some
>         reseach with
>              google,
>               > > I narrowed down my choices to cowboy, misultin and
>         mochiweb and
>              decided
>               > > to go with the cowboy library first...
>               > >
>               > > Looking at some tutorials, I've quickly built a small
>         server
>              capable of
>               > > serving static files and was eager to see first
>              benchmark-results...
>               > > I've also built a small Haskell server using Warp
>         library to
>              compare it
>               > > with erlang's cowboy...
>               > >
>               > > But my first impression was, that my cowboy server is
>         much much
>              slower
>              than
>               > > expected when serving static-files and after some
>         research I
>              found a
>              presentation
>               > > of the cowboy's author claiming that cowboy shouldn't
>         be used for
>              serving
>               > > static-files. So I modified the server code, so that
>         it replies
>              to every
>               > > request with in-memory 4Kb binary blob and compared it
>         with my
>              haskell
>              warp
>               > > server serving 4kb static file...
>               > >
>               > > this is my simple cowboy's http handler:
>               > >
>               > >
>
>         ------------------------------__------------------------------__----------
>               > >
>               > > blob() ->
>               > >     [<<0:8>> || _ <- lists:seq(1,4096)].
>               >
>               > First, try to replace blob/0 function with this:
>               >
>               >   blob() -> <<0:(4096*8)>>.
>               >
>               > Then, restart the test and report ;)
>               >
>
>
>              Hi,
>
>              Thank you very much for pointing out the obvious mistake...
>              After correcting it, I got improvement from 5940 req/s to
>         8650 req/s...
>
>              But still much slower than the haskell warp-server, which
>         has throughput
>              of 38000 req/s...
>
>              But I have another question regarding blob/0. Is it going to be
>              evaluated
>              only once (like GHC would do) since it is a pure
>         expression? I'm not
>              so sure, since erlang is not pure and any function can have
>         side-effects
>              which you can't mark as with the IO monad in Haskell...
>
>              _________________________________________________
>              erlang-questions mailing list
>          <mailto:> <javascript:>
>         http://erlang.org/mailman/__listinfo/erlang-questions
>         <http://erlang.org/mailman/listinfo/erlang-questions>
>              <http://erlang.org/mailman/__listinfo/erlang-questions
>         <http://erlang.org/mailman/listinfo/erlang-questions>>
>
>
>
>
>         _________________________________________________
>         erlang-questions mailing list
>          <mailto:>
>         http://erlang.org/mailman/__listinfo/erlang-questions
>         <http://erlang.org/mailman/listinfo/erlang-questions>
>
>
>
>     --
>     Loïc Hoguin
>     Erlang Cowboy
>     Nine Nines
>     http://ninenines.eu
>     _________________________________________________
>     erlang-questions mailing list
>      <mailto:>
>     http://erlang.org/mailman/__listinfo/erlang-questions
>     <http://erlang.org/mailman/listinfo/erlang-questions>
>
>


-- 
Loïc Hoguin
Erlang Cowboy
Nine Nines
http://ninenines.eu


More information about the erlang-questions mailing list