Java Gradually Decrease Number Until Target Reached Over Time - java

I am struggling a bit with a concept on how to implement some timings.
Basically, I need to write some code that will effectively perform a ramp-up to fire requests to a server.
To explain further, I need to fire requests to a server over the course of a 15 minute ramp-up period. After 15 minutes, a rate of 3 requests per second should be made. At the beginning of the ramp up period, we can start with (say) 1 request every 3 seconds. How it reaches the 3 request per second rate doesn't matter, but it should not reach this rate until 15 minutes.
What I need help with is implementing this as a timer. I need a function that will return the amount of time to wait before sending the next request.
So I have a loop like so:
Send request
Wait x amount of time (where x is returned by a function)
This happens until 15 minutes is reached, whereby the function always returns a value of 0.3 seconds (to achieve 3 requests per second - assumption is that requests take 0 seconds to send, but that's ok...)
The values provided are:
- Total ramp up time.
- Requests per second at the end of the ramp up time.
- Requests per second at the start of the ramp up time.
Any help would be appreciated.

Since you are not too concerned about the exact way the rate speeds up, you could choose the following assumptions:
Rate will increase linearly with time
Some approximations and rounding of the rate is fine, as long as we don't slow down
You are starting at time=0, and going to time=15
At time=0, your rate is (say) 1 every 3 seconds. At time=15, your rate is 1 every 0.3333 seconds
The total change from 0 to 15 is (3 - 0.3333=) 2.77777
Divide this by 15, you get 0.1777777. What this means is: if your rate fell by 0.177777 every second, you could start at 3 and end up at 0.3333
This is shown on a linear graph like this:
So, if you have a method that know how long (in seconds) since the start (x), you can compute what your current rate should be.
double computeRate(double secondsSinceStart)
{
return 3 * (-0.177777 * Math.floor(secondsSinceStart));
}
That computation is the number of seconds you have to wait.
Using a similar principle, you can assume a non-linear curve, or tweak it in other ways.

/**
* start is the moment the first request is sent (in ms)
* end is the moment, in which the targetDelta should be reached (in ms)
* targetDelta is the targeted period between two requests (0.3)
* initDelta is the initial delta (1.0)
*/
private int getWaitingPeriod(long start, long end, double targetDelta, double initDelta) {
double timePassed = (double) (System.currentTimeMillis() - start);
double progress = timePassed / (double) (end - start);
if(progress >= 1) return (int) (targetDelta * 1000);
return (int) ((targetDelta - (targetDelta - initDelta) * progress) * 1000);
}
Not tested, but is this what you are searching for?
edit: whoops, forgot converting seconds to ms.. Now tested, example:
long start = System.currentTimeMillis();
while(System.currentTimeMillis() < start + 10000) { //testing with 10 seconds
int wait = getWaitingPeriod(start, start + 10000, 1, 0.3);
System.out.println("waiting " + wait + "ms");
try {
Thread.sleep(wait);
} catch(InterruptedException ex) {}
}

You can start by creating a class that handles sending the requests if that's not already the case. Something like (this is more Object Oriented) :
public class RequestSender {
double startTime;
// ramp up time is in minutes
double rampUpTime;
boolean firstRequest;
int requestPerSecBeforeTime;
int requestPerSecAfterTime;
RequestSender(double rampUpTime, int requestPerSecBeforeTime, int requestPerSecAfterTime){
this.rampUpTime = rampUpTime;
this.requestPerSecAfterTime = requestPerSecAfterTime;
this.requestPerSecBeforeTime = requestPerSecAfterTime;
firstRequest=true;
}
public void sendRequest(){
if (firstRequest){
startTime = System.currentTimeMillis();
firstRequest = false;
}
// do stuff to send requests
}
public double getWaitTime(){
if ((System.currentTimeMillis() - startTime)/60000 > rampUpTime){
return 1/requestPerSecAfterTime;
}
else {
return 1/requestPerSecBeforeTime;
}
}
}
Then you can use this object in your code :
RequestSender rs = new RequestSender(15, 1, 3);
rs.sendRequest();
Thread.wait(rs.getWaitTime());

Related

Java - Trying to make a timer

I'm trying to make a timer that goes from 15 minutes to 0 but my code doesn't work. Sorry if this is easy, I recently started learning.
package timer;
import java.util.Timer;
import java.util.TimerTask;
public class Timer {
int secondsLeft = 900;
int minutesLeft = secondsLeft/60;
int seconds2 = secondsLeft - minutesLeft * 60;
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
secondsLeft--;
System.out.println("Time left : " + minutesLeft + ":" + seconds2 );
}
};
public void start() {
timer.scheduleAtFixedRate(task, 1000, 1000);
}
public static void main(String[] args) {
Timer timer = new Timer();
timer.start();
}
}
Your program is mostly written correctly, but you are not printing any changes. When the seconds count down, you need to convert existing total seconds to minutes and seconds.
You can do it several ways.
Method 1: Like you are doing it now, by
maintaining a total number of seconds. It requires two operators.
The division operator /
The remainder operator %
To get the minutes remaining, simply divide total seconds by 60. (totalSeconds / 60)
To get the seconds remaining in the current minute take the remainder (totalSeconds % 60)
Method 2: By maintaining separate values for minutes and seconds, where seconds is the number of seconds within the current minute.
define a int minutes field initialized to 15
define a int seconds field initialized to 0
When the timer task runs, you need to update those fields correctly. When the seconds reach 0
decrement the minutes and set the seconds to 59. Otherwise, just decrement the seconds.
When they both reach 0, you're done. So this requires some if clauses on your part.
Additional Recommendations
To retain the leading zeroes of minutes and seconds, you can use the following formatted print statement.
System.out.printf("Time left : %02d:%02d%n",minutesLeft, secondsLeft);
The %02d is the field width and the 0 means keep leading zeroes to fill out that field. To learn more about formatted printing, check out the Formatter class in the Java API.
And finally, please call you class something other than Timer. You are using a Timer class by that name already and even though it is in the same package it can be confusing.

How to generate more than 1000 events / second in java using sleep time

I have a generator which generates events for Flink CEP, code for which is given below. Basically, I am using Thread.sleep() and I have read somewhere that java can't sleep less than 1 millisecond even we use System.nanoTime(). Code for the generator is
public class RR_interval_Gen extends RichParallelSourceFunction<RRIntervalStreamEvent> {
Integer InputRate ; // events/second
Integer Sleeptime ;
Integer NumberOfEvents;
public RR_interval_Gen(Integer inputRate, Integer numberOfEvents ) {
this.InputRate = inputRate;
Sleeptime = 1000 / InputRate;
NumberOfEvents = numberOfEvents;
}
#Override
public void run(SourceContext<RRIntervalStreamEvent> sourceContext) throws Exception {
long currentTime;
Random random = new Random();
int RRInterval;
int Sensor_id;
for(int i = 1 ; i <= NumberOfEvents ; i++) {
Sensor_id = 2;
currentTime = System.currentTimeMillis();
// int randomNum = rand.nextInt((max - min) + 1) + min;
RRInterval = 10 + random.nextInt((20-10)+ 1);
RRIntervalStreamEvent stream = new RRIntervalStreamEvent(Sensor_id,currentTime,RRInterval);
synchronized (sourceContext.getCheckpointLock())
{
sourceContext.collect(stream);
}
Thread.sleep(Sleeptime);
}
}
#Override
public void cancel() {
}
}
I will specify my requirement here in simple words.
I want generator class to generate events, let's say an ECG stream at 1200 Hz. This generator will accept parameters like input rate and total time for which we have to generate the stream.
So far so good, the issue is that I need to send more than 1000 events / second. How can I do this by using generator function which is generating values U[10,20]?
Also please let me know if I am using wrong way to generate x number of events / second in the above below.
Sleeptime = 1000 / InputRate;
Thanks in advance
The least sleep time in Windows systems is ~ 10 ms and in Linux and Macintosh is 1 millisecond as mentioned here.
The granularity of sleep is generally bound by the thread scheduler's
interrupt period. In Linux, this interrupt period is generally 1ms in
recent kernels. In Windows, the scheduler's interrupt period is
normally around 10 or 15 milliseconds
Through my research, I learned that using the nano time sleep in java will not help as the issue in at OS level. If you want to send data at arrival rate > 1000 in a controlled way, then it can be done using Real-Time Operating Systems (RTOS), as they can sleep for less then a millisecond. Now, I have come up with another way of doing it, but in this solution, the interarrival times will not be constantly distributed.
Let's say you want arrival rate of 3000 events/ second, then you can create a for loop which iterates 3 times to send data in each iteration and then sleep for 1ms. So for the 3 tuples, the interarrival time will be close to one another, but the issue will be solved. This may be a stupid solution but it works.
Please let me know if there is some better solution to this.

Java calculations that takes X amount of time

This is just a hypothetical question, but could be a way to get around an issue I have been having.
Imagine you want to be able to time a calculation function based not on the answer, but on the time it takes to calculating. So instead of finding out what a + b is, you wish to continue perform some calculation while time < x seconds.
Look at this pseudo code:
public static void performCalculationsForTime(int seconds)
{
// Get start time
int millisStart = System.currentTimeMillis();
// Perform calculation to find the 1000th digit of PI
// Check if the given amount of seconds have passed since millisStart
// If number of seconds have not passed, redo the 1000th PI digit calculation
// At this point the time has passed, return the function.
}
Now I know that I am horrible, despicable person for using precious CPU cycles to simple get time to pass, but what I am wondering is:
A) Is this possible and would JVM start complaining about non-responsiveness?
B) If it is possible, what calculations would be best to try to perform?
Update - Answer:
Based on the answers and comments, the answer seems to be that "Yes, this is possible. But only if it is not done in Android main UI thread, because the user's GUI will be become unresponsive and will throw an ANR after 5 seconds."
A) Is this possible and would JVM start complaining about non-responsiveness?
It is possible, and if you run it in the background, neither JVM nor Dalvik will complain.
B) If it is possible, what calculations would be best to try to perform?
If the objective is to just run any calculation for x seconds, just keep adding 1 to a sum until the required time has reached. Off the top of my head, something like:
public static void performCalculationsForTime(int seconds)
{
// Get start time
int secondsStart = System.currentTimeMillis()/1000;
int requiredEndTime = millisStart + seconds;
float sum = 0;
while(secondsStart != requiredEndTime) {
sum = sum + 0.1;
secondsStart = System.currentTimeMillis()/1000;
}
}
You can and JVM won't complain if your code is not part of some complex system that actually tracks thread execution time.
long startTime = System.currentTimeMillis();
while(System.currentTimeMillis() - startTime < 100000) {
// do something
}
Or even a for loop that checks time only every 1000 cycles.
for (int i = 0; ;i++) {
if (i % 1000 == 0 && System.currentTimeMillis() - startTime < 100000)
break;
// do something
}
As for your second question, the answer is probably calculating some value that can always be improved upon, like your PI digits example.

Attempting to create a stable game engine loop

I'm writing a fairly simple 2D multiplayer-over-network game. Right now, I find it nearly impossible for myself to create a stable loop. By stable I mean such kind of loop inside which certain calculations are done and which is repeated over strict periods of time (let's say, every 25 ms, that's what I'm fighting for right now). I haven't faced many severe hindrances this far except for this one.
In this game, several threads are running, both in server and client applications, assigned to various tasks. Let's take for example engine thread in my server application. In this thread, I try to create game loop using Thread.sleep, trying to take in account time taken by game calculations. Here's my loop, placed within run() method. Tick() function is payload of the loop. It simply contains ordered calls to other methods doing constant game updating.
long engFPS = 40;
long frameDur = 1000 / engFPS;
long lastFrameTime;
long nextFrame;
<...>
while(true)
{
lastFrameTime = System.currentTimeMillis();
nextFrame = lastFrameTime + frameDur;
Tick();
if(nextFrame - System.currentTimeMillis() > 0)
{
try
{
Thread.sleep(nextFrame - System.currentTimeMillis());
}
catch(Exception e)
{
System.err.println("TSEngine :: run :: " + e);
}
}
}
The major problem is that Thread.sleep just loves to betray your expectations about how much it will sleep. It can easily put thread to rest for much longer or much shorter time, especially on some machines with Windows XP (I've tested it myself, WinXP gives really nasty results compared to Win7 and other OS). I've poked around internets quite a lot, and result was disappointing. It seems to be fault of the thread scheduler of the OS we're running on, and its so-called granularity. As far as I understood, this scheduler constantly, over certain amount of time, checks demands of every thread in system, in particular, puts/awakes them from sleep. When re-checking time is low, like 1ms, things may seem smooth. Although, it is said that WinXP has granularity as high as 10 or 15 ms. I've also read that not only Java programmers, but those using other languages face this problem as well.
Knowing this, it seems almost impossible to make a stable, sturdy, reliable game engine. Nevertheless, they're everywhere.
I'm highly wondering by which means this problem can be fought or circumvented. Could someone more experienced give me a hint on this?
Don't rely on the OS or any timer mechanism to wake your thread or invoke some callback at a precise point in time or after a precise delay. It's just not going to happen.
The way to deal with this is instead of setting a sleep/callback/poll interval and then assuming that the interval is kept with a high degree of precision, keep track of the amount of time that has elapsed since the previous iteration and use that to determine what the current state should be. Pass this amount through to anything that updates state based upon the current "frame" (really you should design your engine in a way that the internal components don't know or care about anything as concrete as a frame; so that instead there is just state that moves fluidly through time, and when a new frame needs to be sent for rendering a snapshot of this state is used).
So for example, you might do:
long maxWorkingTimePerFrame = 1000 / FRAMES_PER_SECOND; //this is optional
lastStartTime = System.currentTimeMillis();
while(true)
{
long elapsedTime = System.currentTimeMillis() - lastStartTime;
lastStartTime = System.currentTimeMillis();
Tick(elapsedTime);
//enforcing a maximum framerate here is optional...you don't need to sleep the thread
long processingTimeForCurrentFrame = System.currentTimeMillis() - lastStartTime;
if(processingTimeForCurrentFrame < maxWorkingTimePerFrame)
{
try
{
Thread.sleep(maxWorkingTimePerFrame - processingTimeForCurrentFrame);
}
catch(Exception e)
{
System.err.println("TSEngine :: run :: " + e);
}
}
}
Also note that you can get greater timer granularity by using System.nanoTime() in place of System.currentTimeMillis().
You may getter better results with
LockSupport.parkNanos(long nanos)
altho it complicates the code a bit compared to sleep()
maybe this helps you.
its from david brackeen's bock developing games in java
and calculates average granularity to fake a more fluent framerate:
link
public class TimeSmoothie {
/**
How often to recalc the frame rate
*/
protected static final long FRAME_RATE_RECALC_PERIOD = 500;
/**
Don't allow the elapsed time between frames to be more than 100 ms
*/
protected static final long MAX_ELAPSED_TIME = 100;
/**
Take the average of the last few samples during the last 100ms
*/
protected static final long AVERAGE_PERIOD = 100;
protected static final int NUM_SAMPLES_BITS = 6; // 64 samples
protected static final int NUM_SAMPLES = 1 << NUM_SAMPLES_BITS;
protected static final int NUM_SAMPLES_MASK = NUM_SAMPLES - 1;
protected long[] samples;
protected int numSamples = 0;
protected int firstIndex = 0;
// for calculating frame rate
protected int numFrames = 0;
protected long startTime;
protected float frameRate;
public TimeSmoothie() {
samples = new long[NUM_SAMPLES];
}
/**
Adds the specified time sample and returns the average
of all the recorded time samples.
*/
public long getTime(long elapsedTime) {
addSample(elapsedTime);
return getAverage();
}
/**
Adds a time sample.
*/
public void addSample(long elapsedTime) {
numFrames++;
// cap the time
elapsedTime = Math.min(elapsedTime, MAX_ELAPSED_TIME);
// add the sample to the list
samples[(firstIndex + numSamples) & NUM_SAMPLES_MASK] =
elapsedTime;
if (numSamples == samples.length) {
firstIndex = (firstIndex + 1) & NUM_SAMPLES_MASK;
}
else {
numSamples++;
}
}
/**
Gets the average of the recorded time samples.
*/
public long getAverage() {
long sum = 0;
for (int i=numSamples-1; i>=0; i--) {
sum+=samples[(firstIndex + i) & NUM_SAMPLES_MASK];
// if the average period is already reached, go ahead and return
// the average.
if (sum >= AVERAGE_PERIOD) {
Math.round((double)sum / (numSamples-i));
}
}
return Math.round((double)sum / numSamples);
}
/**
Gets the frame rate (number of calls to getTime() or
addSample() in real time). The frame rate is recalculated
every 500ms.
*/
public float getFrameRate() {
long currTime = System.currentTimeMillis();
// calculate the frame rate every 500 milliseconds
if (currTime > startTime + FRAME_RATE_RECALC_PERIOD) {
frameRate = (float)numFrames * 1000 /
(currTime - startTime);
startTime = currTime;
numFrames = 0;
}
return frameRate;
}
}

Java Thread.sleep Exception

I've made a class that controls the speed at which my program runs, kind of like a vertical sync, and it passes some necessary information to the program at each frame. I have the entire thing working, but I've tried using the more accurate Thread.sleep(long millis, int nanos), something I'm fairly inexperienced using. Based upon the descriptions I've seen, it simply adds the milliseconds provided to the nanoseconds, then pauses the thread. But, about 90% of the frames throw an odd exception, which I really cannot decipher.
java.lang.IllegalArgumentException: nanosecond timeout value out of range
The following is most of the code I used, that interacts in any way with the variable I use to delay the thread.
long startTime = System.nanoTime();
while (! this.stop)
{
try
{
// Run Frame
long endTime, deltaTime, deltaRemainder;
endTime = System.nanoTime();
deltaTime = endTime - startTime;
deltaRemainder = this.rate - (deltaTime % this.rate);
System.out.println("Frame Completed with "
+ (double)(deltaRemainder * .000000001) + " seconds left!");
if (deltaRemainder > 0)
Thread.sleep(0, (int)(deltaRemainder));
startTime = System.nanoTime();
}
catch (Exception e)
{
e.printStackTrace();
}
}
rate is the variable which is equal to the length of a frame in nanoseconds, stop is really unimportant, and apparent. start/endTime are the times at the start and end of a frame. deltaTime is the length of time the frame took to finish. And finally, deltaRemainder is the amount of extra time the frame should have taken to finish(if it takes longer than it should, it jumps up to end at the next possible frame).
Could anyone explain why this exception is thrown? I would really prefer to use the accuracy this function provides.
It seems that your deltaRemainder is outside of the allowed ranged between 0 and 999999.
From Thread.sleep documentation:
millis - the length of time to sleep in milliseconds.
nanos - 0-999999 additional nanoseconds to sleep.
So you should check if it is greater than 999999 and if so, put the value that is above 999999 into milliseconds, e.g.
int milliseconds = 0;
if ( deltaRemainder > 999999 ) {
milliseconds = deltaRemainder / 1000000;
deltaRemainder = deltaRemainder % 1000000;
}
if ( milliseocnds > 0 || deltaRemainder > 0) {
Thread.sleep(milliseconds, deltaRemainder);
}
Edit: My sample code is to be treated as "late night code", there are bugs in it ;).
Only a guess:
ints have 32bits so ints go from -2^31 to 2^31-1
If the deltaRemainder is too big it can overflow and the resulting int will be negative.
Can your deltaRemainder go over 2^31? (2GB which is aprox 2.000.000.000, it is: 2 secs?)
Other guess is:
deltaRemainder is > 0 but < 1. So the int'ed value is 0.

Categories