Performance of Ruby

Discussion in 'Ruby' started by Michael Gebhart, Oct 11, 2004.

  1. Hi,

    I am just thinking about programming a serverapplication with Ruby. The
    application should manage a lot of sockets and should also be
    multithreaded. One year ago I have tried to develop a similar application
    with php. The performance was absolutely bad. No, that was not only my
    fault ;) My question is now: What about the performance of ruby? Is it
    possible to write an application using sockets and threads with ruby, but
    also with a good performance? Normally I am using C/C++ for these things.
    Sure, Ruby will not be as far as C/C++. But the php-scripts were very very
    slow. Has anyone experiences with this?

    Greetings

    Michael
    Michael Gebhart, Oct 11, 2004
    #1
    1. Advertising

  2. Michael Gebhart wrote:
    > I am just thinking about programming a serverapplication with Ruby. The
    > application should manage a lot of sockets and should also be
    > multithreaded. One year ago I have tried to develop a similar application
    > with php.


    The horror!

    > The performance was absolutely bad. No, that was not only my
    > fault ;) My question is now: What about the performance of ruby? Is it
    > possible to write an application using sockets and threads with ruby, but
    > also with a good performance? Normally I am using C/C++ for these things.
    > Sure, Ruby will not be as far as C/C++. But the php-scripts were very very
    > slow. Has anyone experiences with this?


    I have once written a threaded NNTP server with MySL backend in ruby. I
    didn't try it with many parallel users, but it was fast enough to be
    usable. If you can tell me what kind of server you are trying to create
    and how it will be used I might be able to give you more useful
    information...

    --
    http://www.mikrocontroller.net - Das Mikrocontroller-Forum
    Andreas Schwarz, Oct 11, 2004
    #2
    1. Advertising

  3. On Oct 10, 2004, at 6:29 PM, Michael Gebhart wrote:

    > Hi,
    >
    > I am just thinking about programming a serverapplication with Ruby.


    Ruby is considerably slower than C of course.

    However, network applications tend to spend a lot of time waiting on
    traffic, so I think load would need to be quite significant, before
    Ruby is slowing you down significantly.

    Could you please tell us how many users you need to accommodate and
    what the server would be doing? I'm just trying to get a feel for the
    processing involved.

    I would be pretty surprised if Ruby can't handle a couple hundred users
    if the processing isn't too intensive? Though, I will confess that I'm
    guessing.

    (I've handle over 50 in Perl at a surprisingly high loads.)

    James Edward Gray II
    James Edward Gray II, Oct 11, 2004
    #3
  4. Michael Gebhart

    Bill Kelly Guest

    ------=_NextPart_000_05D6_01C4AF00.9A646CB0
    Content-Type: text/plain;
    charset="iso-8859-1"
    Content-Transfer-Encoding: 7bit

    Hi,

    From: "Michael Gebhart" <>
    > I am just thinking about programming a serverapplication with Ruby. The
    > application should manage a lot of sockets and should also be
    > multithreaded. One year ago I have tried to develop a similar application
    > with php. The performance was absolutely bad. No, that was not only my
    > fault ;) My question is now: What about the performance of ruby? Is it
    > possible to write an application using sockets and threads with ruby, but
    > also with a good performance? Normally I am using C/C++ for these things.
    > Sure, Ruby will not be as far as C/C++. But the php-scripts were very very
    > slow. Has anyone experiences with this?


    I've just hacked up a TCP/IP throughput test of sorts,
    where you can spawn a server, and as many clients
    as you want (each client is a separate OS process.)

    The server and clients will blast data at each other
    in chunks of a specified byte size, for a specified
    number of seconds.

    The server prints some stats about the throughput as
    each client disconnects.

    Dunno if it will be useful to you. One thing of interest
    to me is that the chunk-size makes a huge difference.
    (I.e. printing 2048 bytes at a time is hugely faster than
    printing 64 bytes at a time. I expected some difference,
    of course, but not as much as I'm seeing.)

    With a server transmit chunk-size of 1024, and a client
    transmit chunk-size of 2048... (Arbitrary, just trying
    different values)... Servicing 100 clients, each of which
    connected for 60 seconds, I get:

    80.045 seconds, MB in: 190.75 (2.38 MB/sec), MB out: 30.38 (0.38 MB/sec)

    I'm running win2k with a 1.33GHz athlon CPU. The elapsed
    time of 80 seconds is because it took awhile to start up
    all 100 clients (which each ran for 60 sec.)

    Leaving the server chunk-size at 1024 but changing the
    client size to 64, I get:

    95.728 seconds, MB in: 38.51 (0.40 MB/sec), MB out: 12.15 (0.13 MB/sec)

    ...And I had trouble even starting 100 client processes
    this time... Well, the same kinds of chunk-size differences
    are apparent when running even one client... Will have
    to try this on Linux ...

    Anyway for whatever it's worth ... :)


    Regards,

    Bill


    ------=_NextPart_000_05D6_01C4AF00.9A646CB0
    Content-Type: application/octet-stream;
    name="tcptest.rb"
    Content-Transfer-Encoding: 7bit
    Content-Disposition: attachment;
    filename="tcptest.rb"

    #!/usr/bin/env ruby

    require 'thread'
    require 'socket'

    #
    # TCP client/server throughput test
    #
    # Start server like: ruby tcptest.rb --server --chunk-bytes 1024
    # Start client like: ruby tcptest.rb --run-seconds 10 --chunk-bytes 2048
    #
    # --run-seconds applies only to client
    # --chunk-bytes is the length of the string "printed" to the peer
    #
    # THE SERVER:
    # The server waits for clients to connect, and creates two threads
    # per client. The read thread reads data transmitted by the client
    # as fast as possible, and the write thread transmits blocks of data
    # to the client (chunk-bytes in length) as fast as possible.
    #
    # When a client disconnects, some megabytes-per-sec in/out statistics
    # are printed.
    #
    # Server keeps running until you kill it, e.g. with ^C
    #
    # THE CLIENT:
    # The client connects to the server, and for run-seconds time, reads
    # and writes as much data from/to the server as possible.
    # Client transmits chunk-bytes size blocks of data to the server.
    #
    # On windows, can spawn a batch of client processes like, for ex:
    # ruby -e "10.times {system('start rubyw tcptest.rb --run-seconds 60 --chunk-bytes 2048')}"

    SERVER_PORT = 12345

    Thread.abort_on_exception = false

    $server_mode = ARGV.include? "--server"
    $xmit_chunk_size = ARGV.join(' ') =~ /--chunk-bytes\s*(\d+)/ ? $1.to_i : 256
    $run_seconds = ARGV.join(' ') =~ /--run-seconds\s*(\d+)/ ? $1.to_i : 60

    $xmit_dat = "." * $xmit_chunk_size

    $total_bytes_in = 0
    $total_bytes_out = 0
    $server_start_time = nil # set when first client connects

    class ClientSession
    def initialize(client_sock)
    @client = client_sock
    @client_port = client_sock.peeraddr[1]
    @bytes_in = 0
    @bytes_out = 0
    @start_time = Time.now
    puts "client #{@client_port} connected, servicing..."
    @read_th = Thread.new {background_read}
    @write_th = Thread.new {background_write}
    end

    def stop
    @read_th.kill
    @write_th.kill
    end

    def stats(bytes_in, bytes_out, elapsed_sec)
    in_mb = bytes_in.to_f / 1024**2
    out_mb = bytes_out.to_f / 1024**2
    "MB in: %2.2f (%2.2f MB/sec), MB out: %2.2f (%2.2f MB/sec)" %
    [in_mb, in_mb/elapsed_sec, out_mb, out_mb/elapsed_sec]
    end

    def background_read
    begin
    while line = @client.gets
    @bytes_in += line.length
    end
    ensure
    @write_th.kill
    elapsed_sec = Time.now - @start_time
    puts "client #{@client_port} disconnected after #{elapsed_sec} seconds, " +
    stats(@bytes_in, @bytes_out, elapsed_sec)
    Thread.exclusive {
    $total_bytes_in += @bytes_in
    $total_bytes_out += @bytes_out
    total_elapsed_sec = Time.now - $server_start_time
    puts "cumulative totals: #{total_elapsed_sec} seconds, " +
    stats($total_bytes_in, $total_bytes_out, total_elapsed_sec)
    }
    end
    end

    def background_write
    loop do
    @client.puts $xmit_dat
    @bytes_out += $xmit_dat.length + 1 # +1 for linefeed
    end
    end
    end

    def run_server
    client_sessions = []

    abort_th = Thread.new { loop {sleep(1)} } # so will respond to ^C on win32
    server = TCPServer.new('localhost', SERVER_PORT)
    begin
    while client = server.accept
    $server_start_time = Time.now unless $server_start_time
    client_sessions << ClientSession.new(client)
    end
    ensure
    client_sessions.each {|cl| cl.stop }
    server.close
    abort_th.kill
    end
    end

    def run_client
    conn = TCPSocket.new('localhost', SERVER_PORT)
    end_time = Time.now + $run_seconds
    write_th = Thread.new { conn.puts $xmit_dat while Time.now < end_time }
    read_th = Thread.new { loop {conn.gets} }
    write_th.join
    read_th.kill
    conn.close
    end

    $server_mode ? run_server : run_client



    ------=_NextPart_000_05D6_01C4AF00.9A646CB0--
    Bill Kelly, Oct 11, 2004
    #4
  5. Michael Gebhart

    David Ross Guest

    Remeber now.. you are using windows. You will get a faster statistic if
    you are on a BSD system(doesnt mean linux). The BSD stack is one of the
    fastest implementations. Is there a place to download this benchmark
    program you created?

    --dross

    Bill Kelly wrote:

    >Hi,
    >
    >From: "Michael Gebhart" <>
    >
    >
    >>I am just thinking about programming a serverapplication with Ruby. The
    >>application should manage a lot of sockets and should also be
    >>multithreaded. One year ago I have tried to develop a similar application
    >>with php. The performance was absolutely bad. No, that was not only my
    >>fault ;) My question is now: What about the performance of ruby? Is it
    >>possible to write an application using sockets and threads with ruby, but
    >>also with a good performance? Normally I am using C/C++ for these things.
    >>Sure, Ruby will not be as far as C/C++. But the php-scripts were very very
    >>slow. Has anyone experiences with this?
    >>
    >>

    >
    >I've just hacked up a TCP/IP throughput test of sorts,
    >where you can spawn a server, and as many clients
    >as you want (each client is a separate OS process.)
    >
    >The server and clients will blast data at each other
    >in chunks of a specified byte size, for a specified
    >number of seconds.
    >
    >The server prints some stats about the throughput as
    >each client disconnects.
    >
    >Dunno if it will be useful to you. One thing of interest
    >to me is that the chunk-size makes a huge difference.
    >(I.e. printing 2048 bytes at a time is hugely faster than
    >printing 64 bytes at a time. I expected some difference,
    >of course, but not as much as I'm seeing.)
    >
    >With a server transmit chunk-size of 1024, and a client
    >transmit chunk-size of 2048... (Arbitrary, just trying
    >different values)... Servicing 100 clients, each of which
    >connected for 60 seconds, I get:
    >
    >80.045 seconds, MB in: 190.75 (2.38 MB/sec), MB out: 30.38 (0.38 MB/sec)
    >
    >I'm running win2k with a 1.33GHz athlon CPU. The elapsed
    >time of 80 seconds is because it took awhile to start up
    >all 100 clients (which each ran for 60 sec.)
    >
    >Leaving the server chunk-size at 1024 but changing the
    >client size to 64, I get:
    >
    >95.728 seconds, MB in: 38.51 (0.40 MB/sec), MB out: 12.15 (0.13 MB/sec)
    >
    >...And I had trouble even starting 100 client processes
    >this time... Well, the same kinds of chunk-size differences
    >are apparent when running even one client... Will have
    >to try this on Linux ...
    >
    >Anyway for whatever it's worth ... :)
    >
    >
    David Ross, Oct 11, 2004
    #5
  6. Michael Gebhart

    Bill Kelly Guest

    Hi,

    From: "David Ross" <>
    >
    > Remeber now.. you are using windows. You will get a faster statistic if
    > you are on a BSD system(doesnt mean linux). The BSD stack is one of the
    > fastest implementations. Is there a place to download this benchmark
    > program you created?


    The program was supposed to be attached to the message...
    Perhaps the attachment got stripped somehow? It seems to
    have come through on the mailing list OK... maybe it got
    stripped before making it out to Usenet?

    Here's a link:
    http://bwk.homeip.net/ftp/ruby/tcptest.rb

    Caution, file contains CRLF.


    Anyway, I have two linux boxes here next to my desk, and a mac
    OS X box, in addition to the win2k box... I haven't tried the
    program on the other systems yet...

    I should attempt to clarify that I'm not trying to make any
    claims of any nature about anything this program does, nor
    claiming its results are particularly significant.

    I wrote it because the OP's question reminded me that the
    program I'm working on now, in ruby, may need to handle a
    fair number of clients. So I just wanted to get a feel for
    what the, er, empirical maximum throughput rates seemed to
    be for my ruby code.


    For what it's worth, I see similar degree of degradation
    relating to smaller chunk sizes on Linux as win32. This
    is using just a single client, for 10 seconds:

    chunk-size: server=1024, client=2048
    10.005472 seconds, MB in: 170.26 (17.02 MB/sec), MB out: 137.35 (13.73 MB/sec)

    chunk-size: server=1024, client=64
    10.003608 seconds, MB in: 12.08 (1.21 MB/sec), MB out: 142.10 (14.20 MB/sec)

    Note that this is using puts(), I'll have to try send() and
    see whether the results differ... (And again, one would of
    course expect more overhead using a smaller chunk size....
    But I confess to being surprised it's that significant.)


    Regards,

    Bill
    Bill Kelly, Oct 11, 2004
    #6
  7. Hello Michael,

    MG> Hi,

    MG> I am just thinking about programming a serverapplication with Ruby. The
    MG> application should manage a lot of sockets and should also be
    MG> multithreaded. One year ago I have tried to develop a similar application
    MG> with php. The performance was absolutely bad. No, that was not only my
    MG> fault ;) My question is now: What about the performance of ruby? Is it
    MG> possible to write an application using sockets and threads with ruby, but
    MG> also with a good performance? Normally I am using C/C++ for these things.
    MG> Sure, Ruby will not be as far as C/C++. But the php-scripts were very very
    MG> slow. Has anyone experiences with this?

    One of the bottlenecks is that ruby only uses one thread and all
    sockets end up into one select call. Unfortuantely the "select" system
    call is one of the most stupid things in the Unix/Linux world and the
    most restricting (thats why BSD people use kqueue).

    So how many clients will you have ?
    On which hardware should it run ? (Multiprocessor server ?)

    You can work around some of the restrictions in ruby but all.


    --
    Best regards, emailto: scholz at scriptolutions dot com
    Lothar Scholz http://www.ruby-ide.com
    CTO Scriptolutions Ruby, PHP, Python IDE 's
    Lothar Scholz, Oct 11, 2004
    #7
  8. "Michael Gebhart" <> schrieb im Newsbeitrag
    news:ckcgh9$m23$-karlsruhe.de...
    > Hi,
    >
    > I am just thinking about programming a serverapplication with Ruby. The
    > application should manage a lot of sockets and should also be
    > multithreaded. One year ago I have tried to develop a similar

    application
    > with php. The performance was absolutely bad. No, that was not only my
    > fault ;) My question is now: What about the performance of ruby? Is it
    > possible to write an application using sockets and threads with ruby,

    but
    > also with a good performance? Normally I am using C/C++ for these

    things.
    > Sure, Ruby will not be as far as C/C++. But the php-scripts were very

    very
    > slow. Has anyone experiences with this?


    There once was a post of a success story porting a php app to ruby. The
    port was not only considerably less lines of code but also easier to
    maintain and above all, faster. Here's the original:

    http://groups.google.com/groups?hl=de&lr=&selm=

    Kind regards

    robert
    Robert Klemme, Oct 11, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. jm
    Replies:
    1
    Views:
    508
    alien2_51
    Dec 12, 2003
  2. Lalit Pant

    Performance: Ruby vs Java

    Lalit Pant, Sep 22, 2003, in forum: Ruby
    Replies:
    14
    Views:
    182
    Robert Klemme
    Sep 23, 2003
  3. Steven Jenkins

    Ruby 1.8.1 REXML performance

    Steven Jenkins, Jan 31, 2004, in forum: Ruby
    Replies:
    18
    Views:
    208
    Sean Russell
    Feb 14, 2004
  4. anne001
    Replies:
    1
    Views:
    439
  5. Software Engineer
    Replies:
    0
    Views:
    329
    Software Engineer
    Jun 10, 2011
Loading...

Share This Page