Re: NIO+Multithreaded TCPSocket listener, very low cpu utilisation

2017-11-16 Thread ade90036 via Digitalmars-d-learn

So, what is next?

Can we enable some sort of profiling to see what is going on?


Re: NIO+Multithreaded TCPSocket listener, very low cpu utilisation

2017-11-16 Thread ade90036 via Digitalmars-d-learn


Mediocre result... let me create a java equivalent program so 
we have a direct comparison..


These are the tests for a similar program in java.

bombardier -c 200 -n 1 http://localhost:8081

Bombarding http://localhost:8081/ with 1 requests using 200 
connections
 1 / 1 
[==] 100.00% 0s

Done!
StatisticsAvg  StdevMax
  Reqs/sec 24527.29   14797.09  46439
  Latency8.25ms15.52ms   235.79ms
  HTTP codes:
1xx - 0, 2xx - 1, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
  Throughput: 3.87MB/s






Re: NIO+Multithreaded TCPSocket listener, very low cpu utilisation

2017-11-16 Thread ade90036 via Digitalmars-d-learn

Result:

bombardier -c 200 -n 1 http://localhost:

Bombarding http://localhost: with 1 requests using 200 
connections
 1 / 1 
[===] 100.00% 1m24s

Done!
StatisticsAvg  StdevMax
  Reqs/sec   122.27 909.33  20363
  Latency   49.98ms   192.16ms  1.07s
  HTTP codes:
1xx - 0, 2xx - , 3xx - 0, 4xx - 0, 5xx - 0
others - 1
  Errors:
the server closed connection before returning the first 
response byte. Make sure the server returns 'Connection: close' 
response header before closing the connection - 1

  Throughput:36.89KB/s

Mediocre result... let me create a java equivalent program so we 
have a direct comparison..


Re: NIO+Multithreaded TCPSocket listener, very low cpu utilisation

2017-11-16 Thread ade90036 via Digitalmars-d-learn

On Thursday, 16 November 2017 at 18:44:11 UTC, Daniel Kozak wrote:
It works for me because I have multiple threads, but when I use 
only one
thread per pool (defaultPoolThreads(1)), it obviosly blocks, 
which is

correct behavior




Ok, let me force the: "defaultPoolThreads(8)" and let me re-test 
it.


By the way, if the socket is blocking you can remove all the 
socketSet and the socket.select as they are not needed anymore.


like this.. https://dpaste.dzfl.pl/ca09e4c54789







Re: NIO+Multithreaded TCPSocket listener, very low cpu utilisation

2017-11-16 Thread ade90036 via Digitalmars-d-learn

On Thursday, 16 November 2017 at 18:20:36 UTC, Daniel Kozak wrote:

Hmm works ok for me. What OS?

Dne 16. 11. 2017 12:05 dop. napsal uživatel "kdevel via 
Digitalmars-d-learn" :



[...]


I'm running MacOS..


Re: NIO+Multithreaded TCPSocket listener, very low cpu utilisation

2017-11-16 Thread ade90036 via Digitalmars-d-learn

On Wednesday, 15 November 2017 at 23:04:46 UTC, kdevel wrote:
On Wednesday, 15 November 2017 at 13:31:46 UTC, Daniel Kozak 
wrote:
This one works ok for me, but I am on linux: 
https://dpaste.dzfl.pl/f54decee45bc


It works, but it does not handle two connects in parallel. STR:

1. start the binary in console 1
2. telnet localhost  in console 2
3. telnet localhost  in console 3
4. enter a [RETURN] in console (3)

observed: nothing (the "thread" handling the first connect 
blocks)

expected: response

On my machine defaultPoolThreads() returns 1. This can easily 
be increased:


```
   defaultPoolThreads(8);
```

There is also another problem with Socket.select: It may return 
-1. This frequently happens when the ACCEPT socket is 
non-blocking and the select is interrupted (by the GC?) then 
errno == EINTR.


Also not having a timeout in the Socket.select of handle_socket 
allows for DOS attacks like the one above. In case of a timeout 
select also returns -1.


Hi Guys,

so i have tried the latest changes with destroy(socket) rather 
than socket.close().


Still the program is extremely slow.

I see that the httpclinet is making successfully 100 request at a 
time and then it freezes for 5/10 seconds and then it process 
another 100 request.


As Kdevel pointed out, this could be related to the Socket.select 
blocking on the interupt or it would be GC kicking in.


I also have seen the value computed for the defaultThread is not 
correct, hence i manually started the TaskPool(int thread) 
manually.


I'm going to share my benchmark program so you can guys test with 
the same tool.


Unfortunately it seems that there is some underline issue which 
is blocking the program and preventing to process all the 
incoming requests in a performant fashion, or at-least utilising 
the full CPU cycles.


reagrds

ade90036





Re: NIO+Multithreaded TCPSocket listener, very low cpu utilisation

2017-11-15 Thread ade90036 via Digitalmars-d-learn
So thanks for the suggestions,  i have fixed HTTP response not 
postman cal also parse the headers correctly!! happy days.


I have removed the duration from the Socket.select but the 
application seems to process a bunch or requests and then it 
stalls for several seconds (3/5) and then it resumes.


The httpclinet which i'm using to test the application is 
reporting: "connection timeout".


Could this be caused by the GC?

```updated 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;

string to_retlf (string s)
{
   import std.algorithm;
   import std.string;
   return s
  .lineSplitter
  .map!(a => chomp (a))
  .join ("\r\n");
}

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

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

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);

string response = "HTTP/1.1 200 OK
Server: dland:v2.076.1
Date: Tue, 11 Nov 2017 15:56:02 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 51

Hello World!".to_retlf;

new Thread({
auto listeningSet = new SocketSet();
while(true) {
listeningSet.add(listener);
if (Socket.select(listeningSet, null, null)) {
if (listeningSet.isSet(listener))// 
connection request

{
Socket socket = listener.accept();
assert(socket.isAlive);
//writefln("Connection from %s established.", 
socket.remoteAddress().toString());
auto task = task!handle_socket(socket, 
response);

taskPool.put(task);
}
}
listeningSet.reset();
}
}).start();
}



void handle_socket(Socket socket, string response) {
auto socketSet = new SocketSet();
while(true) {
socketSet.add(socket);
if (Socket.select(socketSet, null, null)) {
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(response);
}
// release socket resources now

socket.close();

break;

}
socketSet.reset();
}
```

Regards









Re: NIO+Multithreaded TCPSocket listener, very low cpu utilisation

2017-11-15 Thread ade90036 via Digitalmars-d-learn

On Tuesday, 14 November 2017 at 21:09:40 UTC, kdevel wrote:

On Tuesday, 14 November 2017 at 19:57:54 UTC, ade90036 wrote:


while(true) {
listeningSet.add(listener);
if (Socket.select(listeningSet, null, null, 
dur!"nsecs"(150)) > 0) {


Why do you ever timeout? This loop consumes 100 % (a single 
core) when idle on my machine.


Thanks for you feedback, i'll make those cosmetic changes to the 
HTTP response


Why do i specify a timeout in the Socket.select?

I have noticed that if i don't specify a timeout the 
Socket.select seems to block every so often for several seconds 
(2/5sec) and i have read in another post to specify a timeout 
value to the call.


I'll retest now.




NIO+Multithreaded TCPSocket listener, very low cpu utilisation

2017-11-14 Thread ade90036 via Digitalmars-d-learn

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. (Nic)


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

   
Hello World!");

}
// release socket resources now
socket.shutdown(SocketShutdown.BOTH);

socket.close();

break;

}
socketSet.reset();
}
}

```

You help in understanding this matter is extremelly helpfull.

Regards










Re: rawRead using a struct with variable leght

2017-06-07 Thread ade90036 via Digitalmars-d-learn

On Monday, 5 June 2017 at 16:30:53 UTC, Era Scarecrow wrote:

On Monday, 5 June 2017 at 16:04:28 UTC, ade90036 wrote:

Unfortunately the struct doesn't know at compile time what the 
size of the constant_pool array, or at-least was not able to 
specify it dynamically.


 It also won't know ahead of time how many fields, methods or 
attributes you have either.


 First I'd say all the arrays will have to be redefined to use 
[], rather than a fixed size.


 Glancing at the chapter information, you're probably not going 
to have an easy time, and will have to simply have to fill in 
the fields individually in order followed by allocating the 
arrays and probably filling/loading those immediately (although 
it's possible the array contents are done at the end, though it 
seems doubtful).


Thanks for the reply.

I guess i didnt pick such an easy task afterall.

I shall parse each fields individually.

Thanks again..



rawRead using a struct with variable leght

2017-06-05 Thread ade90036 via Digitalmars-d-learn

Hi everyone,

I'm trying out Dland, always been and have been a big fan. So to 
give it a good run i wanted to create is a java class parser, 
based on the spec released here. ( 
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html.)


The class file can be represented in the following "struct" like:

ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_infoconstant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_infomethods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}

where:
u4 == ubyte[4] --> integer
u2 == ubyte[2] --> short
u1 == ubyte[1] --> byte

I have the first 4 fields parsing, however i stumble upon an 
example where you can use a rawRead() with a struct, therefore 
representing the entire structure and then reading from rawRead() 
like


d
ClassFile[1] classFileStruct;
f.rawRead(claddFileStruct);


Unfortunately the struct doesn't know at compile time what the 
size of the constant_pool array, or at-least was not able to 
specify it dynamically.


What is the best approach to go about parsing such structure?

Should i have structs to represent the blocks of fixed fields 
from the structure and then parsing each variable (length) 
structure manually?



Something like this?


ClassHeader[1] classHeader;
f.rawRead(classHeader);

CpInfo[] cpInfo = new CpInfo[classHeader.constant_pool_count];
f.rawRead(cpInfo);
`

Really appreciate any knowledgeable suggestions.

Regards

Ade