Author Topic: _LIMIT and Windows Server 2016  (Read 2749 times)

0 Members and 1 Guest are viewing this topic.

Offline Craz1000

  • Forum Regular
  • Posts: 111
  • I'm OK
    • View Profile
    • Craz1000.net
_LIMIT and Windows Server 2016
« on: May 11, 2020, 06:37:20 pm »
I noticed on my windows server machine the _LIMIT command does not seem to work. The cpu usage always stays high for some reason. And when i run the same exe on a windows 10 machine cpu usage drops when it is supposed to.

Anyone else run into this or know a work around?

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: _LIMIT and Windows Server 2016
« Reply #1 on: May 11, 2020, 08:51:59 pm »
_LIMIT is an automatic variable speed delay.

DO
  _LIMIT 30
  PRINT "HELLO WORLD"
LOOP

Now, on a modern PC with an i9 processor, the limit will be extremely close to 1/30th of a second per loop.

Run the same program on an old 386 computer and it may have difficulty just attempting to print "HELLO WORLD" 30 times in a second.  If your old PC can only print "HELLO WORLD" 22 times per second, then the limit is going to be 0 -- it's *NOT* going to do anything.

_LIMIT slows your machine down to a MAXIMUM number of loops per second, which you specify.  If your PC can't perform more loops than that maximum, it does nothing -- which isn't going to give any time for CPU usage to drop.

It sounds like your windows server runs slower than your windows 10 machine, requiring intense CPU usage to try and perform at the_LIMIT you have set.  If that's the case, you can either swap to a hard-coded _DELAY, or else just use a lower _LIMIT on the slower machine.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Craz1000

  • Forum Regular
  • Posts: 111
  • I'm OK
    • View Profile
    • Craz1000.net
Re: _LIMIT and Windows Server 2016
« Reply #2 on: May 11, 2020, 11:16:31 pm »
Hmm. After reading your post I ran to my server with the thought... “Of course!” Then I looked at the code and saw the _Limit at that loop is set to 5. Then i sat there scratching my head.

I have high doubts the i5 in the server, that is newer than the I7 on my windows 10 machine by at least 5 years is having issues reaching over 5 loops a second. I am beginning to think it may be a Server 2016 issue that is preventing the throttle. I will try to change everything to _Delay. See what happens. It will have to wait until I get home.. silly job has me traveling.
« Last Edit: May 11, 2020, 11:19:58 pm by Craz1000 »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: _LIMIT and Windows Server 2016
« Reply #3 on: May 12, 2020, 12:21:20 am »
If you're curious, the code we use for limit is here:

Code: [Select]
void sub__limit(double fps){
    if (new_error) return;
    static double prev=0;
    double ms,now,elapsed;//cannot be static
    if (fps<=0.0){error(5); return;}
    ms=1000.0/fps;
    if (ms>60000.0){error(5); return;}//max. 1 min delay between frames allowed to avoid accidental lock-up of program
    recalculate:
    now=GetTicks();
    if (prev==0.0){//first call?
        prev=now;
        return;
    }
    if (now<prev){//value looped?
        prev=now;
        return;
    }
    elapsed=now-prev;//elapsed time since prev
   
    if (elapsed==ms){
        prev=prev+ms;
        return;
    }
   
    if (elapsed<ms){
        int64 wait;//cannot be static
        wait=ms-elapsed;
        if (!wait) wait=1;
        if (wait>=10){
            Sleep(9);
            evnt(0);//check for new events
            }else{
            Sleep(wait); 
        }
        //recalculate time
        goto recalculate;
    }
   
    //too long since last call, adjust prev to current time
    //minor overshoot up to 32ms is recovered, otherwise time is re-seeded
    if (elapsed<=(ms+32.0)) prev=prev+ms; else prev=now;
}

Looking it over, I can't see anything which would fail to compile and work properly on Windows Server 2016.

If you're proficient in c, you can c that the routine basically does as I mentioned above: automatically calculates the delay necessary to obtain a maximum fps equal to your _LIMIT.  If your program runs too slow to go over your set limit, it basically does nothing to pause operation (that's our call to Sleep, if it's needed at the end of the routine).

I'm not sure why a _LIMIT 5 might be getting ignored, without seeing the code itself.  Could it be that your program is using multiple _LIMIT statements in it, and tossing off those internal static variables?  (Such as a _LIMIT in the main loop, and then one in an input loop to check keypresses elsewhere?)

If you can share the problem code, that'd help a lot with trying to debug the issue.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline TerryRitchie

  • Seasoned Forum Regular
  • Posts: 495
  • Semper Fidelis
    • View Profile
Re: _LIMIT and Windows Server 2016
« Reply #4 on: May 12, 2020, 12:38:26 am »
Just a thought, is 2016 running in a VM? I'm currently writing my tutorial using a Windows 10 VM and _LIMIT sometimes acts all kinds of strange in there. When I move my code to Windows 7 that hosts the VM _LIMIT behaves as it should.
In order to understand recursion, one must first understand recursion.

Offline Craz1000

  • Forum Regular
  • Posts: 111
  • I'm OK
    • View Profile
    • Craz1000.net
Re: _LIMIT and Windows Server 2016
« Reply #5 on: May 12, 2020, 03:22:21 pm »
Just a thought, is 2016 running in a VM? I'm currently writing my tutorial using a Windows 10 VM and _LIMIT sometimes acts all kinds of strange in there. When I move my code to Windows 7 that hosts the VM _LIMIT behaves as it should.

All are native.


Quote from: SMcNeil
If you're proficient in c, you can c that the routine basically does as I mentioned above:

I c what you did there.

Agreed there should be no reason why Server 2016 should not throttle down.

 I will post the code when I get home. The source isnt on my work laptop. Should be home by the end of the week.
« Last Edit: May 12, 2020, 03:29:20 pm by Craz1000 »

Offline Craz1000

  • Forum Regular
  • Posts: 111
  • I'm OK
    • View Profile
    • Craz1000.net
Re: _LIMIT and Windows Server 2016
« Reply #6 on: May 14, 2020, 01:00:54 pm »
Here is the Code it is currently running.
Code: QB64: [Select]
  1. _TITLE "Score Server v1.2 - Online since: " + DATE$ + " - " + TIME$
  2.  
  3. TYPE SettingsObject
  4.     Updated AS INTEGER
  5.     Connected AS INTEGER
  6.     GamesServiced AS INTEGER
  7.     Asleep AS INTEGER
  8.  
  9. TYPE LeaderBoardObject
  10.     Score AS INTEGER
  11.     User AS STRING * 15
  12.  
  13. TYPE ClientObject
  14.     IP AS STRING * 15
  15.     Active AS INTEGER
  16.     ColR AS INTEGER
  17.     ColG AS INTEGER
  18.     ColB AS INTEGER
  19.  
  20. DIM SHARED Settings AS SettingsObject
  21. Settings.GamesServiced = 1
  22. Settings.Updated = 1
  23.  
  24. DIM SHARED Leaderboard(Settings.GamesServiced, 20) AS LeaderBoardObject
  25. DIM SHARED Client(100)
  26. DIM SHARED ClientInfo(100) AS ClientObject
  27.  
  28. DIM SHARED CONNECTION
  29. DIM SHARED UpdateTimer
  30. DIM SHARED NEWCLIENT
  31.  
  32.  
  33. UpdateTimer = _FREETIMER
  34. ON TIMER(UpdateTimer, 300) UpdateServer
  35. TIMER(UpdateTimer) ON
  36.  
  37. Display& = _NEWIMAGE(1024, 768, 32)
  38. SCREEN Display&
  39. _DEST Display&
  40.  
  41. LoadDatabase
  42.  
  43. HOST = _OPENHOST("TCP/IP:3571")
  44.  
  45. IF HOST <> 0 THEN
  46.  
  47.     DO
  48.         _LIMIT 5
  49.        
  50.         NEWCLIENT = _OPENCONNECTION(HOST)
  51.  
  52.         IF NEWCLIENT THEN
  53.             FOR x = 1 TO 100
  54.                 IF ClientInfo(x).Active = 0 THEN
  55.                     Client(x) = NEWCLIENT
  56.                     ClientInfo(x).IP = RIGHT$(_CONNECTIONADDRESS(NEWCLIENT), 15)
  57.                     ClientInfo(x).ColR = INT(RND * 155) + 100
  58.                     ClientInfo(x).ColG = INT(RND * 155) + 100
  59.                     ClientInfo(x).ColB = INT(RND * 155) + 100
  60.                     PRINT RTRIM$(ClientInfo(x).IP); " connected."
  61.                     ClientInfo(x).Active = 1
  62.                     Settings.Connected = Settings.Connected + 1
  63.                     Settings.Asleep = 0
  64.                     EXIT FOR
  65.                 END IF
  66.             NEXT x
  67.         ELSE
  68.         END IF
  69.  
  70.  
  71.  
  72.         FOR Scan = 1 TO 100
  73.             IF Client(Scan) THEN
  74.  
  75.                 COLOR _RGB(ClientInfo(Scan).ColR, ClientInfo(Scan).ColG, ClientInfo(Scan).ColB)
  76.                 IF ClientInfo(Scan).Active = 1 THEN MSG$ = WAITFORREPLY$(Client(Scan))
  77.  
  78.  
  79.                 IF MSG$ = "SENDSCORE" THEN
  80.                     SENDMSG Client(Scan), "GAMENO"
  81.                     GameID = VAL(WAITFORREPLY$(Client(Scan)))
  82.                     SENDMSG Client(Scan), "OK"
  83.                     User$ = WAITFORREPLY$(Client(Scan))
  84.                     'CheckIfUserBanned
  85.                     SENDMSG Client(Scan), "SCORE"
  86.                     Score = VAL(WAITFORREPLY$(Client(Scan)))
  87.  
  88.                     Position = 0
  89.                     FOR x = 1 TO 20
  90.                         IF Score > Leaderboard(GameID, x).Score THEN Position = x: EXIT FOR
  91.                     NEXT x
  92.  
  93.                     IF Position < 20 THEN
  94.                         FOR x = 20 TO Position STEP -1
  95.                             Leaderboard(GameID, x).Score = Leaderboard(GameID, x - 1).Score
  96.                             Leaderboard(GameID, x).User = Leaderboard(GameID, x - 1).User
  97.                         NEXT x
  98.                     END IF
  99.  
  100.                     Leaderboard(GameID, Position).Score = Score
  101.                     Leaderboard(GameID, Position).User = User$
  102.  
  103.                     IF GameID = 1 THEN PRINT "Stereospace2 Board Updated by:"; ClientInfo(Scan).IP
  104.  
  105.                     Settings.Updated = 0
  106.                     TIMER(UpdateTimer) ON
  107.                     IF Settings.Asleep = 1 THEN
  108.                         PRINT "Waking up server"
  109.                         Settings.Asleep = 0
  110.                     END IF
  111.                     MSG$ = ""
  112.  
  113.  
  114.                 ELSEIF MSG$ = "GETBOARD" THEN
  115.                     SENDMSG Client(Scan), "GAMENO"
  116.                     GameID = VAL(WAITFORREPLY$(Client(Scan)))
  117.                     SENDMSG Client(Scan), "OK"
  118.                     FOR x = 1 TO 20
  119.                         IF WAITFORREPLY$(Client(Scan)) = "NAME" THEN SENDMSG Client(Scan), RTRIM$(Leaderboard(GameID, x).User)
  120.                         IF WAITFORREPLY$(Client(Scan)) = "SCORE" THEN SENDMSG Client(Scan), STR$(Leaderboard(GameID, x).Score)
  121.                         IF WAITFORREPLY$(Client(Scan)) = "OK" THEN SENDMSG Client(Scan), "NEXT"
  122.                     NEXT x
  123.                     SENDMSG Client(Scan), "DONE"
  124.                     IF GameID = 1 THEN PRINT "Stereospace2 Board Sent to:"; ClientInfo(Scan).IP
  125.                     MSG$ = ""
  126.  
  127.                 ELSEIF MSG$ = "CLOSE" THEN
  128.                     SENDMSG Client(Scan), "GOODBYE"
  129.                     ClientInfo(Scan).Active = 0
  130.                     CLOSE #Client(Scan)
  131.                     PRINT "Connection to: "; RTRIM$(ClientInfo(Scan).IP); " closed."
  132.                     MSG$ = ""
  133.                     Settings.Connected = Settings.Connected - 1
  134.  
  135.                 ELSEIF MSG$ = "HELLO" THEN
  136.                     'CheckIfIPIsBanned
  137.                     SENDMSG Client(Scan), "OK"
  138.                     IF WAITFORREPLY$(Client(Scan)) = "READY" THEN
  139.                         Tmp = INT(RND * 256) + 1
  140.                         SENDMSG Client(Scan), STR$(Tmp)
  141.                         PW = 5 '**** REMOVED *****
  142.                         Test = VAL(WAITFORREPLY$(Client(Scan)))
  143.                         IF PW = Test THEN
  144.                             SENDMSG Client(Scan), "LOCKED"
  145.                             PRINT "Connection to: "; RTRIM$(ClientInfo(Scan).IP); " Locked."
  146.                         ELSE
  147.                             PRINT "Got:"; Test; " instead of"; PW; "disconnecting"
  148.                             ClientInfo(Scan).Active = 0
  149.                             CLOSE #Client(Scan)
  150.                             PRINT "Connection to: "; RTRIM$(ClientInfo(Scan).IP); " closed."
  151.                         END IF
  152.                         MSG$ = ""
  153.                     END IF
  154.  
  155.  
  156.                 END IF
  157.             END IF
  158.         NEXT Scan
  159.  
  160.         IF Settings.Connected = 0 AND Settings.Updated = 1 AND Settings.Asleep = 0 THEN
  161.             COLOR _RGB(100, 100, 100)
  162.             PRINT "Putting server to sleep."
  163.             Settings.Asleep = 1
  164.             TIMER(UpdateTimer) OFF
  165.         END IF
  166.  
  167.  
  168.         IF Settings.Connected < 0 THEN Settings.Connected = 0
  169.     LOOP
  170.  
  171.  
  172. SUB UpdateServer
  173.     COLOR _RGB(100, 100, 100)
  174.  
  175.     PRINT "Checking all active connections"
  176.     FOR x = 1 TO 100
  177.         IF ClientInfo(x).Active = 1 THEN
  178.             SENDMSG Client(x), "PING"
  179.             IF WAITFORREPLY$(Client(x)) <> "PONG" THEN
  180.                 ClientInfo(x).Active = 0
  181.                 CLOSE #CONNECTION
  182.                 PRINT "Connection to: "; RTRIM$(ClientInfo(x).IP); " closed."
  183.                 Settings.Connected = Settings.Connected - 1
  184.  
  185.             END IF
  186.         END IF
  187.     NEXT x
  188.  
  189.     PRINT "Backing up database"
  190.  
  191.     FOR x = 1 TO Settings.GamesServiced
  192.         IF x = 1 THEN File$ = "Stereospace2.dat"
  193.         OPEN File$ FOR OUTPUT AS #1
  194.         FOR y = 1 TO 20
  195.             PRINT #1, RTRIM$(Leaderboard(x, y).User)
  196.             PRINT #1, Leaderboard(x, y).Score
  197.         NEXT y
  198.         PRINT #1, "EOF";
  199.         PRINT #1, 0
  200.         CLOSE #1
  201.     NEXT x
  202.     PRINT "Writing to web server"
  203.     WriteWebsite
  204.     PRINT "Done"
  205.     Settings.Updated = 1
  206.     Settings.Connected = 0
  207.  
  208. SUB LoadDatabase
  209.     FOR x = 1 TO Settings.GamesServiced
  210.         IF x = 1 THEN File$ = "Stereospace2.dat"
  211.         OPEN File$ FOR INPUT AS #1
  212.         FOR y = 1 TO 20
  213.             INPUT #1, Leaderboard(x, y).User
  214.             INPUT #1, Leaderboard(x, y).Score
  215.         NEXT y
  216.         CLOSE #1
  217.         'IF x = Settings.GamesServiced THEN EXIT FOR
  218.     NEXT x
  219.  
  220. SUB WriteWebsite
  221.     OPEN "C:\inetpub\wwwroot\Scores.html" FOR OUTPUT AS #1
  222.     PRINT #1, "<html>"
  223.     PRINT #1, "<head>"
  224.     PRINT #1, "<link rel="; CHR$(34); "stylesheet"; CHR$(34); " type="; CHR$(34); "text/css"; CHR$(34); " href="; CHR$(34); "css/style.css"; CHR$(34); " />"
  225.     PRINT #1, "</head>"
  226.     PRINT #1, "<body>"
  227.     PRINT #1, "<br><br>"
  228.     PRINT #1, "<center>"
  229.     PRINT #1, "<table width=80% border=0>"
  230.     PRINT #1, "<tr><td>Stereospace 2</tr></td>"
  231.     FOR y = 1 TO 20
  232.         PRINT #1, "<tr><td>"
  233.         PRINT #1, RTRIM$(Leaderboard(1, y).User); "</td><td>"; Leaderboard(1, y).Score; "</tr></td>"
  234.     NEXT y
  235.     PRINT #1, "</table>"
  236.     PRINT #1, "</body>"
  237.     PRINT #1, "<body>"
  238.     PRINT #1, "</html>"
  239.     CLOSE #1
  240.  
  241.     COLOR _RGB(100, 100, 100)
  242.     PRINT "Database Loaded."
  243.  
  244.  
  245. '$include:'ipcommsg.bi'
  246.  
  247.  
« Last Edit: May 14, 2020, 01:02:33 pm by Craz1000 »

Offline Craz1000

  • Forum Regular
  • Posts: 111
  • I'm OK
    • View Profile
    • Craz1000.net
Re: _LIMIT and Windows Server 2016
« Reply #7 on: May 15, 2020, 12:05:18 pm »
Tried _DELAY just now. CPU usage does not drop either.

Offline Craz1000

  • Forum Regular
  • Posts: 111
  • I'm OK
    • View Profile
    • Craz1000.net
Re: _LIMIT and Windows Server 2016
« Reply #8 on: May 23, 2020, 11:40:59 pm »
Upgraded server to Windows Server 2019 today. And now cpu usage drops like it is supposed to... odd