I am running performance tests on FiberServerSocketChannel,
the test is very simple, it's dummy http server implementation that I try to load it, but the program behavior looks buggy.
I use some tool I wrote (you can use ab or any http benchmark tool you prefer):
https://github.com/cmpxchg16/gobench
when I ran that command (no keepalive, 4 clients, 10 seconds test):
$>go run gobench.go -k=false -u http://localhost:1234 -c 4 -t 10
I got ~reasonable results, but when I try 500 clients:
$>go run gobench.go -k=false -u http://localhost:1234 -c 500 -t 10
there are a lot of socket errors, and the throughput is very poor,
also when I repeat the test over and over the whole clients was failed and the server not responding at all.
Env:
Ubuntu 13.10
JDK7 && JDK8
4 cores
16GB RAM
fibers with javaagent 0.5.0
Note that for comparison I have some dummy implementation also in Go (below):
Server source code (based on test/fibers/io):
//###################################################################
package main;
import co.paralleluniverse.fibers.Fiber;
import co.paralleluniverse.fibers.FiberForkJoinScheduler;
import co.paralleluniverse.fibers.FiberScheduler;
import co.paralleluniverse.fibers.SuspendExecution;
import co.paralleluniverse.fibers.io.FiberServerSocketChannel;
import co.paralleluniverse.fibers.io.FiberSocketChannel;
import co.paralleluniverse.strands.SuspendableRunnable;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
public class Main {
private static final int PORT = 1234;
private static final Charset charset = Charset.forName("UTF-8");
private static final CharsetEncoder encoder = charset.newEncoder();
private static FiberScheduler scheduler = new FiberForkJoinScheduler("test", 4);
public static void main(String[] args) throws Exception {
final Fiber server = new Fiber(scheduler, new SuspendableRunnable() {
@Override
public void run() throws SuspendExecution {
try {
FiberServerSocketChannel socket = FiberServerSocketChannel.open().bind(new InetSocketAddress(PORT));
int counter = -1;
while(true)
{
FiberSocketChannel ch = socket.accept();
++counter;
ByteBuffer buf = ByteBuffer.allocateDirect(1024);
int n = ch.read(buf);
String response = "HTTP/1.0 200 OK\r\n" +
"Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: 0\r\n\r\n";
n = ch.write(encoder.encode(CharBuffer.wrap(response)));
ch.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
server.start();
server.join();
}
}
//###################################################################
//###################################################################
GO:
//###################################################################
package main
import (
"net"
"os"
"runtime"
)
const (
RECV_BUF_LEN = 1024
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
println("Starting the server")
listener, err := net.Listen("tcp", "0.0.0.0:1234")
if err != nil {
println("Error Listen:", err.Error())
os.Exit(1)
}
for {
conn, err := listener.Accept()
if err != nil {
println("Error Accept:", err.Error())
return
}
go Handler(conn)
}
}
func Handler(conn net.Conn) {
defer conn.Close()
buf := make([]byte, RECV_BUF_LEN)
_, err := conn.Read(buf)
if err != nil {
println("Error Read:", err.Error())
return
}
_, err = conn.Write([]byte("HTTP/1.0 200 OK\r\nDate: Fri, 31 Dec 1999 23:59:59 GMT\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n"))
if err != nil {
println("Error Write:", err.Error())
}
}