Mochabot log - CommonJS IRC channel: #commonjs on irc.freenode.net

2010-07-26:

[7:16] <ashb> Ruby's File.expand_path is *fruity*
[7:16] <ashb> File.expand_path('../../Gemfile', __FILE__)
[7:16] <ashb> gets you the Gemfile in the directory above the file, not two dirs above
[13:35] <mschwartz> I started an interesting project over the weekend
[13:35] <mschwartz> I call it "Silk"
[13:36] <mschwartz> it is a WWW server built on top of SpiderMonkey
[13:36] <Wes-> silk silk silk
[13:36] <Wes-> mschwartz: what do cows drink?
[13:36] <mschwartz> I ran ab against it
[13:36] <mschwartz> and it's 10% faster than apache
[13:36] <Wes-> mschwartz: What's your implementation like?
[13:36] <mschwartz> apache is serving "It works!" flat HTML
[13:36] <mschwartz> silk was running a simple JavaScript to iterate the request headers and print them
[13:37] <mschwartz> it's standard prefork model
[13:37] <mschwartz> there's one runtime
[13:37] <mschwartz> each http child gets its own context
[13:37] <Wes-> mschwartz: Interesting. So you fork the JS runtime with a traditional UNIX daemon?
[13:37] <mschwartz> from the command line, you run it like this:
[13:37] <mschwartz> silk [-c childcount] [-p port] JavaScript.js [optional args...]
[13:37] <Wes-> (why bother generating a unique cx per child? Or when you say context, do you not mean JSContext * ?)
[13:38] <mschwartz> JSContext
[13:38] <mschwartz> each child runs the JavaScript.js you pass in
[13:38] <mschwartz> each script gets the optional args passed to it
[13:38] <mschwartz> I'm not even compiling the JavaScripts yet
[13:38] <mschwartz> and it's 10% faster than apache
[13:39] <mschwartz> each script is passed a global.res and global.req object (similar to helma)
[13:39] <mschwartz> much simpler at this point, obviously
[13:39] <mschwartz> the thing is, there's no "framework" forced on you
[13:40] <mschwartz> whatever you implement in your JavaScript is your framework
[13:40] <mschwartz> it obviously needs some glue functionality
[13:40] <mschwartz> and it should support commonjs style require() and modules
[13:40] <Wes-> mschwartz: You're possibly measuing a lot of apache's page-serving overhead, multiple module processing stuff
[13:40] <Wes-> (do you know how apache internals work?)
[13:40] <mschwartz> I know how apache internals work
[13:40] <Wes-> mschwartz: You could have require() today if you recompiled with GPSEE
[13:41] <Wes-> mschwartz: FWIW - if you're pre-forking, you could save JS_NewContext() and JS_InitStandardClasses() overhead by doing them in the parent
[13:41] <mschwartz> I know
[13:41] <Wes-> mschwartz: You would want to create a new global object per request, though, unless you know the request is for the same client
[13:41] <mschwartz> I know that, too
[13:42] <mschwartz> I am thinking of switching it over to use v8 (or optionally pick one)
[13:42] <mschwartz> I had a previous version of Silk that was pthreaded
[13:43] <mschwartz> the entire server side (including dynamic WWW pages) were written in C++
[13:43] <mschwartz> if you edited a C++ file in your DocumentRoot, it would fork GCC and compile it, dlopen() it and run it on request
[13:43] <Wes-> mschwartz: Nice!
[13:44] <mschwartz> the thing served dynamic WWW pages in nanoseconds
[13:44] <mschwartz> the pthread model was too scary for me to try it in production though
[13:44] <Wes-> mschwartz: So why are you so much faster than apache? (not being smart, really curious -- I have been thinking about writing an SSJS module)
[13:44] <mschwartz> It's so lightweight
[13:45] <mschwartz> apache is probably doing stat() on the flat HTML file
[13:45] <mschwartz> but you'd think stat() would be faster than building a context and global object
[13:45] <mschwartz> on the other hand, I notice Helma 1.7.0 doing helma.File.listRecursive() can take many milliseconds for even a small directory tree
[13:46] <mschwartz> I have a TServerSocket class
[13:46] <mschwartz> and a TSocket class
[13:46] <Wes-> stat() speed depends a LOT on the calling environment as well
[13:46] <mschwartz> TServerSocket is instantiated in the parent process
[13:46] <mschwartz> each child calls TSocket *s = TServerSocket.accept()
[13:46] <mschwartz> (something like that)
[13:47] <mschwartz> TServerSocket.accept() does flock() on the fd, then accept, then flock() to unlock it
[13:48] <mschwartz> stat() is slow enough that PHP caches the stat() results
[13:48] <Wes-> Interesting, running gsr against a script file vs. against a command-line script takes 0.028s vs. 0.026s. In that 0.002 I stat() and mmap()
[13:48] <Wes-> This is on leopard with a ~2 GHz machine
[13:49] <Wes-> I wish I could measure that a little more fine-grainily
[13:49] <mschwartz> gettimeofday()
[13:49] <Wes-> (truss on solaris is nice for that)
[13:49] <Wes-> Yeah, I could do that I suppose :)
[13:49] <mschwartz> new Date().getTime()
[13:49] <mschwartz> LOL
[13:50] <Wes-> Hm
[13:51] <mschwartz> Silk also buffers the output to the browser (so it can calculate content-length), which may also slow it down some
[13:51] <mschwartz> new Date().getTime() is only millisecond resolution
[13:51] <mschwartz> but gettimeofday() is usec
[13:51] <mschwartz> not guaranteed, though
[13:51] <mschwartz> there's also clock()
[13:53] <mschwartz> wes - why spidermonkey and not v8?
[13:53] <mschwartz> (GPSEE)
[13:53] <mschwartz> I chose spidermonkey in case I went pthread route, and spidermonkey has thread_safe code
[13:54] <Wes-> mschwartz: Biggest reason - v8 did not exist in August 2007. Also, community involvement, feedback, advanced JS features, my confidence that the engine will continue to evolve and serve my needs over time.
[13:55] <Wes-> mschwartz: Turns out ms resolution is enough to measure stat on my box, I get 21 ms for this: http://pastebin.mozilla.org/754647
[13:56] <Wes-> mschwartz: I suppose it's also worth pointing out that v8 doesn't run on sparc CPUs
[13:56] <Wes-> (and I use 'em all over the place)
[13:56] <Wes-> And if you think v8 is fast, wait 'till you firefox 4
[13:57] <ondras> also, gm supports some additional features not present in v8
[13:57] <ondras> such as e4x, "const" and much more
[13:57] <mschwartz> 21 ms for 1000 x stat
[13:57] <ondras> (which is a pity)
[13:57] <mschwartz> so 21 ns
[13:57] <mschwartz> er
[13:57] <Wes-> mschwartz: Yep. And that's hitting a cache in the kernel
[13:57] <mschwartz> 21 usec
[13:57] <mschwartz> well
[13:57] <mschwartz> listRecursive() is doing readdir
[13:57] <mschwartz> readdir()
[13:58] <Wes-> Yeah. readdir() can be a real bitch, especially when dirs get big and holey
[13:58] <Wes-> mschwartz: BTW, what do you think of my FFI syntax? :)
[13:59] <mschwartz> interesting
[13:59] <mschwartz> I'm getting to the point of implementing glue
[14:00] <Wes-> mschwartz: What kind of glue are you looking for?
[14:00] <mschwartz> I realize it's going to be a lot of copy/paste and tweak
[14:00] <mschwartz> I was thinking... Posix.*() functions
[14:00] <mschwartz> I might even want to implement the glue type stuff as .so files
[14:01] <mschwartz> and have the server dlopen() them
[14:01] <Wes-> mschwartz: FWIW - GPSEE strives to make all of POSIX (single unix 3) available via the gffi module, including structs, portably (so JS doesn't need to know layout details)
[14:01] <Wes-> mschwartz: I also have commonjs require() for .so files
[14:01] <mschwartz> seems like the way to go (.so)
[14:01] * Wes- nods
[14:02] <mschwartz> btw
[14:02] <mschwartz> I think I can create the globalObject in the parent
[14:02] <mschwartz> and just stuff in the req and res objects in the child over and over again
[14:03] <mschwartz> not sure if the GC() overhead is worth it though
[14:03] <mschwartz> I can always benchmark it
[14:04] <Wes-> mschwartz: glue - http://code.google.com/p/gpsee/source/browse/modules/net/net.js - node's net API implemented in JS, calling select() about the same way as thttpd works
[14:04] <Wes-> mschwartz: glue - http://code.google.com/p/gpsee/source/browse/modules/fs-base/fs-base.js - commonjs fs-base module. (note that .call() is now deprecated and un-needed)
[14:05] <Wes-> mschwartz: Are you running content-generation code in your children, or just implementing HTTPd?
[14:05] <mschwartz> child can do what it wants, no?
[14:05] <mschwartz> child can switch on hostname and do vhost (in the JavaScript.js)
[14:06] <mschwartz> the script can require() or include() other scripts to make a complex appliation
[14:06] <mschwartz> application
[14:06] <Wes-> mschwartz: Depends on what you want it to do. :) - reason I was suggesting fresh global was to avoid leaking data from request to another
[14:06] <mschwartz> or the script can do something trivial like...
[14:06] <mschwartz> check HTTP_REFERRER is me, then do res.forward() to an image file
[14:07] <mschwartz> the beauty of the process model
[14:07] <Wes-> If you're worried about data leakage, BTW, I have API for this which covers both JS modules and C code. (GPSEE realms) -- we needed it because of worker threads and multiple runtimes. (need multiple runtimes for the debugger, which itself is written in JS)
[14:07] <mschwartz> is you can do 100 keep-alive requests, leaking memory the whole time
[14:07] <mschwartz> then exit()
[14:07] <Wes-> mschwartz: You are doing pre-fork but don't reuse across different connections?
[14:07] <mschwartz> what do you use to talk to the debugger?
[14:07] <Wes-> mschwartz: JSD
[14:08] <mschwartz> reuse what?
[14:08] <Wes-> mschwartz: I have a local fork of the old jsdb project, with a local JSD fork
[14:08] <Wes-> mschwartz: the child
[14:08] <mschwartz> oh
[14:08] <mschwartz> yeah
[14:08] <mschwartz> the child does:
[14:08] <mschwartz> if (my_request_count > max_request_count) exit();
[14:08] <mschwartz> plus keep alive
[14:09] <mschwartz> so you can serve 1000 requests
[14:09] <mschwartz> 30 keep-alive at a time
[14:09] <mschwartz> (tunable parameters)
[14:09] <Wes-> mschwartz: You can tune the GC to not hurt much in a leak,leak,leak child - there is a test and tunable which basically won't trigger GC until the heap size increases a LOT (e.g. doubles)
[14:10] <mschwartz> the pthread/C++ version of silk was pretty amazing
[14:10] <mschwartz> it had several caches
[14:10] <mschwartz> one for static objects
[14:10] <mschwartz> one for dynamic objects
[14:10] <mschwartz> so serving an image (or other static file) was done from shared memory almost all the time
[14:11] <mschwartz> mmap() rocks
[14:11] <mschwartz> for doing that sort of thing with processes
[14:12] <Wes-> Yep, it's absolutely perfect. A little trickier with the pre-fork model, would be interesting to have a pipe back to the parent, feeding it filenames to map for future children
[14:12] <Wes-> Although, there's one other API to consider, what the heck is it... It's the one that allows you to spool right from disk controller to network card
[14:12] <Wes-> I guess that's probably only realistic for large files any how
[14:12] <mschwartz> there's another one, too
[14:13] <mschwartz> I think apache uses it to bypass socket writes
[14:13] <Wes-> Ah - I'm thinking of sendfile()
[14:13] <Wes-> Maybe what you're thinking of, too?
[14:13] <mschwartz> maybe
[14:14] <Wes-> I know there is an APR version of it
[14:14] <Wes-> mschwartz: Is your work on silk foss?
[14:15] <mschwartz> nope
[14:15] <Wes-> mschwartz: Bummer, it sounds cool.
[14:15] <mschwartz> oh
[14:15] <mschwartz> I just haven't decided what to do with it yet
[14:15] <mschwartz> it will most likely be open source
[14:15] <Wes-> mschwartz: If you want to try a GPSEE underpinning - let me know, I can still help (was hoping to just do a port for you :) )
[14:16] <mschwartz> you guys like github...
[14:16] <mschwartz> LOL
[14:16] <Wes-> Actually, I prefer google code.. but any DAG VCS is fine by me
[14:17] <mschwartz> man 2 splice
[14:17] * Wes- has considered buying the license plate DAG BTW
[14:17] <mschwartz> hah
[14:17] <mschwartz> I tell you what
[14:17] <mschwartz> I'll put it on github tonight
[14:17] <Wes-> mschwartz: Is that anything like weave? I don't have splice on either leopard or solaris
[14:17] * Wes- dances
[14:18] <mschwartz> I want to set up a real message board for discussion though
[14:18] <Wes-> mschwartz: I'll fork it and make it build on GPSEE tonight if i have the chance. Might be useful, would at least be a fun thing to play with
[14:18] <mschwartz> I HATE google groups
[14:18] <mschwartz> I don't mind if you commit to the main fork
[14:18] <Wes-> mschwartz: I do too, but I like out sourcing
[14:18] <mschwartz> I have the server to set up a real message board
[14:18] <Wes-> mschwartz: We'll see how much surgery is involved. Hopefully, very little.
[14:19] <mschwartz> one where you can put source code in a post
[14:19] <mschwartz> and it syntax highlights
[14:19] <mschwartz> track bugs
[14:19] <mschwartz> post attachments
[14:19] <Wes-> mschwartz: I have servers galore, but, seemingly no time at all. Project Kenai looked like it was going in an awesome direction (mercurial, bugzilla, forums) - but then they locked me out of my account and then oracle killed it
[14:19] * Wes- sighs
[14:20] <mschwartz> there is one other thing I'm tempted to do with silk
[14:20] <mschwartz> that is to embed PHP as well
[14:20] <Wes-> mschwartz: There is a spidermonkey project somewhere that lets jsapi and php interoperate
[14:20] <mschwartz> so a single Silk server could run WordPress and custom JS app at the same time
[14:20] <Wes-> mschwartz: he does it by translating at the jsval / zval level - even function calls work
[14:20] <mschwartz> oh
[14:21] <mschwartz> I don't want to mix the code
[14:21] <Wes-> I wish I could remember the name of that project
[14:21] <mschwartz> just to be able to run out of the box PHP apps
[14:21] <Wes-> mschwartz: c'mon, be brave! :D
[14:21] <Wes-> mschwartz: But I hear you. That's why I've been looking at doing a GPSEE Apache Module
[14:21] <Wes-> mschwartz: Currently, I haven't figured out /what/ I'm doing for web work; I run CGI for God's sake, although I'm working on a Solaris port of APE to play with
[14:22] <mschwartz> ouch
[14:22] <mschwartz> those SPARC chips make porting code a problem these days
[14:22] <Wes-> Yeah, good thing I don't need any volume (10 requests/sec is PLENTY and I can do that easily)
[14:22] <mschwartz> I am always searching for the microsecond speed server side script
[14:23] <Wes-> mschwartz: This isn't a sparc problem so much as a solaris/kqueue/epoll/etc problem. Author wrote bare-metal code for Leopard and Linux
[14:23] <mschwartz> my view of the future of WWW is you serve a WWW page that's simple
[14:23] <mschwartz> it has JS on it
[14:23] <mschwartz> the JS does a bazillion RPC like requests
[14:23] <Wes-> mschwartz: That's similar to the APE model
[18:34] <WesMac> anybody on Snow Leopard willing to help me test the GPSEE build system?

 

 

Logs by date :