It also makes me mad, because by every metric save the what-you-already-know, Lua is at least comparable, if not outright superior.
It also makes me mad, because by every metric save the what-you-already-know, Lua is at least comparable, if not outright superior.
It's easy to slow the code down with "obvious" coding - which is a bad thing in a language.
Some other operations like metatable lookup might not be always the fastest.
But overall the convenience of having a 700K source tarball that compiles on any ANSI C into a modern language blows all these concerns away for my use. And the performance-critical parts can be easily pushed down to C. If they are not premature optimizations to begin with.
$ time lua -e 's="";for i=1,100000 do s=s.."-";end'
real 0m1.292s user 0m1.029s sys 0m0.108s
$ time lua -e 't={};for i=1,100000 do table.insert(t,"-");end; s=table.concat(t,"")'
real 0m0.284s user 0m0.062s sys 0m0.077s
times are somewhat bogus since it is cygwin under win7, but they give the impression of what I am talking about.
I do not argue it is a feature very coherent with the design of the language, and the immutable strings have other good properties. But if you do intensive string ops you need to watch out not to fall into the trap of treating the strings as mutable objects.
Don't get me wrong - I like Lua a lot and use it almost on a daily basis. Just that I think the posts like this may attract some new folks to try Lua out - and they deserve to know the obvious ways they can shoot themselves in the foot in order to avoid some disappointment.
$ time lua -e 't={};for i=1,100000 do table.insert(t,"-");end; s=table.concat(t,"")'
0m0.05s real 0m0.05s user 0m0.01s system
0m0.05s real 0m0.05s user 0m0.00s system
0m0.05s real 0m0.04s user 0m0.02s system
(Times on OpenBSD/amd64 4.7, Lua 5.1.4.)table.insert checks the table's length on each iteration, which dominates the string-handling time - len is O(lg n). If you just use the loop index (or otherwise cache it), it cuts the time in half:
$ time lua -e 't={};for i=1,100000 do t[i] = "-"; end; s=table.concat(t,"")'
0m0.02s real 0m0.02s user 0m0.00s system
0m0.02s real 0m0.02s user 0m0.01s system
0m0.02s real 0m0.03s user 0m0.00s system
Changing to i=1,1000000 gave me an avg. of 0.54s and 0.22s respectively. LuaJIT is probably also considerably better. (You could also just do t = string.rep('-', 100000), but that's not the point of your benchmark.)The advantage is that you get to use the same tools for client-side development and server-side development. Testing tools, interactive development tools, editor tools, etc. When you don't have to build your toolchain twice, you can make your toolchain twice as good.
In theory. Javascript needs namespaces and modules before it will be useful for real work.
Lots of people write robust, real world code in languages they are only casually familiar with. That is how you learn a language well.
The other reality you're facing here is your career. While it is gradually slowing, our field moves quickly. You need to be constantly studying and reading and learning to be any good at it at all. The reality is: grow and keep up or stop and be left behind.
To me, a new language is an opportunity. “What insights do these people have?” “What new design patterns will I learn?” “What can I take from this to my daily coding jobs?” They excite me.
Much of the complexity comes from error handling, not just the async IO. Erlang gets that right, too. I don't know how much error handling node.js does. (I plan on checking it out eventually, since my framework will be compared to it.)
I don't have a time frame yet. I'm also working on a compiler and a bunch of other stuff, and I'm really not a web developer, so it's been a fairly low priority.
If you're not worried about being "web scale", it's not hard to write an async socket server using luasocket's sockets for nonblocking TCP IO and luasocket.select for scanning for active connections. It gets bogged down once you have > 100 or so idle connections (the usual trade-offs with select apply), but it's easy to write, very portable, and (on x86) LuaJIT is amazingly fast. Contact me if you want example code.
I've been working on an actual framework for async servers (libev-based), but haven't had much free time lately.