
Comparing Node.js with Tcl - blacksqr
http://pietersz.co.uk/2015/06/beating-node-js
======
nickpsecurity
Interesting enough, Tcl was one of the past's most versatile tools. We used it
in agent-oriented programming in 90's where code could move from place to
place to cut data bill. Sandboxes were built for it. Tcl was also used in
AOLserver and a related web framework before that became a fad. So, the
author's point that Tcl is an _option_ for high-performance event driven apps
was proven when the highest traffic site in the world ran on it. I think we
have something better today in about every area due to inherent properties of
Tcl and labor invested in other solutions. Yet, Tcl delivered plenty in the
past, apparently still can, and has potential for people using that sort of
thing.

The main potential, though, is portability and future-proofing. Tcl is so
ridiculously simple that it's been implemented on about every OS and
architecture. That's batteries included due to all the existing code and
ActiveState's development tools. People can extend live apps, run shell
scripts, configure networks, and so on all using the same (or a similar)
language. Any change in underlying platform just requires porting the (simple)
lower layers. Makes Tcl a powerful future-proofing option if used judiciously.

------
phpnode
This is a very silly comparison. There's a huge difference in terms of
features and reliability between node's http module and this -
[http://pietersz.co.uk/software/dandelion-
server](http://pietersz.co.uk/software/dandelion-server)

I'm sure an equally minimal http implementation using the net module would
match or beat that, but since you'd never use either of them in production,
the results are meaningless.

~~~
graemep
I state the point of the comparison in the post: to see how TCL's event loop +
my code compres. Node's http module is fairly lightweight, and even if
something more minimal would beat my TCL code by a bit it still show what I
wanted to, that they are comparable and TCL is an option for event driven
servers (at least as far as performance goes)

~~~
woah
Sounds like your title is a distraction.

~~~
graemep
In retrospect the title is a bit too attention grabbing. If I had anticipated
the reaction I could justly be accused of writing flame bait, but I did not
expect it to get so much attention or debate - I thought just TCL people would
be interested!

~~~
mattLummus
1\. Node is not a language it is an implementation of a language, so the title
would really be TCL vs JS or Dandelion vs Node...

2\. In which case you would be opened up not only to performance benchmarks
but usability, simplicity, and features - whether you are talking about the
language or the implementation.

That being said, I have nothing against your opinions or work though and
understand that your implementation is also from 2008 :)

------
amelius
If it really matters that much how many connections per second you can handle,
perhaps Node is not the right tool for the job. Try Go instead, which also
runs on multiple cores more naturally.

------
onion2k
So some Node written by a self-confessed Node novice, based on a 'hello world'
example, and running on an old(ish) verson of Node is actually quite similar
in performance terms compared to TCL written by someone who knows how to write
a TCL server from scratch. That is not a reasonable comparison. Get someone
with some Node experience to write the Node server, then compare them.

~~~
tobik
He uses the Hello World code from [http://howtonode.org/hello-
node](http://howtonode.org/hello-node) so he did not write the Node version.

~~~
onion2k
The point it that he's comparing his TCL code (which is as fast as he could be
bothered to make it) to a 'hello world' tutorial that was written as an
introduction to Node, not as anything that was designed to demonstrate Node is
in any way fast.

~~~
Xophmeister
The 'hello world' example is a good comparator: Presumably the Node developers
have optimised the `http` library as much (if not more) than the author's Tcl
equivalent. Given that they are therefore doing the same thing, it seems a
fair test. Beyond forking new Node processes to handle more requests, I don't
think you could make it faster (likewise with the Tcl version).

That said, while it's a fair test, I don't think it's a particularly useful
one. It would be interesting to see how the two compete when they do something
equivalent but non-trivial.

~~~
graemep
I suspect that for something non-trivial, it will depend on what you are
doing. TCL is slow at most things, has fast string manipulation and very fast
regular expressions. TCL also makes it easy to write some C to do your heavy
lifting, which could be very fast indeed. On the other hand it lacks libraries
for async database access etc.

It was not meant to be more than a limited test of the TCL event loop and my
code.

~~~
beering
Node's regular expression engine will run circles around almost every other
language implementation out there.[0] This is thanks to Google's work on
V8.[1] Regexes are, maybe surprisingly, one of the few things that Node is
good at.

[0]
[http://benchmarksgame.alioth.debian.org/u32/performance.php?...](http://benchmarksgame.alioth.debian.org/u32/performance.php?test=regexdna)

[1] [http://blog.chromium.org/2009/02/irregexp-google-chromes-
new...](http://blog.chromium.org/2009/02/irregexp-google-chromes-new-
regexp.html)

~~~
klibertp
Nothing really surprising here.

Regexes are the only way to do more advanced text manipulation in JavaScript,
so they're being used far more than in other languages. Lua is similar here,
having only a couple most basic string operations built-in and relying on
regexes for anything even slightly more advanced. This makes it natural for
these languages' implementations to focus heavily on optimizing regexes.

Also, regexes are easily JITable and of course implementations having a JIT
are going to be much more performant than normal interpreters. This explains
the results of your [0] - I didn't check, but I suppose it's a vanilla Lua
interpreter and not LuaJIT.

------
tempodox
Tcl may be tolerable if what you need is on the level of some shell script.
Beyond that, it's the most god-awful language I've ever seen, barring only
classic BASIC.

So this comparison is as skewed as can be. Writing server (or even client)
software in Tcl is a pure travesty.

~~~
klibertp
I'm sorry, but you're really wrong. TCL is a beautiful language; consistent,
easy to extend both semantically and syntactically, it offers a stable and
mature ecosystem and is quite performant for an interpreter.

> it's the most god-awful language I've ever seen

I wonder, how many and which exactly languages have you seen, used and
learned? Are you sure you're versed in PLT enough to be able to really
understand all the TCL features and their impact on the language?

I'd say TCL is fairly similar to Lisps and REBOL, which makes it both simple
and hard to master. It also makes it very different from BASIC...

[EDIT: typo]

~~~
tempodox
My exact pain points with Tcl are: (1) No types at all, everything is a
string. If strings are all you have to deal with that may be enough but it
gets hairy fast for everything else. (2) Dynamic scoping rules and `uplevel` &
Co. Do I really have to say anything about that?

~~~
klibertp
> No types at all, everything is a string

At least there's no need for any kind of toString() method...

This is a design decision which makes the language smaller and easily
composable. It also helps greatly with metaprogramming, because the code
itself is also just a string - this makes Tcl homoiconic, which is a nice
property to have. Last but not least, you can easily type-tag the values you
use in more than one way if you want; you also have a built-in object system
for cases where you need more structure in order for things not to get hairy.

> Dynamic scoping rules and `uplevel` & Co

Tcl is lexically scoped by default, it just provides ways to break out from
lexical context. It's a good thing, allowing you to write for example this:
[http://rosettacode.org/wiki/Generic_swap#Tcl](http://rosettacode.org/wiki/Generic_swap#Tcl)
without any hassle. Like all design decisions it has its downsides, but it's a
powerful tool if used correctly.

Tcl is not a bad language, it's just ill-suited for you or for your use case.

~~~
tempodox
That rosetta code has NO static scoping (neither has Tcl, you got that wrong).
It uses dynamic scoping with `upvar`. It's a design decision all right, just a
really bad one.

~~~
klibertp
> That rosetta code has NO static scoping

That was the point! I pasted it as an example of what you can do with upvar,
by bypassing lexical scoping. Take a look at other entries on that page:
almost all high-level languages either pack the two variables into a list of
some kind (passed by reference) or have a specialized language construct for
this (inout etc.)

> neither has Tcl

This is very easy to disprove, take a look. This code:

    
    
        proc g {} {
            echo $a
        }
    
        proc f {} {
            set a 10
            g
        }
    
        f
    

results in an error in Tcl:

    
    
        can't read "a": no such variable
            while executing
        "echo $a"
            (procedure "g" line 2)
            invoked from within
        "g"
            (procedure "f" line 3)
            invoked from within
        "f"
            (file "main.tcl" line 35)
    

while in a dynamically scoped language, like Emacs Lisp, it would work:

    
    
        (defun g ()
          (message "%s" a))
    
        (defun f ()
          (let ((a 10))
            (g)))
    
        (f)
    

How can you argue with that, I wonder? :)

> just a really bad one.

It (upvar and uplevel) lets you easily define new control structures (think
"unless", "until", "await", things like these). I don't think you can convince
me that adding a powerful feature to the language is a bad decision... but
that's indeed a matter of preference and there are people who use Go, so I'm
not going to argue about this :)

