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 in Sydney.

I have worked at places such as Google, News Corp, Fox Sports, NineMSN, FetchTV, Woolworths, and Westpac, among others. If you're looking for a good iOS developer, drop me a line!

Get in touch:
my resume

 Subscribe via RSS