Recent

Author Topic: cannot receive messages; udp server with lnet  (Read 14217 times)

440bx

  • Hero Member
  • *****
  • Posts: 4070
Re: cannot receive messages; udp server with lnet
« Reply #105 on: July 09, 2022, 07:19:27 pm »
just wrapping some QueryPerformanceCounter around to measure time:
Obviously, you're messing things up somewhere because you should get the same results I get.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: cannot receive messages; udp server with lnet
« Reply #106 on: July 09, 2022, 07:27:00 pm »
Note sleep(0) is actually called yield() in other languages. A.K.A. give up time slice if others need it. It is not forced, though. That can - depending on the complexity of other pieces in an application - have a big hit on performance if after the yield slower code will be executed.
So sleep(0) is a bit nonsense in single threaded applications, but useful in muti-threaded applications.
Mind sleep(0) may yield to the OS too, so not complete nonsense, actually. But then again, most OS's do scheduling anyway.

The above is applicable for at least WINAPI. See MSDN.

Ergo: one can not time Sleep(0)..... although I wonder if it is possible to time just the context switch.
Note that Sleep(1) WILL force a context switch.
« Last Edit: July 09, 2022, 07:56:41 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: cannot receive messages; udp server with lnet
« Reply #107 on: July 09, 2022, 08:09:11 pm »
Obviously, you're messing things up somewhere because you should get the same results I get.
Code: Pascal  [Select][+][-]
  1. program TestSleep;
  2.  
  3.   uses
  4.     Windows
  5.     ;
  6.  
  7.   procedure SleepLoop(ms : DWORD);
  8.   const
  9.     COUNTER_LIMIT = 1000;
  10.  
  11.   var
  12.     counter : DWORD = 0;
  13.  
  14.   begin
  15.     writeln;
  16.     writeln('ms : ', ms, ' repeat count ', COUNTER_LIMIT);
  17.     for counter := 1 to COUNTER_LIMIT do
  18.     begin
  19.       Sleep(ms);
  20.     end;
  21.   end;
  22.  
  23. var
  24.   f, s, e: Int64;
  25. begin
  26.   QueryPerformanceFrequency(f);
  27.   QueryPerformanceCounter(s);
  28.   SleepLoop(1);  { use values 1, 8 and 16 }
  29.   QueryPerformanceCounter(e);
  30.   WriteLn('Total time: ', (e-s) / f:3:3, 's');
  31.   QueryPerformanceCounter(s);
  32.   SleepLoop(8);  { use values 1, 8 and 16 }
  33.   QueryPerformanceCounter(e);
  34.   WriteLn('Total time: ', (e-s) / f:3:3, 's');
  35.   QueryPerformanceCounter(s);
  36.   SleepLoop(16);  { use values 1, 8 and 16 }
  37.   QueryPerformanceCounter(e);
  38.   WriteLn('Total time: ', (e-s) / f:3:3, 's');
  39. end.    
I kept your code char by char. I'm sorry if reality doesn't conform to your expectations, maybe you are working on some ancient windows version, but these results are consistent with my experience for at least the past 10 years as well as my theoretical knowledge of the topic

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: cannot receive messages; udp server with lnet
« Reply #108 on: July 09, 2022, 09:32:10 pm »
Just fired up a Windows XP and a Windows 2000 VM.
Windows XP:
Sleep 1: 15.711s
Sleep 8: 18.734s
Sleep 16: 31.398s

Windows 2000:
Sleep 1: 16.535s
Sleep 8: 16.796s
Sleep 16: 32.265s

I granted both VMs 2 cores so the process could monopolize one core. The results are very similar to the modern Windows 10 Results.

So I'm quite confident in saying that this behavior is how the windows sheduler works since the introduction of the NT kernel
« Last Edit: July 09, 2022, 09:53:24 pm by Warfley »

rvk

  • Hero Member
  • *****
  • Posts: 6171
Re: cannot receive messages; udp server with lnet
« Reply #109 on: July 09, 2022, 10:51:23 pm »
With sleep(0) or no sleep at all, it is very very very fast. Insert even the lowest possible, sleep(1), the program runs very very very slow.  %)
I didn't really find it very very slow   :)

Can you give an estimate in seconds how long 1000 or 10.000 ping pongs take with my last example?


prodingus

  • Jr. Member
  • **
  • Posts: 83
Re: cannot receive messages; udp server with lnet
« Reply #110 on: July 09, 2022, 11:29:00 pm »
This thread is on fire!! :D Am I the firestarter..? :P

Anyway,
Quote
I didn't really find it very very slow   :)

Can you give an estimate in seconds how long 1000 or 10.000 ping pongs take with my last example?

Using my last example (I currently work on this "itteration" as I get the grip of it), without sleep I get 10000 ping-pongs every ~4 seconds. Using epiktimer systemsleep(1) I get  10000 every ~210 seconds.


Code: Pascal  [Select][+][-]
  1. program multi_iv;
  2. uses
  3.         winsock, SysUtils, lnet, crt, Classes, StreamIO, Windows, strutils, lcommon, epiktimer;
  4. var
  5.         buff: string;
  6.     psock:TLUDP;
  7.     psock2:TLUDP;       //tludp is pointer type by itself
  8.     i: integer= 0;
  9.     j: integer= 0;
  10.     k: integer= 0;
  11.     myip: string;
  12.     msg: string;
  13.     ET: TEpikTimer;
  14.     now: longint;
  15. type
  16.         TConsoleOutputStream = class(TStream)
  17.     function Write(const Buffer; Count: longint): longint; override;
  18. end;
  19.  
  20. function TConsoleOutputStream.Write(const Buffer; Count: longint): longint;
  21. var
  22.     charcount: longword=0;
  23. begin
  24.     WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), @Buffer, Count, charcount, nil);
  25.     Result := charcount;
  26. end;
  27.  
  28. procedure connectr(port:integer);
  29. var
  30.         Sock: TLUDP;
  31. begin
  32.         Sock := TLUdp.Create(nil);
  33.     psock:= sock;
  34.     Sock.listen(port);
  35. end;
  36.  
  37. procedure connects(addr:string; port:integer);
  38. var
  39.         Sock2: TLUDP;
  40. begin
  41.         Sock2 := TLUdp.Create(nil);
  42.     psock2:= sock2;
  43.     Sock2.connect(addr, port);
  44. end;
  45.  
  46.  
  47. begin
  48.         AssignStream(Output, TConsoleOutputStream.Create);
  49.         Rewrite(Output);
  50.     //crt.WindMaxY := 9999;
  51.     ET := TEpikTimer.Create(nil);
  52.  
  53.     myip:= GetHostIP('');
  54.     i:=0;
  55.     writeln('ip: ',myip);
  56.         write('send or listen?');
  57.         readln(k);
  58.  
  59.     if k=1 then begin
  60.         connects('1.1.1.10', 1234);
  61.         msg:='1 ping';
  62.         psock2.sendmessage(msg);
  63.     end;
  64.                                        // sock for receive, sock2 for send
  65.     begin
  66.         connectr(1234);
  67.         repeat
  68.                 pSock.CallAction;
  69.                 pSock.GetMessage(buff);
  70.             if buff <> '' then begin
  71.                 writeln(buff,' ',pSock.Socks[0].PeerAddress);
  72.                 connects(pSock.Socks[0].PeerAddress, 1234);
  73.                 psock2.sendmessage(msg+' pong'); //needed here too, else the sender is not geting reply
  74.             end;
  75.                 ET.SystemSleep(1);
  76.                 until buff <> '';
  77.  
  78.         now:= gettickcount64;
  79.                 repeat
  80.                 pSock.CallAction;
  81.                 pSock.GetMessage(buff);
  82.             if buff <> '' then begin
  83.                 if (i mod 10000 = 0) then begin
  84.                         writeln(buff,' ',pSock.Socks[0].PeerAddress,' *',uint64(gettickcount64-now));
  85.                         now:= gettickcount64;
  86.                 end;
  87.                 inc(i);
  88.                         msg:=inttostr(i);
  89.                         psock2.sendmessage(msg+' pong');
  90.             end;
  91.                 //ET.SystemSleep(1);
  92.                 until keypressed=true;
  93.     end;
  94.  
  95.     readln;
  96. end.
lazarus 2.2.0, FPC 3.2.2

rvk

  • Hero Member
  • *****
  • Posts: 6171
Re: cannot receive messages; udp server with lnet
« Reply #111 on: July 10, 2022, 12:17:50 am »
Using my last example (I currently work on this "itteration" as I get the grip of it), without sleep I get 10000 ping-pongs every ~4 seconds. Using epiktimer systemsleep(1) I get  10000 every ~210 seconds.
Ok, I see what you mean.
But with your code, the 4 seconds for 10.000 ping pongs is also a lot of time without a sleep-line.
If I use my code I get this:

Without any sleep().

Quote
ip: 172.18.144.1
1 = send or 2 = listen? 2
ping from 192.168.2.11 0
1000 ping from 192.168.2.11 78
2000 ping from 192.168.2.11 78
3000 ping from 192.168.2.11 78
4000 ping from 192.168.2.11 62
5000 ping from 192.168.2.11 63
6000 ping from 192.168.2.11 62
7000 ping from 192.168.2.11 79
8000 ping from 192.168.2.11 93
9000 ping from 192.168.2.11 94
10000 ping from 192.168.2.11 78
11000 ping from 192.168.2.11 78
press enter to quit

So 765ms (0,7 seconds) for 10.000 ping pongs.

That's because my version uses the events and is much more efficient with the code flow.
Your code flow synchronous and also takes a lot of time with that flow itself (including waiting of the other side before sending another package).

Doing a sleep(0) didn't make much difference

Quote
ip: 172.18.144.1
1 = send or 2 = listen? 2
ping from 192.168.2.11 0
1000 ping from 192.168.2.11 78
2000 ping from 192.168.2.11 62
3000 ping from 192.168.2.11 63
4000 ping from 192.168.2.11 62
5000 ping from 192.168.2.11 78
6000 ping from 192.168.2.11 63
7000 ping from 192.168.2.11 62
8000 ping from 192.168.2.11 78
9000 ping from 192.168.2.11 63
10000 ping from 192.168.2.11 78
press enter to quit

Only when doing sleep(1) it got a lot slower.

Quote
ip: 172.18.144.1
1 = send or 2 = listen? 2
ping from 192.168.2.11 0
1000 ping from 192.168.2.11 29157
2000 ping from 192.168.2.11 29375
3000 ping from 192.168.2.11 29890
4000 ping from 192.168.2.11 30094
5000 ping from 192.168.2.11 30844
6000 ping from 192.168.2.11 30750
7000 ping from 192.168.2.11 31000
8000 ping from 192.168.2.11 30984
9000 ping from 192.168.2.11 30797
10000 ping from 192.168.2.11 30734
11000 ping from 192.168.2.11 30813
press enter to quit

BTW. With my event version the CPU doesn't go over the 25% (sometimes even far less) even without any sleep-line.

I think if you really want more control over performance you would need to go with Socket or Synapse sockets in threads.

But it all depends on what you want, where you use it for and what is practical.

440bx

  • Hero Member
  • *****
  • Posts: 4070
Re: cannot receive messages; udp server with lnet
« Reply #112 on: July 10, 2022, 12:53:13 am »
I'm sorry if reality doesn't conform to your expectations, maybe you are working on some ancient windows version, but these results are consistent with my experience for at least the past 10 years as well as my theoretical knowledge of the topic
I don't think Win7 SPI qualifies as "ancient" and, it's not about my expectations, it's about how things work.  Sleep(n) is obviously not exact but, it is much more precise than what you're getting.  Neither my computer nor my version of Windows is "special" and, it works quite nicely over here.  Sleep(n) is within 30% of n.



 
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

prodingus

  • Jr. Member
  • **
  • Posts: 83
Re: cannot receive messages; udp server with lnet
« Reply #113 on: July 10, 2022, 01:11:02 am »
@rvk,

trying to use your example to verify the speed difference, I cannot compile:

Sock.OnReceive := @TMyDummy.OnReceive; gives Error: Incompatible types: got "<class method type of procedure(TLSocket) of object;Register>" expected "<procedure variable type of procedure(TLSocket) of object;Register>"
lazarus 2.2.0, FPC 3.2.2

prodingus

  • Jr. Member
  • **
  • Posts: 83
Re: cannot receive messages; udp server with lnet
« Reply #114 on: July 10, 2022, 01:13:30 am »
Side question (@everyone): Is it possible to do something like a custom sleep that waits x number of cpu cycles, or do something like the idle proccess of windows, or wait for something without polling (something else consuming cpu cycles)??

(Forgive the vagueness..)
lazarus 2.2.0, FPC 3.2.2

440bx

  • Hero Member
  • *****
  • Posts: 4070
Re: cannot receive messages; udp server with lnet
« Reply #115 on: July 10, 2022, 01:32:25 am »
Is it possible to do something like a custom sleep that waits x number of cpu cycles,
In user mode, Sleep(n) is the closest thing to that.

or do something like the idle proccess of windows,
The system idle process is not a real process.

or wait for something without polling (something else consuming cpu cycles)??
there sure is.  WaitForSingle/MultipleObject, allows a process to wait until an object is signaled and, no cpu is consumed during the wait.

(Forgive the vagueness..)
No problem, you're forgiven.  Your penance is two hello-worlds and 3 binary searches.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

prodingus

  • Jr. Member
  • **
  • Posts: 83
Re: cannot receive messages; udp server with lnet
« Reply #116 on: July 10, 2022, 02:00:08 am »
Quote
Quote from: prodingus on Today at 01:13:30 am
Is it possible to do something like a custom sleep that waits x number of cpu cycles,
In user mode, Sleep(n) is the closest thing to that.
sleep (tries to) measure time, regardless of cpu frequency, unless I am wrong. I am not asking to pause for x amount of time, but x amount of cpu cycles (don't know if its possible though).

Quote
Quote from: prodingus on Today at 01:13:30 am
or do something like the idle proccess of windows,
The system idle process is not a real process.
I am aware that its not a real process.

Quote
Quote from: prodingus on Today at 01:13:30 am
or wait for something without polling (something else consuming cpu cycles)??
there sure is.  WaitForSingle/MultipleObject, allows a process to wait until an object is signaled and, no cpu is consumed during the wait.
Any (easy to understand) reference on this? Is this, as Warfley said, similar to blocking sockets?
lazarus 2.2.0, FPC 3.2.2

rvk

  • Hero Member
  • *****
  • Posts: 6171
Re: cannot receive messages; udp server with lnet
« Reply #117 on: July 10, 2022, 02:01:01 am »
Sock.OnReceive := @TMyDummy.OnReceive; gives Error: Incompatible types: got "<class method type of procedure(TLSocket) of object;Register>" expected "<procedure variable type of procedure(TLSocket) of object;Register>"
If you use DELPHI mode you don't need to put @ before an eventname to assign it to a event-variable. In FPCObj mode yoy DO need to put @ in front of the event-proc during assignment.

You first need to examine... do you want or need DELPHI mode?
(You did put it in one of your examples, so I used it in mine and didn't put @ in front)

If you still ave mode DELPHI at the top, remove it or remove the @.

« Last Edit: July 10, 2022, 02:05:35 am by rvk »

440bx

  • Hero Member
  • *****
  • Posts: 4070
Re: cannot receive messages; udp server with lnet
« Reply #118 on: July 10, 2022, 02:16:08 am »
sleep (tries to) measure time, regardless of cpu frequency, unless I am wrong. I am not asking to pause for x amount of time, but x amount of cpu cycles (don't know if its possible though).
You're not wrong.  There is no way to pause/wait for a specifiable "x" number of CPU cycles.

Any (easy to understand) reference on this?
The MSDN documentation on it is reasonably easy to understand and there is even an example (In C of course.)

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

prodingus

  • Jr. Member
  • **
  • Posts: 83
Re: cannot receive messages; udp server with lnet
« Reply #119 on: July 10, 2022, 02:31:32 am »
Quote
f you use DELPHI mode you don't need to put @ before an eventname to assign it to a event-variable. In FPCObj mode yoy DO need to put @ in front of the event-proc during assignment.

You first need to examine... do you want or need DELPHI mode?
(You did put it in one of your examples, so I used it in mine and didn't put @ in front)

If you still ave mode DELPHI at the top, remove it or remove the @.

I had object pascal by default for the compiler option, switched to delphi and worked without edit!

I modified your program:

Code: Pascal  [Select][+][-]
  1. program pingpong;
  2.  
  3. uses
  4.   SysUtils,
  5.   lnet, lnetbase, lcommon,
  6.   crt, Classes, StreamIO, Windows;
  7.  
  8. var
  9.   Sock: TLUDP;
  10.   i: integer = 0;
  11.   [b]j: integer = 0;[/b]
  12.   k: integer;
  13.   [b]now:longint;[/b]
  14.  
  15. type
  16.   TConsoleOutputStream = class(TStream)
  17.     function Write(const Buffer; Count: longint): longint; override;
  18.   end;
  19.  
  20.   function TConsoleOutputStream.Write(const Buffer; Count: longint): longint;
  21.   var
  22.     charcount: longword = 0;
  23.   begin
  24.     WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), @Buffer, Count, charcount, nil);
  25.     Result := charcount;
  26.   end;
  27.  
  28. type
  29.   TMyDummy = class
  30.     class procedure OnReceive(aSocket: TLSocket);
  31. end;
  32. class procedure TMyDummy.OnReceive(aSocket: TLSocket);
  33. var
  34.         tmp: string;
  35. begin
  36.                 if aSocket.GetMessage(tmp) > 0 then begin
  37.            [b]inc(j);
  38.            if (j mod 10000 = 0) then begin
  39.                 writeln(tmp + ' from ' + aSocket.PeerAddress,' *',uint64(gettickcount64-now));
  40.                 now:= gettickcount64;
  41.                    end;[/b]
  42.           Inc(i);
  43.           tmp := IntToStr(i);
  44.           if k = 1 then
  45.             aSocket.sendmessage(tmp + ' ping')
  46.           else
  47.             aSocket.sendmessage(tmp + ' pong');
  48.                 end;
  49.  
  50. end;
  51.  
  52. begin
  53.   AssignStream(Output, TConsoleOutputStream.Create);
  54.   Rewrite(Output);
  55.   crt.WindMaxY := 9999;
  56.   i := 0;
  57.   [b]j:=0;[/b]
  58.  
  59.   writeln('ip: ', GetHostIP(''));
  60.   Write('1 = send or 2 = listen? ');
  61.   readln(k);
  62.  
  63.   if k = 1 then
  64.   begin
  65.     Sock := TLUdp.Create(nil);
  66.     Sock.Connect('1.1.1.10', 1234); // <-- change the receiver IP here once
  67.     Sock.OnReceive := TMyDummy.OnReceive;
  68.     Sock.sendmessage('ping');
  69.   end
  70.   else
  71.   begin
  72.     Sock := TLUdp.Create(nil);
  73.     Sock.Listen(1234);
  74.     Sock.OnReceive := TMyDummy.OnReceive;
  75.   end;
  76.  
  77.   [b]now:= gettickcount64;[/b]
  78.   repeat
  79.         Sock.CallAction;
  80.         [b]//delay(1);[/b]
  81.   until keypressed = True;
  82.  
  83.   writeln('press enter to quit');
  84.   readln;
  85. end.

it runs about the same as mine  :o

EDIT: tried to bold the changes, but didn't knew they dont work inside "code".
« Last Edit: July 10, 2022, 02:35:42 am by prodingus »
lazarus 2.2.0, FPC 3.2.2

 

TinyPortal © 2005-2018