Version 16 of More Tcl socket performance

Updated 2005-07-06 21:53:17

CL often has occasion to listen on TCP ports for process control data. My general advice to clients is that they work in Tcl whenever possible, and that they not fret about performance in particular. While there's no question that C is "closer to the silicon", and is definitely faster for basic bit- and byte-wrangling, Tcl generally is plenty fast.

This page reports on one attempt to quantify that counsel. My model is a client which connects on a port, receives a sequence of bytes, twiddles their bits slightly, and computes a result. Here's the corresponding Tcl code:

    proc read_data {} {
        set sum 0
        set count 0
        set mask 0x5A
            # Choose any host other than the local one, and the difference between C and Tcl
            # shrinks even more.  5837 is a port chosen merely for convenience.
        set channel [socket localhost 5837]
        fconfigure $channel -encoding binary
        while 1 {
            set data [read $channel]
            foreach item [split $data {}] {
                incr count
                    # In process-control contexts, I often need to mask off a few bits and manipulate
                    # the resultingjust  value.  Neither $mask nor the single right-shift are particularly
                    # meaningful; they're just the results of experiments to yield suggestive, quantifi-
                    # able results. 
                set value [scan $item %c]
                set addend [expr {($mask & $value) >> 1}]
                incr sum $addend
                # puts -nonewline "$value ($addend) "
            }
            if [eof $channel] break
        }
        puts "\nSum is '[format %x $sum]'."
        return $count
    }

    set result [time {set count [read_data]} 3]
    puts $result
        # This is a hackish way to extract the time.
    set microseconds [lindex $result 0]
    set quotient [expr round(double($microseconds) / $count)]
    puts "$quotient microseconds per byte received."

On a generic Linux x86 host at hand, when I blasted random data from a simple server (see below) as fast as possible, I observed these results:

                                 simple Tcl client                                   simple C client

     100 bytes            19 microseconds per byte received         36
     300                     10                                                           14
    1000                      8                                                             6
   10000                     6                                                             2
   30000                     6                                                             2
 100000                     6                                                             2      

My summary: don't choose C because of performance. Unless message sizes are quite large, or you're willing to tune your C coding carefully, you can safely assume that Tcl's performance penalty is 60% at most (an amount easily lost in network, UI, and other noise), and possibly far less.

[Still to do: exhibit simple C client and model server, and comment on Windows vs. Unix.]


See also "Tcl socket performance", "Socket performance analysis", "How to measure performance", and the rest of Category Performance.