Official Everybody Edits Forums

Do you think I could just leave this part blank and it'd be okay? We're just going to replace the whole thing with a header image anyway, right?

You are not logged in.

Donate!

pls donate


#1 2017-03-17 21:57:48

Tomahawk
Forum Mod
From: BiH
Joined: 2015-02-18
Posts: 2,133

(More) Accurate Thread.Sleep

Now that there's no artificial block limit, you can send blocks with zero delay between them. Despite this, sensible bot coders will still choose to have a small delay between blocks so that they don't DC themselves, the bot or other players and ruin the reputation of bots in general.

With that piece of advice subtly given, we now need a simple way to delay for a few milliseconds between each block we send.

Thread.Sleep is pretty inaccurate for small delays (<15ms), because of reasons. Here's some testing I did:

Thread.Sleep(5);

Expected delay: 5ms

Actual example delays: 19.8ms, 15.9ms, 18.6ms, 9.2ms, 15.9ms, 14.5ms, 15.9ms  ~ etc.
Average delay (calculated from 1000 repeats): 15.6ms

This means that every time you've been writing Thread.Sleep(9); to get that maximum draw speed, it's actually been sending blocks only every 15ms, and any attempt to test the maximum draw limit using Thread.Sleep has been wildly inaccurate due to the random variations in the actual sleep duration.

Simple solution:
Five minutes of googling gave me this code. The timeBeginPeriod function increases the accuracy of Thread.Sleep, and should only be used when you need accurate delays because it increases CPU usage and power consumption.

Test:

timeBeginPeriod(1);

Thread.Sleep(5);

timeEndPeriod(1);

Expected delay: 5ms

Actual example delays: 5.15ms, 5.04ms, 5.16ms, 5.88ms, 5.18ms, 5.23ms  ~ etc.
Average delay (calculated from 1000 repeats): 5.50ms

Yay, Thread.Sleep is now much more accurate for small delays!


One bot to rule them all, one bot to find them. One bot to bring them all... and with this cliché blind them.

Offline

#2 2017-03-17 22:00:18

HG
Member
Joined: 2017-08-16
Posts: 2,219

Re: (More) Accurate Thread.Sleep

That's what asynchronous methods are for.

Offline

#3 2017-03-17 22:14:36

Tomahawk
Forum Mod
From: BiH
Joined: 2015-02-18
Posts: 2,133

Re: (More) Accurate Thread.Sleep

HG wrote:

That's what asynchronous methods are for.

The key word here is "simple". Async is overkill.


One bot to rule them all, one bot to find them. One bot to bring them all... and with this cliché blind them.

Offline

#4 2017-03-17 22:16:11

HG
Member
Joined: 2017-08-16
Posts: 2,219

Re: (More) Accurate Thread.Sleep

Then create a small loop with delays that doesn't make the entire program get stuck.

Offline

#5 2017-03-17 22:21:23, last edited by LukeM (2017-03-17 22:26:28)

LukeM
Dev Team
From: England
Joined: 2016-06-03
Posts: 2,838
Website

Re: (More) Accurate Thread.Sleep

my favourite solution is to hava a normal timer / sleep / whatever but place multiple blocks per wait, this way you dont need any fancy code or anything, but can place the max of (as far as I have been able to (tested using multiple solutions)) 2000 ish blocks per second

Edit: note- using begin and end period wont allow you to get close to this speed because even if you could get to a resolution of 1ms, then you would only be able to place 1000 per second

Also, generally you shouldnt use timerBeginPeriod to get more accurate resolutions because it can slow down your computer, increase power consumption, and I think a few other bad things

Offline

#6 2017-03-17 23:22:25

Tomahawk
Forum Mod
From: BiH
Joined: 2015-02-18
Posts: 2,133

Re: (More) Accurate Thread.Sleep

HG wrote:

Then create a small loop with delays that doesn't make the entire program get stuck.

What? Nowhere have I said to put thread sleeps in the main GUI thread and freeze the bot. It's the coder's responsibility to send blocks in a new thread or wherever, and not relevant to this topic, which is purely about improving the resolution of Thread.Sleep.

destroyer123 wrote:

my favourite solution is to hava a normal timer / sleep / whatever but place multiple blocks per wait, this way you dont need any fancy code or anything, but can place the max of (as far as I have been able to (tested using multiple solutions)) 2000 ish blocks per second

Edit: note- using begin and end period wont allow you to get close to this speed because even if you could get to a resolution of 1ms, then you would only be able to place 1000 per second

It's not my intention here to send blocks insanely quickly. Nobody's done an methodical stress-test yet on a world filled with players, but if it turns out that everyone can handle 5ms (i.e. 200 blocks/second) then the code in this thread allows the bot to send at around that rate. 2000 blocks/s would absolutely cause players to DC.

destroyer123 wrote:

Also, generally you shouldnt use timerBeginPeriod to get more accurate resolutions because it can slow down your computer, increase power consumption, and I think a few other bad things

You're advised not to set it at 1ms resolution and leave it there without utilising it, but there's nothing wrong with using it. Modern CPUs don't run at their maximum frequency unless under full load, so boosting the clock rate still leaves the CPU well within its limits. Doing this is no more harmful than starting up and playing a PC game.


One bot to rule them all, one bot to find them. One bot to bring them all... and with this cliché blind them.

Offline

#7 2017-03-17 23:38:24, last edited by LukeM (2017-03-17 23:42:35)

LukeM
Dev Team
From: England
Joined: 2016-06-03
Posts: 2,838
Website

Re: (More) Accurate Thread.Sleep

Tomahawk wrote:
destroyer123 wrote:

It's not my intention here to send blocks insanely quickly. Nobody's done an methodical stress-test yet on a world filled with players, but if it turns out that everyone can handle 5ms (i.e. 200 blocks/second) then the code in this thread allows the bot to send at around that rate. 2000 blocks/s would absolutely cause players to DC.

Ive tested 1000-2000bps on a world with around 5 other players, and I dont think any of them disconnected strangely... Ill look into this further later, but I dont think block placing is a big problem after you have actually connected to the world

Tomahawk wrote:
destroyer123

You're advised not to set it at 1ms resolution and leave it there without utilising it, but there's nothing wrong with using it. Modern CPUs don't run at their maximum frequency unless under full load, so boosting the clock rate still leaves the CPU well within its limits. Doing this is no more harmful than starting up and playing a PC game.

I know its not that bad, but it is still probably better to use another method, Microsoft themselves have also advised against using it when possible, so dont use it if there is another way. (Although what you are using it for isnt terribly bad, I wouldnt suggest it to people who dont know exactly what it does, because they may use it when they really shouldnt e.g. running a bot for multiple hours at a time, with the higher precision left on for long periods of time)
Also, this doesnt do anything special to the CPU (that naturally runs at many millions of cycles per second, even when not under load), this changes windows instead. It turns up the speed at which windows switches / checks threads, and also can prevents the CPU from going into a low power mode when not being used as much.

Offline

#8 2017-03-18 00:10:40

Tomahawk
Forum Mod
From: BiH
Joined: 2015-02-18
Posts: 2,133

Re: (More) Accurate Thread.Sleep

destroyer123 wrote:

I know its not that bad, but it is still probably better to use another method

Suggest another method that will allow blocks to be sent at a regular interval of <15ms with reasonable reliability.

destroyer123 wrote:

Also, this doesnt do anything special to the CPU

My bad. Seems you can google search better than I can.


One bot to rule them all, one bot to find them. One bot to bring them all... and with this cliché blind them.

Offline

#9 2017-03-18 00:26:44, last edited by LukeM (2017-03-18 00:28:54)

LukeM
Dev Team
From: England
Joined: 2016-06-03
Posts: 2,838
Website

Re: (More) Accurate Thread.Sleep

Tomahawk wrote:
destroyer123 wrote:

I know its not that bad, but it is still probably better to use another method

Suggest another method that will allow blocks to be sent at a regular interval of <15ms with reasonable reliability.

You don't really need an accurate way to time anything in EE, you can currently send hundreds of blocks almost instantly, then wait the same time you would have all at once at the end, before placing hundreds of blocks again, as far as I can tell, it makes almost no difference (I will be testing this sort of thing soon and making a topic with all my results in)
This is the way I've been doing it in all of my previous bots, and will probably continue to do it this way after this update

Just a quick example of how to do this fairly simply (there are better ways, but this is a good enough example)

int i = 0;
while(i < blocks to place) {
    if(i % speed == 0) Thread.Sleep(> 25ms);
    con.send(a block);
    i++;
}

Offline

#10 2017-03-18 00:39:58

Tomahawk
Forum Mod
From: BiH
Joined: 2015-02-18
Posts: 2,133

Re: (More) Accurate Thread.Sleep

destroyer123 wrote:

You don't really need an accurate way to time anything in EE, you can currently send hundreds of blocks almost instantly, then wait the same time you would have all at once at the end, before placing hundreds of blocks again, as far as I can tell, it makes almost no difference (I will be testing this sort of thing soon and making a topic with all my results in)

You're really missing the point, which is this: if I want to place a block every 5ms, how do I do it?


One bot to rule them all, one bot to find them. One bot to bring them all... and with this cliché blind them.

Offline

#11 2017-03-18 12:35:27

LukeM
Dev Team
From: England
Joined: 2016-06-03
Posts: 2,838
Website

Re: (More) Accurate Thread.Sleep

Tomahawk wrote:
destroyer123 wrote:

You don't really need an accurate way to time anything in EE, you can currently send hundreds of blocks almost instantly, then wait the same time you would have all at once at the end, before placing hundreds of blocks again, as far as I can tell, it makes almost no difference (I will be testing this sort of thing soon and making a topic with all my results in)

You're really missing the point, which is this: if I want to place a block every 5ms, how do I do it?

I'm asking why you need to place blocks every 5ms? It's basically indistinguishable from placing 5 blocks every 25ms, and the latter doesn't produce any adverse effects on your computer

I'm just saying if you can do it without timeBeginPeriod, then you should

Offline

#12 2017-03-18 16:45:21

Tomahawk
Forum Mod
From: BiH
Joined: 2015-02-18
Posts: 2,133

Re: (More) Accurate Thread.Sleep

destroyer123 wrote:

I'm asking why you need to place blocks every 5ms? It's basically indistinguishable from placing 5 blocks every 25ms, and the latter doesn't produce any adverse effects on your computer

T_T

Let's say you have a BAL that places 5 blocks every time a player hits a coin. You could send those 5 blocks with no delay, and with only a few players there's no problem. But then 10 more players join, and suddenly you can have 50 or 100 blocks being placed with no delay, and people start to DC. I could sleep for 25ms after every 5 blocks were sent, but then players would experience increased lag due to a backlog of messages.

Unless you do something fancy like a block queue and a timer to send off batches of blocks every tick, the only way to ensure safe draw speeds is to have a delay between every block, which is the standard thing to do. This delay can now be much smaller, hence the need for a more accurate delay.

This argument is off-topic. I don't need to rattle off 10 scenarios on the spot in order to justify regulated block sending, and usefulness of this isn't just in block sending.

destroyer123 wrote:

I'm just saying if you can do it without timeBeginPeriod, then you should

You can only judge the safety of this on a case-by-case basis, not in general, because it's harmless (for instance) for sending 50 blocks.

But, if using it at all is evil, I'll ask again: give me another simple way of doing some action every 5ms.


One bot to rule them all, one bot to find them. One bot to bring them all... and with this cliché blind them.

Offline

#13 2017-03-18 17:30:32

LukeM
Dev Team
From: England
Joined: 2016-06-03
Posts: 2,838
Website

Re: (More) Accurate Thread.Sleep

Im going to say now, I cant think of a better way to have a delay of 5ms, but my point is if you are fine with having a 5ms delay after each of 5 blocks, then why is having a 25ms delay after all 5 worse?
Even if all of the blocks were being send in random positions throughout the code, there would be loads of simple ways to have it sleep after every 5 blocks, here is one (its not very neat, but its the simplest I could think of):

(static) short requireSleep = 0;
void Place(params object[] args)
{
    con.Send("b", args);
    if ((requireSleep = (requireSleep + 1) % 5) == 0) Thread.Sleep(25);
}

Offline

#14 2017-03-18 17:48:40

SmittyW
Member
Joined: 2015-03-13
Posts: 2,080

Re: (More) Accurate Thread.Sleep

Go back and read TH's last post. He says pausing after every block is more secure. For instance, multiple events triggering a batch of 5 blocks simultaneously would increase the risk of disconnecting. Also it's easier to adjust the block count and block type with a sleep in between each because you wouldn't have to calculate the delay x blocks. I suppose for testing purposes it doesn't matter if that's what you're picking at.

Offline

#15 2017-03-18 17:49:33

Tomahawk
Forum Mod
From: BiH
Joined: 2015-02-18
Posts: 2,133

Re: (More) Accurate Thread.Sleep

destroyer123 wrote:

my point is if you are fine with having a 5ms delay after each of 5 blocks, then why is having a 25ms delay after all 5 worse?

Tomahawk wrote:

Let's say you have a BAL that places 5 blocks every time a player hits a coin. You could send those 5 blocks with no delay, and with only a few players there's no problem. But then 10 more players join, and suddenly you can have 50 or 100 blocks being placed with no delay, and people start to DC.

...


One bot to rule them all, one bot to find them. One bot to bring them all... and with this cliché blind them.

Offline

#16 2017-03-18 18:06:19

LukeM
Dev Team
From: England
Joined: 2016-06-03
Posts: 2,838
Website

Re: (More) Accurate Thread.Sleep

SmittyW wrote
Tomahawk wrote

Oh oops... I didnt explain why this wouldnt be a problem for what you are explaining

PlayerIO only runs on one thread, this means that one message has to finish before the next starts, so this wouldnt be a problem unless you are creating a new thread to place the blocks, and from this post, it sounds like you are not:

Tomahawk wrote

This means that if you put a Thread.Sleep at the end of a message, it will wait that long until handling another message, so there is no chance of having all 50-100 blocks placed at the same time.

Note: I just tested this with this code, just incase I was wrong:

private static void Con_OnMessage(object sender, Message e)
{
    if (e.Type == "say")
    {
        Console.WriteLine("Message recieved");
        Thread.Sleep(5000);
        Console.WriteLine("Finished sleep");
    }
}

The first Finished sleep was printed before the second Message recieved was,
even though I sent 2 messages about 1-2 seconds apart

Offline

Wooted by:
LukeM1489856779651456

Board footer

Powered by FluxBB

[ Started around 1568776724.7197 - Generated in 0.072 seconds, 10 queries executed - Memory usage: 1.49 MiB (Peak: 1.7 MiB) ]