Calculating a operational rate? E.g. Checking X per second - delphi

I want to be able to calculate the rate at which my software is performing look ups. The software is iterating over a listbox which contains usernames, and then querying my server. I want to calculate how many username look ups I am performing every second?
Would I have to use a timer that executes the calculation every 1000 m/secs? I really have no idea where to start.
I don't have any code to show, just wanted to get some pseudo code.

This might help (I don't really know delphi, so cannot verify syntax, it's only pseudo-code per request):
var
// Set a timer and counter variable
timer : TDateTime;
rate, counter : Integer;
n : Integer; // Iterator
begin
timer := Time;
counter := 0;
for n := 0 to list.items.count - 1 do
begin
// Do the processing here
// add 1 to the counter every time you iterate over a username
counter := counter + 1;
end;
// Divide Time difference by total to get the rate of username lookups per second
// TDateTime is counted in days, convert it to seconds, to get "per sec" rate
rate := counter / ((Time - timer) * 24 * 60 * 60);

If you wanna see aproximate number of lockups your program does per second you might be able to do that with TTimer.
First you need to have soume counter in your loop to count how many items has been processed:
for n := 0 to list.items.count - 1 do
begin
// Do the processing here
// add 1 to the counter every time you iterate over a username
counter := counter + 1;
end;
Then in the OnTimer event of your Timer you check the current counter state and output that to label. And finally you reset your counter to zero:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
//read the coutner value to find out how many items was processed
Label1.Caption := IntToStr(Counter);
//reset timer to zero
Counter := 0;
end;
Now this will give you aproximate results of how many items was processed in the last second. Why only aproximate? TTimer is a windows message based component. What this means is that it doesen't guarantees precision so OnTimer events might not be fired exactly on specified intervals. I have seen deviation even up to half a second. It laregly depends on your main program code and overal system utilization.
NOTE: This approach won't work if you are doing all of this processing in main program thread as such processing could lock up your application till the loop ends. And this means that your application won't process any windows based messages, including the messages that agre created in order to fire the timers OnTimer event.
In such case I recomend next approach. Instead of measuring how many items is processed in one second measure how much time takes to process X amount of items.
You can do this with something like this:
const X := 20; //Constant defining how many items needs to be processed
//before processing time is evaluated
//You will need to find out which number of items is best
//suitable for you on your own by trial and error.
var
//StopWatch is a special record which alows precision timing
sw: TStopWatch;;
//Variable for storing elapsed milliseconds of one measuring cycle
elapsedMilliseconds : cardinal;
//Estimated number of calculations that would have been processed in one
//second
CalculationsPerSecond: Integer;
begin
counter := 0;
//Initialize the stop watch
sw := TStopWatch.Create() ;
//Start stopwatch
sw.Start;
for n := 0 to list.items.count - 1 do
begin
// Do the processing here
// add 1 to the counter every time you iterate over a username
counter := counter + 1;
//Check if the counter has been set to specific number of cycles
//you want to to measure time taken for
if Counter = X then
begin
//Stop the StopWatch
sw.Stop;
//Get how many milliseconds have elapsed since start
elapsedMilliseconds := sw.ElapsedMilliseconds;
//Calculate estimated number of items that would have been processed
//per second
CalculationsPerSecond := Round(1000 * X / elapsedMillisecond);
//Reset counter to zero fopr next cycle
counter := 0;
//Reset stopwatch to zero for next cycle
sw.Reset;
//Start stopwatch agina for next cycle
sw.Start;
end;
//Stop the StopWatch since we no longer need it
sw.Stop;
//Free up the stopwatch record to free up the used memory
sw.Free;
end;

Related

Get idle time of windows and/or application (time since last mouse move or key stroke)

I want to perform background tasks (Updates, Backups, Calculations, ...) at a time when nobody is using my application.
Therefore, I want to determine the time since the last keystroke and/or mouse move in my application. If there is no user activity for more than a specific time, the chance is high not to disturb a user. Multithreading is not an option for me.
I want to avoid touching every single OnMouseDown-/OnKeyPress-Event of every component in my application because this doesn't make any sense.
How can I get
a) The time since last input in Windows
b) The time since last input in my application
This solution works for problem
a) The time since last input in Windows
Every mouse move or keyboard input resets the time to zero.
function GetTimeSinceLastUserInputInWindows(): TTimeSpan;
var
lastInput: TLastInputInfo;
currentTickCount: DWORD;
millisecondsPassed: Double;
begin
lastInput := Default(TLastInputInfo);
lastInput.cbSize := SizeOf(TLastInputInfo);
Win32Check( GetLastInputInfo(lastInput) );
currentTickCount := GetTickCount();
if (lastInput.dwTime > currentTickCount) then begin // lastInput was before 49.7 days but by now, 49.7 days have passed
millisecondsPassed :=
(DWORD.MaxValue - lastInput.dwTime)
+ (currentTickCount * 1.0); // cast to float by multiplying to avoid DWORD overflow
Result := TTimeSpan.FromMilliseconds(millisecondsPassed);
end else begin
Result := TTimeSpan.FromMilliseconds(currentTickCount - lastInput.dwTime );
end;
end;
https://www.delphipraxis.net/1504414-post3.html

Differentiation of a buffer with Delphi

I receive a buffer of data periodically that contains a number of values that are a fixed distance in time apart. I need to differentiate them. It is soo long since I did calculus at school ....
What I have come up with is this:
function DifferentiateBuffer(
ABuffer: TDoubleDynArray; AVPS: integer): TDoubleDynArray;
var
i: integer;
dt, dy: double;
begin
if (AVPS = 0) then exit;
// calc the delta time
dt := 1 / AVPS;
// run through the whole buffer
for i := 0 to high(ABuffer) do begin
if (i = 0) then
if (IsNan(FLastDiffValue) = false) then
dy := ABuffer[0] - FLastDiffValue
else
dy := ABuffer[0]
else
dy := Abuffer[i] - ABuffer[i -1];
result[i] := dy / dt
end;
// remember the last value for next time
FLastDiffValue := ABuffer[high(ABuffer)];
end;
AVPS is values per second. A typical value for this would be between 10 and 100.
The length of the buffers would typically be 500 to 1000 values.
I call the buffer time after time with new data which is continuous with the previous block of data, hence keeping the last value of the block for next time. That last value is set to NAN in a constructor.
Is what I have done correct? ie, will it differentiate the values properly?
I also need to integrate similar data ... what is that likely to look like?
I cannot find any faults in that.
The first value returned, on the first call will be (ABuffer[0] - 0.0) / dt which is based on the assumption that the signal starts with a zero. I presume that is what you intend.
Now, rather than asking the Stack Overflow community to check your code, you can do much better yourself. You should test the code to prove it is accurate. Test it using a unit testing framework, for example DUnitX. Feed the function values for which you can predict the output. For example, feed it values from y = x2, or y = sin(x).
The other great benefit of writing tests is that they can be executed again and again. As you develop your code you run the risk of introducing faults. The code might be correct today, but who knows whether it will still be correct after the modification you make tomorrow. If you have a strong test in place, you can defend against faults introduced during maintenance.
One comment on style is that you should not ever test = false or = true. The if statement operates on boolean expressions and so comparing against a boolean value is always rather pointless. I would write your test like this:
if not IsNan(FLastDiffValue) then
dy := ABuffer[0] - FLastDiffValue
else
dy := ABuffer[0]
or like this:
if IsNan(FLastDiffValue) then
dy := ABuffer[0]
else
dy := ABuffer[0] - FLastDiffValue

Calculating FPS in delphi Firemonkey

I'm using two timers for that
Timer1.Interval = 1;
Timer2.Interval = 1000;
var
FPS: Integer = 0;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Inc(FPS);
end;
procedure TForm1.Timer2Timer(Sender: TObject);
begin
Caption := IntToStr(FPS) + 'FPS';
FPS := 0;
end;
Im getting 65 FPS.
How accurate is that and What is the most right/accurate way to calculate FPS(Frame per second)?
You don't calculate FPS here. This code counts events of 1 ms-period Windows timer per second. Note that 1 millisecond is too short period for Window timer, because typical Windows response time (don't know exact English word for it) is 10-20 milliseconds (65 events =~ 15 ms). So in Windows you can measure time interval with good precision, but it is much harder to guarantee exact time of event triggering.
To calculate FPS, you have to count needed events during exactly measured time (read about QueryPerformanceCounter function etc).

Delphi 'Alarm Clock'-like application

I need to make a simple alarm clock application that, instead of playing a sound, will upload a file to the ftp (got the latter figured out). Timers have proved to be ineffective when it comes to executing a thread.
Here's what I got so far:
var
ttime : tDateTime;
timerstr : string;
timealarm : string;
aThread : TMyThread;
begin
aThread := tMyThread.Create(false);
ttime := Now;
timestr := FormatDateTime('hh:nn:ss', ttime);
timealarm := '09:30:30';
if timestr = timealarm then
aThread.Resume; //The thread will execute once and terminate;
end;
Can you guys think of another way to make that command happen once a day in a more effective way?
Thank you.
Solution found: CRON Scheduler
Thank you LU RD and Runner.
Here's my sample code. It's important to note that the comparison is between TDateTime values instead of strings, the comparison is >= rather than =, I'm careful to exclude the day portion when I don't want it, and I'm keeping track of the last day it ran.
procedure TForm1.Timer1Timer(Sender: TObject);
var
currentTime: TDateTime;
alarmTime: TDateTime;
begin
// Time is a floating point value with everything to the left of the zero
// representing the days, and everything to the right of the decimal
// point representing time of day
// Date() gets just the day portion, and lastDateExecuted is a global TDateTime
// variable where we store the last day the program ran
// We only go further if it didn't execute today
if (Date > lastDateExecuted) then
begin
// Use Time() instead of Now() to get just the time portion and leave the day
// portion at 0
currentTime := Time;
// Covert our alarm string to TDateTime instead of TDateTime to string
alarmTime := EncodeTime(9, 30, 30, 0);
// Is it time to run?
// Greater than or equal comparison makes the application still run in case
// our timer happens to miss the exact millisecond of the target time
if currentTime >= alarmTime then
begin
// Immediately set the last run date to keep the next timer event
// from repeating this
lastDateExecuted := Date;
// Do your work here
DoMyThing;
end;
end;
end;
Be sure to initialize the lastDateExecuted value to something like 0.
Use the timer interval for your granularity. If you want it to run within a minute of the target time, set the Interval to a minute. If you want it to try to run within a second, set the timer interval to a second.
If I understand you right, all you need to know is how to recognize when a particular time has been reached in order to execute this thread. Indeed, a timer isn't necessarily an ideal tool to use for this, as timers don't actually trigger in real-time (you can have the interval on 500 msec, but over after 1 minute, or 60,000 msec, it will not be perfectly lined up to an exact 120 executions, as you would wish). However, that doesn't mean we can't use timers.
Inside the timer (or you can make another repeating thread for this too), you simply get the current date/time. IMPORTANT: Make sure the interval of this timer or thread is less than half a second - this will ensure that your time won't be missed. So you would read it like this...
uses
DateUtils;
.....
var
HasExecuted: Bool;
.....
constructor TForm1.Create(Sender: TObject);
begin
HasExecuted:= False;
end;
procedure TimerOnTimer(Sender: TObject);
var
N, A: TDateTime;
Thread: TMyThread;
begin
N := Now;
A := StrToDateTime('11/20/2011 15:30:30'); //24 hour time
//If now is within 1 second over/under alarm time...
if (N >= IncSecond(A, -1)) and (N <= IncSecond(A, 1)) then
begin
if not HasExecuted then begin
HasExecuted:= True;
aThread := tMyThread.Create(true);
aThread.Resume; //The thread will execute once and terminate;
end;
end;
end;
It probably doesn't work right for you because you are using a = operator. What if this timer skips that 1 second? One execution could be the second before, and the next execution could be the second answer, in which case it won't evaluate this expression to equal true.
On another note, your TMyThread constructor - are you overriding this? If so, is the False still the original CreateSuspended parameter? If so, then you are telling this thread to execute immediately upon creation. Pass True in this parameter to make it suspended upon creation, because I see you are also calling Thread.Resume below that (which if the parameter remains false, it's already resumed). On the other hand, you also do not need to create that thread (at least I'm assuming) unless the time has been reached. Why are you creating it before you even check? It's creating one of these for each and every time this timer is executed (I'm presuming this is the thread that will take care of the uploading, as needed). Also, make sure that the thread is properly free'ing its self when it's done, and doesn't just get stuck...
constructor TMyThread.Create(CreateSuspended: Bool);
begin
inherited Create(CreateSuspended);
FreeOnTerminate:= True; //Make sure it free's its self when it's terminated
end;
EDIT:
I missed something - if, let's say, the interval of this timer was 1 (it should be more like 200-400), then it could very well execute many times in a row, during this time period. I modified the code above to also make sure it's only executed once. NOTE: This code was typed by memory, not in a delphi environment.

Delphi(2006) Loop Help

So What I'm essentially trying to do is have something happen 70% of the time, another few things happen 10% of the time each if that makes sense but my app doesn't seem to do any of the actions I'm guessing I'm misunderstanding the loop syntax or something, anyway if anyone could take a look and maybe give me some advice
per1 := 70;
per2 := 77;
per3 := 84;
per4 := 91;
per5 := 100;
per6 := Random(2) + 1;
randomize;
RandPer:= Random(100);
randomize;
RandPer2 := Random(100);
if RandPer2 <= 70 then begin
If RandPer <= per1 then begin
Functiontest(1);
end Else If RandPer <= per2 then begin
Functiontest(3);
end Else begin If RandPer <= per3 then begin
Functiontest(5);
end Else begin If RandPer <= per4 then begin
Functiontest(6);
end Else begin If RandPer <= per5 then begin
Functiontest(9);
end;
end;
end;
end;
You don't have any loop syntax, so that's certainly a possible source of your confusion.
Do not call Randomize multiple times. It reinitializes the random seed each time you do, and that's based on the system clock. If your code runs faster than the clock advances, then your several calls to Randomize will actually reset the random seed to the same value it had before, resulting in repeated Random calls returning the same value.
The help advises you to call Randomize just once at the start of your program. If you are writing a unit or component and you are not in charge of the whole program, then do not call Randomize at all. Instead, document that consumers of your code should call it themselves.
If you are writing a DLL and not using run-time packages, then call Randomize in an initialization function that your DLL exports; consumers of your DLL won't have access to your DLL's copy of the Delphi run-time library.
Also, if you want something to happen 70 percent of the time, then you should check whether your value is strictly less than 70. The possible return values of Random include zero; 70 percent of the results will be between 0 and 69 inclusive. Allowing 70 will actually make the event happen 71 percent of the time.
Finally, your calculations of 10 percent of the time don't make sense to me. You have three events that will happen 7 percent of the time, and one that will happen 9 percent of the time. You can't have four events that each happen 10 percent of the time when you only have 30 percent remaining. Do you mean for each event's frequency to be measured independently of the others? If so, then do not link all your conditional tests together with else; Use completely a separate if statement for each one.
I just modified CharlesF code to do what you need.
Hope CharlesF won't mind.
begin
randomize;
for i := 0 to NumberOfTimesNeed do
begin
R := Random(100);
case R of
0..69 : Functiontest(1); // this will fire 70% of NumberofTimes
70..79 : Funciotntest(2); // 10 percent
80..89 : Funciotntest(3); // 10 percent
90..94 : Funciotntest(4); // 5 percent
// and so on ...
end;
end;

Resources