I'm relatively new to coding, and wondering if there's a conventional way to have some code execute on every nth iteration of a loop (in this case, an NSTimer ticking).
I'm using a CADisplayLink and it updates however many times per second, 40, 50, whatever. If I want to execute some code on every, say, 500 of those loops, is there a standard way to do so? I assume I could put something together with the modulo operator and an integer, but is there a better / more normalized way that a new coder should know?
Extra clarity (though I'm sure this is a fairly common thing to do..): I have a timer that ticks 60 times per second, but I only want to do something with every 10th iteration. I already know that I can use a modulo and an integer to do this, but I want to know if there's any other convention for handling a situation like this.
Thanks in advance!
Establish a dedicated timer for the right interval.
Regardless of whether you're using NSTimer or CADisplayLink, timer calls can be coalesced and offset if they take too long. If you have a display link that takes 20 frames to run, it only gets called thrice every second (given the refresh interval is 60 frames per second). And if you have a timer set to run every second that at one instance takes a bit more than two and a half seconds to run, it will have "ate" its next iteration and will run the next iteration half a second too late.
Because of this, your timer can get out of sync if you only count timer calls. To do something repeatedly on an interval, having a timer set to that interval is the absolute best approximation.
Having a second timer like this is not a performance problem unless you do very many timers, in which case you should standardize on one tick timer and have events scheduled for specific points in time (which still isn't the same as counting previous iterations).
Related
I am new using kotlin and I am wondering if I can do the following...
I wanna call a method on the first of each month, I found this and saw a couple of examples like this:
timer.schedule(1000) {
println("hello world!")
}
I am wondering if is possible to use (instead of a fixed time) a calendar day? like first of the month?
There's no built-in way to do this.
If the exact time of day doesn't matter*, then one approach is to schedule a task to fire every 24 hours, and have it check whether the current time is the first day of the month, and if so, perform the task.
(* It will drift slightly when summer time starts or ends, or leap-seconds get added, but that may not be significant.)
A more powerful (but more complex approach) is to set the timer to go off once, at the appropriate time on the 1st of next month. Then, after performing the task, it could re-schedule itself for the 1st of the following month. (You'd need to take care that it always did so, even if the task threw an exception.)
You could put all this into a timer class of your own, to separate it from the business logic you want to run.
For examples in Java (which will translate directly to Kotlin/JVM), see the answers to these questions.
I want to collect statistics on traffic every 10 seconds and the only tool that I found is connection_state_remove event,
event connection_state_remove(c: connection)
{
SumStats::observe( "traffic", [$str="all"] [$num=c$orig$num_bytes_ip] );
}
how to deal with those connections that did not removed by the end of this period. How to get statistics from them?
The events you're processing are independent of the time interval at which the SumStats framework reports statistics. First, you need to define what exactly are the statistics you care about — for example, you may want to count the number of connections for which Bro completes processing in a given time interval. Second, you need to define the time interval (in your case, 10 seconds) and how to process the statistical observations in the SumStats framework. This latter part is missing in your snippet: you're only making an observation but not telling the framework what to do with it.
The examples in the SumStats documentation are very close to what you're looking for.
In the elm-guide there is a section in Effects/Time which gives an example to return a subscription Time.every second.
In the documentation there seems to be only the granularity units millisecond, second, minute, etc...
Is there a way to get a subscription like 20 per second or another subgranularity?
What is the best way to achieve something like that.
Time is just an alias for Float, so you can do numeric operations on it. If you want a subscription to fire 20 times a second, just make sure it fires every 1/20 of a second.
In other words: Time.every (second / 20.0)
I'm reading the source code of redis 3.2. To expire keys actively, redis server calls activeExpireCycle function in the event loop.
This function has a parameter type to specify the time limit. The type can be ACTIVE_EXPIRE_CYCLE_FAST (fast cycle) or ACTIVE_EXPIRE_CYCLE_SLOW (slow cycle). The time limit of fast cycle is hard coded to 1 millisecond (ACTIVE_EXPIRE_CYCLE_FAST_DURATION). The time limit of slow cycle takes 25% of serverCron period, which is 25 milliseconds by default. So first cycle takes much shorter time than slow cycle.
What's more, the fast cycle is called in beforSleep function, and the slow cycle is called in serverCron function. I drew a diagram about these two calls in event loop.
I can't figure out the purpose of fast cycle. Why doesn't redis leave all the active expiring work to slow cycle?
UPDATE: I changed the upper diagram. Function serverCron doesn't be called in every loop. Redis executes serverCron() per 100 milliseconds by default.
I found the comment in redis source code. Hope It's helpful for you(it will get more aggressive to avoid that too much memory is used by keys that can be removed from the keyspace):
// in https://github.com/redis/redis/blob/6.0/src/expire.c#L76
/* Try to expire a few timed out keys. The algorithm used is adaptive and
* will use few CPU cycles if there are few expiring keys, otherwise
* it will get more aggressive to avoid that too much memory is used by
* keys that can be removed from the keyspace.
*
* The function can perform more or less work, depending on the "type"
* argument. It can execute a "fast cycle" or a "slow cycle". The slow
* cycle is the main way we collect expired cycles: this happens with
* the "server.hz" frequency (usually 10 hertz).
*
* However the slow cycle can exit for timeout, since it used too much time.
* For this reason the function is also invoked to perform a fast cycle
* at every event loop cycle, in the beforeSleep() function. The fast cycle
* will try to perform less work, but will do it much more often.
*/
Inside my scene, I have overridden the default -(void) update: (CFTimeInterval) currentTime function. It is worth noting that the currentTime variable is actually the elapsed time since the beginning of a presumably arbitrary system time, as opposed to the elapsed time since last frame. This update function runs through all of my characters and applies their movement based on velocity per second and elapsed time since last update in seconds. The usual way to get the elapsed time since last update in seconds is to have an NSTimeInterval in your class that stores the last update, and subtract the last update time from the current update time, getting elapsed seconds. However, the initial elapsed time is NOT zero. As such, subtracting zero from a very large number produces a perceived elapsed time of many tens of thousands of seconds. As such, any characters already in motion on the very first frame will have moved very far away.
The obvious solution to this would be to initially set the last update time to the initial time elapsed. However, I do not see any method to access this within SKScene, or more specifically within -(void) didMoveToView: (SKView *) view.
Another solution would be to set the initial CFTimeInterval to a negative number, such as -1. Then, one would check each update function whether the time is -1. If so, one would set the elapsed time since last update to 0, otherwise one would do the ordinary elapsedTime = currentTime - lastUpdate. However, doing this if statement every single update function seems messy and unneeded.
Are there any other ways of finding this elapsed time since last update accurately?
You're right that checking for a flag every iteration is wasteful, so it's a question of what's the most efficient solution.
I would think the best (read: most efficient) solution would be to not apply any changes in the first update besides simply saving the currentTime variable. This shouldn't affect your gameplay at all; nobody will notice the frame has been dropped. You could do it by saving a pointer to a function, calling that function in the first iteration of update which will also change the pointer to another function, and then update will call the second function from that point onward.
The method I think you're looking for is CFAbsoluteTimeGetCurrent, but SK's update method tends to hand back a different, earlier time, likely due to the amount of time taken to pass the time into update versus just using CFAbsoluteTimeGetCurrent. If you're OK with a little extra overhead without using an if, disregard currentTime and always use CFAbsoluteTimeGetCurrent in your update method.
Then again, if you're worried about the overhead of a single if statement in each frame, you wouldn't be using a framework. 60 ifs per second is trivial work for even the slowest mobile processor anyway.
I think I understand.. but I may not. So correct me if I'm wrong. But your problem is that your initial delta time is very large, and so using that value to move characters results in them jumping immediately on the first frame of your game. If thats the case, then youre missing a crucial piece of the code in update.
if self.last_update_time == 0.0 { // this is the important part
self.delta = 0
} else {
self.delta = currentTime - self.last_update_time
}
self.last_update_time = currentTime
last_update_time time will always be 0 when your game starts, and delta will always be 0 too. After that point, your delta value will be very small numbers which you can use to progressively move your sprites.
hopefully this was helpful