I've been on a journey to find a way to run PicoLisp on my windows laptop for web development. At one point I started to extend miniPicolisp with win32 socket calls but that proved to be more work than I would like. Next, I tried running a virtual linux through qemu. That worked pretty well, but I wanted to see if I could eke out better performance. I then switched to coLinux and acheived even getter performance. I still wanted more, so I started looking into ersatz.
TODO:
I'd like to further this example by adding methods for the response as well and then build a complete exampleTest Setup:
1. jmeter with 30 threadsAll tests were running from my windows box. The virtual linux examples (qemu and coLinux) I set up a port forward to enable an outside connection from the host to the guest. For qemu, the networking performance of the usermode driver was the major limiter. When I ran it using apache bench on the guest, I saw around ~120 requests/sec but only ~10 when connecting external.
Benchmarks:
- PicoLisp running under qemu (~10 requests/sec) *need to rerun to confirm
- PicoLisp running under coLinux (120 requests/sec)
- ersatz w/simplewebframework (700 requests/sec)
- simplewebframework (1300 requests/sec)
Overall, I was very happy with the speed of ersatz. 2x penalty for reflection and the indirection of the ActionEvent is fine. I can't run a native PicoLisp comparison because I don't dual boot on this machine. I was really happy to see it use both cores and that memory didn't climb.
TEST #1/#2 - PicoLisp Example
I used a very basic example:(html 0 "Hello" "@lib.css" NIL "Hello World!" )
TEST #3 - ersatz example
Due to this issue I could not figure out how to write the code completely in ersatz. My first workaround was to create a simple class that took a Runnable instance and ran it. This failed for some unknown reflection exception. So, I took the swing repl example and created a custom EventAction to receive the argumentsRunner.java
import org.simpleframework.http.core.Container; import org.simpleframework.http.Response; import org.simpleframework.http.Request; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.PrintStream; import java.io.IOException; public class Runner implements Container { ActionListener evt; public void addActionListener(ActionListener evt) { this.evt = evt; } public class RequestEvent extends ActionEvent { public RequestEvent(Object src) { super(src, 1, "foo"); } //needed because I can't access this through java reflection api public PrintStream getBody() { try { Response r = (Response)this.getSource(); return r.getPrintStream(); } catch (IOException e) { System.out.println(e.toString()); return null; } } } public void handle(Request request, Response response) { evt.actionPerformed(new RequestEvent(response)); } }
go.l
(setq Container (java "Runner" T)) (java Container "addActionListener" (interface "java.awt.event.ActionListener" 'actionPerformed '((Resp) (setq Body (java Resp 'getBody)) (java Body 'println "hello world") (java Body 'close) ) ) ) (setq Con (java "org.simpleframework.transport.connect.SocketConnection" T Container)) (setq Addr (java "java.net.InetSocketAddress" T 8005)) (java Con 'connect Addr)
TEST #4 - HelloWorld.java
This one ran the fastest, but it's also pure javaimport org.simpleframework.http.core.Container; import org.simpleframework.transport.connect.Connection; import org.simpleframework.transport.connect.SocketConnection; import org.simpleframework.http.Response; import org.simpleframework.http.Request; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.io.PrintStream; import java.io.IOException; public class HelloWorld implements Container { public void handle(Request request, Response response) { try { PrintStream body = response.getPrintStream(); long time = System.currentTimeMillis(); response.set("Content-Type", "text/plain"); response.set("Server", "HelloWorld/1.0 (Simple 4.0)"); response.setDate("Date", time); response.setDate("Last-Modified", time); body.println("Hello World"); body.close(); } catch (IOException e) { } } public static void main(String[] list) throws Exception { Container container = new HelloWorld(); Connection connection = new SocketConnection(container); SocketAddress address = new InetSocketAddress(8080); connection.connect(address); } }
http://picolisp.com/wiki/?exampleersatzwebserver
28jan12 | joebo |