[racket] My toy web app's performance: Racket vs Perl vs Ruby

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Wed Apr 18 15:06:12 EDT 2012

I'm surprised you don't get any difference with the new version.

This is very surprising for me. Here are results from my tiny Macbook Air:

% ab -c 20 -n 10000 http://localhost:8000/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        Racket
Server Hostname:        localhost
Server Port:            8000

Document Path:          /
Document Length:        8630 bytes

Concurrency Level:      20
Time taken for tests:   14.501 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      88090000 bytes
HTML transferred:       86300000 bytes
Requests per second:    689.59 [#/sec] (mean)
Time per request:       29.003 [ms] (mean)
Time per request:       1.450 [ms] (mean, across all concurrent requests)
Transfer rate:          5932.24 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       3
Processing:     2   29  16.0     26     213
Waiting:        1   21  14.3     19     198
Total:          2   29  16.0     26     213

Percentage of the requests served within a certain time (ms)
  50%     26
  66%     30
  75%     34
  80%     36
  90%     43
  95%     51
  98%     65
  99%     84
 100%    213 (longest request)

with this server:

#lang racket/base
(require racket/list
         web-server/servlet-env
         web-server/http)

(serve/servlet
 (λ (req)
   (response
    200 #"Okay"
    (current-seconds) TEXT/HTML-MIME-TYPE
    empty
    (λ (op)
      (for ([i (in-range 8630)])
        (write-byte 42 op)))))
 #:port 8000
 #:command-line? #t
 #:servlet-regexp #rx"")

that serves dynamic content of similar size to what your Perl example does.

Jay

On Wed, Apr 11, 2012 at 3:03 PM,  <joshua at anwu.org> wrote:
>
> Racketeers,
>
> I'm new to the language, and loving it.  I'm having trouble getting good performance out of my little toy web app, however.
>
> I wrote this fake billing app to play with some new languages (like Racket) and some other webdev ideas I've had (like client-side
> templating with jQuery and mustache).  As such, I have the same JSON api written in Perl, Ruby, and Racket (working on node.js
> and Haskell).  Perl runs under Dancer and Starman, ruby under Sinatra and Unicorn, and Racket under nohup and its own included webserver.
> All are running on the same machine.  Each connects to a postgres db, executes some queries from a config file, and returns JSON
> to the client.
>
> I've been running apache bench against all three, and the performance of Racket vs Perl and Ruby has been... disheartening.  I
> compiled the racket code with 'raco exe' before running it, but Perl and Ruby both blow it away.  The racket executable also
> seems to grab and hold a lot of memory, even though I told it to be stateless.  It also tends to have failures.
>
> ab -c 20 -n 10000 <uri>
>
>
> Perl:
>
> Concurrency Level:      20
> Time taken for tests:   86.100 seconds
> Complete requests:      10000
> Failed requests:        0
> Write errors:           0
> Total transferred:      88150000 bytes
> HTML transferred:       86300000 bytes
> Requests per second:    116.14 [#/sec] (mean)
> Time per request:       172.199 [ms] (mean)
> Time per request:       8.610 [ms] (mean, across all concurrent requests)
> Transfer rate:          999.82 [Kbytes/sec] received
>
>
> Ruby:
>
> Concurrency Level:      20
> Time taken for tests:   102.914 seconds
> Complete requests:      10000
> Failed requests:        0
> Write errors:           0
> Total transferred:      88480000 bytes
> HTML transferred:       86050000 bytes
> Requests per second:    97.17 [#/sec] (mean)
> Time per request:       205.827 [ms] (mean)
> Time per request:       10.291 [ms] (mean, across all concurrent requests)
> Transfer rate:          839.60 [Kbytes/sec] received
>
>
> Racket:
>
> Concurrency Level:      20
> Time taken for tests:   139.059 seconds
> Complete requests:      10000
> Failed requests:        687
>   (Connect: 0, Receive: 0, Length: 687, Exceptions: 0)
> Write errors:           0
> Total transferred:      9421469 bytes
> HTML transferred:       7100095 bytes
> Requests per second:    71.91 [#/sec] (mean)
> Time per request:       278.119 [ms] (mean)
> Time per request:       13.906 [ms] (mean, across all concurrent requests)
> Transfer rate:          66.16 [Kbytes/sec] received
>
>
> I'm hoping it's just inexperience on my part - maybe my Racket code just sucks.  Or maybe it's that I'm trying to
> stay functional and avoid mutation, which I don't bother with in the other two. Anyone interested in looking at
> the code and telling me what I'm doing wrong, or could do better?  I would love to use Racket for more serious
> projects.
>
> https://github.com/TurtleKitty/CalicoBill
>
>
> Thanks,
> TurtleKitty
>
>
>
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users



-- 
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93


Posted on the users mailing list.