NIO+Multithreaded TCPSocket listener, very low cpu utilisation

ade90036 andrea.rizzini at gmail.com
Tue Nov 14 19:57:54 UTC 2017


Hi Forum,

Let's cut the chase, i'm a newby in Dlang. I have 15+ years 
experience in java and 7+ years experience in C++.

I found D very fascinating and the sugar coated syntax very 
appealing to my style of coding. (groovy like)

I've been trying to learn Dland and  bring it thought the motions 
by creating a very simple and basic TCPSocket listerner that when 
you send a request it responds with an HTTP response over a 
specific port. (localhost:4445)

I have the code working on a worked thread and when the socket 
accept() it defers the processing of the request (socket) in a 
different thread backed by TaskPool(8).

i have 8 logical core, which is a macBook pro retina 16gb, i7.

What i'm expecting to see is the CPU of my 8 core I7 go through 
the roof and nearly melt (hope not) but at-least have the fan on 
at sustainable level and obtain full CPU utilisation.

What i'm benchmarking it against is a JAVA NIO2 implementation. 
This implementation achieves very high CPU utilisation and high 
throughput. The process utilisation averages 400% at times and 
the fan is really searching for cold air. (Niceeee)

However, when i run the Dlang program i see i very poor CPU 
utilisation. The fan is always in silent mode.

Not sure if you are familiar with MacOS cpu metrics, but they are 
based per core. So dland program reports 100% under the process 
monitor (which equates to one core) and the overall system CPU 
utilisation is 13%.

I would have expected to see a much higher cpu utilisation but it 
is not happening. I have been trying different variation of the 
same implementation but not luck.

I'm starting to suspect that this is an BUG related to the macOS 
but i would like to confirm or atleast have a second pair of eyes 
having a look.

```Code

import std.algorithm : remove;
import std.conv : to;
import core.thread: Thread;
import std.socket : InternetAddress, Socket, SocketException, 
SocketSet, TcpSocket, SocketShutdown;
import core.time : Duration, dur;
import std.stdio : writeln, writefln;
import std.parallelism : task, TaskPool;

void main(string[] args)
{
     ushort port;

     if (args.length >= 2)
         port = to!ushort(args[1]);
     else
         port = 4447;

     auto listener = new TcpSocket();
     assert(listener.isAlive);
     listener.blocking = false;
     listener.bind(new InternetAddress(port));
     listener.listen(100);
     writefln("Listening on port %d.", port);

     auto taskPool = new TaskPool(8);

     new Thread({
         auto listeningSet = new SocketSet();
         while(true) {
             listeningSet.add(listener);
             if (Socket.select(listeningSet, null, null, 
dur!"nsecs"(150)) > 0) {
                 if (listeningSet.isSet(listener))        // 
connection request
                 {
                     Socket socket = null;
                     scope (failure)
                     {
                         writefln("Error accepting");

                         if (socket)
                             socket.close();
                     }
                     socket = listener.accept();
                     assert(socket.isAlive);
                     assert(listener.isAlive);
                     //writefln("Connection from %s established.", 
socket.remoteAddress().toString());
                     auto task = task!handle_socket(socket);
                     taskPool.put(task);
                 }
             }
             listeningSet.reset();
         }
     }).start();
}

void handle_socket(Socket socket) {
     auto socketSet = new SocketSet();
     while(true) {
         socketSet.add(socket);
         if (Socket.select(socketSet, null, null, 
dur!"nsecs"(150)) > 0) {
             char[1024] buf;
             auto datLength = socket.receive(buf[]);

             if (datLength == Socket.ERROR)
                 writeln("Connection error.");
             else if (datLength != 0)
             {
                 //writefln("Received %d bytes from %s: \"%s\"", 
datLength, socket.remoteAddress().toString(), buf[0..datLength]);
                 //writefln("Writing response");

                 socket.send("HTTP/1.1 200 OK
                                                Server: 
dland:v2.076.1
                                                Date: Tue, 11 Nov 
2017 15:56:02 GMT
                                                Content-Type: 
text/plain; charset=UTF-8
                                                Content-Length: 32

                                                
<html><head></head><body>Hello World!</body></html>");
             }
             // release socket resources now
             socket.shutdown(SocketShutdown.BOTH);

             socket.close();

             break;

         }
         socketSet.reset();
     }
}

```

You help in understanding this matter is extremelly helpfull.

Regards










More information about the Digitalmars-d-learn mailing list