Firstly, a note: The aim of this article is more of a step by step 'first steps with D' kinda thing, i'm not trying to make too much of a point about D's performance here. Calm down, redditors! ;) Environment I'm working with Windows XP here, which adds a few complications you wouldn't see on other platforms. Using the Digitalmars' C compiler ( from here, unzipped to c:\dm. Also using the Tango D package ( from here, unzipped to c:\dmd. Libev Libev is a high performance event loop that i'm using to wait for incoming port 80 connections. It's here: Docs are here: Download the CVS version (it contains fixes so it'll compile) here: Unzip it all into a folder, and create a 'myev.c' file in that folder, with the following contents: #define EV_STANDALONE 1 // so i don't need a config.h file #define EV_SELECT_IS_WINSOCKET 1 // windows //#define EV_USE_POLL 1 // uncomment me for unix //#define EV_USE_EPOLL 1 // uncomment me for gnu/linux //#define EV_USE_KQUEUE 1 // uncomment me for bsd/osx //#define EV_USE_PORT 1 // uncomment me for solaris #define EV_STAT_ENABLE 0 // disable file watching #include "ev.c" To compile it, do the following from that folder (you'll get a couple of warnings which you can ignore): \dm\bin\dmc myev.c -c This will produce a myev.obj which you'll need later Server 1: Create a new folder for the simple 'D' server. You'll need the ev.d with the libev bindings, which you can download or copy n paste from here. 2: Copy the 'myev.obj' that you compiled earlier from the libev folder into this folder. 3: You'll then create the 'server.d' which is the main point of this article:
import ev; 

extern (C)
   static void libev_cb (ev_loop_t *loop, ev_io *w, int revents)
  int _open_osfhandle (long osfhandle, int flags);

ServerSocket listener;
void main() 
  listener = new ServerSocket (new InternetAddress(80));
  int fd = _open_osfhandle(listener.fileHandle,0); // for win32: convert from socket to file descriptor

  // Start libev
  ev_loop_t* loop = ev_default_loop(0); 
  ev_io io_watcher; 
  ev_io_init(&io_watcher, &libev_cb, fd, READ); 
  ev_io_start(loop, &io_watcher); 
  ev_loop(loop, 0); 

void callback()
  // accept the connection
  SocketConduit request = listener.accept;

  // wait for the 'http get ...'
  char[1024] response;
  uint len = (response);
  Cout (response[0..len]).newline; // you'll want to comment this out if you run apachebench against this...

  // send HTML
  request.output.write("HTTP/1.1 200 OK

<style>body {font-family:trebuchet ms;background:#424242;color:#fff;text-align:center;margin-top:10em;}</style>
<body><h1>Your 'D' web server is alive!</h1></body>

To compile and run all this, do the following: \dmd\bin\dmd server.d ev.d myev.obj server Next test it in your browser, by browsing to 'localhost': [[posterous-content:zuyleIbpsAFDquIexnoo]] Voila! And if i do an apachebench (ab -n 10000 -c 100), my requests-per-second is 2071 for an 2 years old P4-3ghz, and it only uses 2.4mb of memory, which is pretty impressive considering each Ruby on Rails Mongrel typically uses ~30megs last time i checked. I guess the next question is: why doesn't someone make a super-scalable web framework using the speed/efficiency and ease of D? If any of this doesn't work, make sure you post a comment so i can sort it out - cheers.

Thanks for reading! And if you want to get in touch, I'd love to hear from you: chris.hulbert at gmail.

Chris Hulbert

(Comp Sci, Hons - UTS)

iOS Developer (Freelancer / Contractor) in Australia.

I have worked at places such as Google, Cochlear, Assembly Payments, News Corp, Fox Sports, NineMSN, FetchTV, Coles, Woolworths, Trust Bank, and Westpac, among others. If you're looking for help developing an iOS app, drop me a line!

Get in touch:
[email protected]

 Subscribe via RSS