B4J Question Calculating elapsed milliseconds with DateTime.Now

max123

Well-Known Member
Licensed User
Longtime User
Hi all,

I want to make a simple System Benchmark application, is this the best way to calculate the elapsed time ?
Results on this will continue to change from time to time and seem to be not precise, may I need to use a Timer ?
Using this only the second thread of eight of my CPU is used, how I can calculate using all threads ? I need to use Threading library ?

Many thanks
B4X:
Private Sub Button1_Click
  
    Dim t1,t2 As Long
    t1 = DateTime.Now
    Log("S: " & t1)
  
    Dim Number1 As Double = 3485746742.534568
    Dim Number2 As Double = 46742.844366
  
    Wait For (DivideDouble(Number1, Number2, 1000000)) Complete (rtn As Double)
  
    t2 = DateTime.Now
    Log("E: " & t2)
    t1 = t2 - t1
    Log("TIME: " & t1)
  
    Log("RESULT: " & rtn)
End Sub

Sub DivideDouble (n1 As Double, n2 As Double, Repetitions As Long) As ResumableSub
    Dim n3 As Double
  
    For i = 0 To Repetitions - 1
        n3 = n1 / n2
        Sleep(0)
    Next
  
    Return n3
End Sub
 
Last edited:

kimstudio

Active Member
Licensed User
Longtime User
Don't use timer. I just use DateTime.Now to calc computation time like you.

Why Wait For is used here? maybe tiny but still overhead will be brought in.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Hi @kimstudio , thanks for reply.... I still tested with Timer before you replied me.... Oooooh... and seem more precise , but just a bit, even this will continue to change from time to time.
What I do is to initialize a Timer and a counter in a button press sub, then I reset counter, enable the timer to 1 millisecond and inside a timer tick sub I just increase counter by one. But I always use Wait For and it need sleep(0), yes, so may some overhead.... And how avoid this ?

B4X:
Private Sub Button1_Click
  
    Dim t1,t2 As Long
    t1 = DateTime.Now
    Log("S: " & t1)
  
    Dim Number1 As Double = 3485746742.534568
    Dim Number2 As Double = 46742.844366
  
    Dim const REPETITIONS As Long = 100000
  
    count = 0
    Timer1.Initialize("Timer1", 1)
    Timer1.Enabled = True
  
    Wait For (DivideDouble(Number1, Number2, REPETITIONS)) Complete (rtn As Double)
    Log("TIME: " & count)
  
    Log("RESULT: " & rtn)
End Sub

Sub DivideDouble (n1 As Double, n2 As Double, Repetitions As Long) As ResumableSub
    Dim n3 As Double
  
    For i = 0 To Repetitions - 1
        n3 = n1 / n2
        Sleep(0)
    Next
  
    Return n3
End Sub

Sub Timer1_Tick
    count = count + 1
End Sub
Here some results in the log:
 
Last edited:
Upvote 0

kimstudio

Active Member
Licensed User
Longtime User
I just tried this:

B4X:
Sub Button1_Click
    Dim Number1 As Double = 3485746742.534568
    Dim Number2 As Double = 46742.844366
    Dim Number3 As Double
    Dim t1,t2 As Long
    t1 = DateTime.Now
'    Wait For (DivideDouble(Number1, Number2, 1000000)) Complete (rtn As Double)
    For i = 0 To 1000000 - 1
        Number3 = Number1 / Number2
'        Sleep(0)
    Next
    t2 = DateTime.Now

    Log("S: " & t1)
    Log("E: " & t2)
    t1 = t2 - t1
    Log("TIME: " & t1)
    Log("RESULT: " & Number3)
End Sub

Log: the computation time is stable 0ms...
B4X:
S: 1694512333036
E: 1694512333041
TIME: 5
RESULT: 74572.84189299453
S: 1694512337777
E: 1694512337779
TIME: 2
RESULT: 74572.84189299453
S: 1694512339010
E: 1694512339010
TIME: 0
RESULT: 74572.84189299453
S: 1694512339737
E: 1694512339737
TIME: 0
RESULT: 74572.84189299453
S: 1694512340471
E: 1694512340471
TIME: 0
RESULT: 74572.84189299453

Correct some of my personal points if wrong:
  • Avoid to put log() inbetween calculation
  • The first one or two run is slow always, guess it is related to java VM running mechanism
  • I am not sure the accuracy of java timer, if using Windows API timer the accuracy is very low can reach 10ms+, depends on how it is implemented
  • There is a nanotime lib by @stevel05 I remeber can reach nano precision? should also work on B4J
  • The for loop is doing same thing so for some intelligent compiler it will only loop/calc once, not sure java
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Mmmmmm, I'm not sure from your results, did you tied to use a bigger repetitions number ?
 
Upvote 0

kimstudio

Active Member
Licensed User
Longtime User
I changed the code as below: Loop 1000000000 times and Number3 = Number3 + Number1 / Number2

B4X:
Sub Button1_Click
    Dim Number1 As Double = 3485746742.534568
    Dim Number2 As Double = 46742.844366
    Dim Number3 As Double
    Dim t1,t2 As Long
    t1 = DateTime.Now
'    Wait For (DivideDouble(Number1, Number2, 1000000)) Complete (rtn As Double)
    For i = 0 To 1000000000 - 1
        Number3 = Number3 + Number1 / Number2
'        Sleep(0)
    Next
    t2 = DateTime.Now

    Log("S: " & t1)
    Log("E: " & t2)
    t1 = t2 - t1
    Log("TIME: " & t1)
    Log("RESULT: " & Number3)
End Sub

Now the log is:
B4X:
S: 1694513469797
E: 1694513470743
TIME: 946
RESULT: 7.457284329093866E13
S: 1694513471756
E: 1694513472704
TIME: 948
RESULT: 7.457284329093866E13
S: 1694513473489
E: 1694513474446
TIME: 957
RESULT: 7.457284329093866E13
S: 1694513475246
E: 1694513476173
TIME: 927
RESULT: 7.457284329093866E13
S: 1694513477111
E: 1694513478063
TIME: 952
RESULT: 7.457284329093866E13
S: 1694513478922
E: 1694513479869
TIME: 947
RESULT: 7.457284329093866E13
S: 1694513480898
E: 1694513481832
TIME: 934
RESULT: 7.457284329093866E13
S: 1694513482675
E: 1694513483599
TIME: 924
RESULT: 7.457284329093866E13
S: 1694513484913
E: 1694513485846
TIME: 933
RESULT: 7.457284329093866E13
S: 1694513486552
E: 1694513487488
TIME: 936
RESULT: 7.457284329093866E13
S: 1694513488215
E: 1694513489144
TIME: 929
RESULT: 7.457284329093866E13
 
Last edited:
Upvote 0

kimstudio

Active Member
Licensed User
Longtime User
Changed back to For i = 0 To 1000000 - 1, still with Number3 = Number3 + Number1 / Number2

B4X:
S: 1694513643654
E: 1694513643658
TIME: 4
RESULT: 7.457284189380397E10
S: 1694513644404
E: 1694513644406
TIME: 2
RESULT: 7.457284189380397E10
S: 1694513645035
E: 1694513645039
TIME: 4
RESULT: 7.457284189380397E10
S: 1694513645630
E: 1694513645632
TIME: 2
RESULT: 7.457284189380397E10
S: 1694513646321
E: 1694513646323
TIME: 2
RESULT: 7.457284189380397E10
S: 1694513647012
E: 1694513647014
TIME: 2
RESULT: 7.457284189380397E10
S: 1694513647721
E: 1694513647723
TIME: 2
RESULT: 7.457284189380397E10
S: 1694513648412
E: 1694513648414
TIME: 2
RESULT: 7.457284189380397E10
S: 1694513649016
E: 1694513649018
TIME: 2
RESULT: 7.457284189380397E10
S: 1694513649690
E: 1694513649692
TIME: 2
RESULT: 7.457284189380397E10
S: 1694513650337
E: 1694513650339
TIME: 2
RESULT: 7.457284189380397E10
S: 1694513650985
E: 1694513650987
TIME: 2
RESULT: 7.457284189380397E10
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Thanks... This sound good... I still test it by doing 2 ^ 32 - 1, so 4.294.967.295
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Something very strange to me.... because with this line works returning near 900 milliseconds:
B4X:
Number3 = Number3 + Number1 / Number2
and with this line do not and it just return near 0 milliseconds?
B4X:
Number3 = Number1 / Number2
Same exact code you posted.

Even without use Sleep(0) make my app unresponsive.

And return values that will continue to change:
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
and with this line do not and it just return near 0 milliseconds?
The JVM may realize that the value never changes after the first calculation and then just not run the loop (since the value of the calculation does not change).
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Even without use Sleep(0) make my app unresponsive.
Yes, since the loop takes up all the time on the main thread and there is no time (while processing your loop) for processing the event queue. For process-intensive tasks like this, you will either 1) have to split up the task in such a way as to give the event queue a chance to process (this will slow down the overall processing of your loop and will add code complexity of managing the splitting the task up on your own) or 2) create a thread for such intensive tasks (and then deal with the complexities that you may encounter while working with threads).
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
I ran your code through VisualVM profiler, the figures you get are quite close to what it measures. The only difference being it measures in nanos so you see values like 0.063ms which you would see as 0ms.
 
Upvote 0

kimstudio

Active Member
Licensed User
Longtime User
and with this line do not and it just return near 0 milliseconds?
Could be my last point so I added the n3=n3+
  • The for loop is doing same thing so for some intelligent compiler it will only loop/calc once, not sure java
Even without use Sleep(0) make my app unresponsive.
Could run in another thread but since its purpose is to measures computation time I don't mind unresponsive.

And return values that will continue to change:
I think it is normal to have some fluctuations if the difference is not very absurd, guess we don't know how other processes own CPU and what java VM is doing during calculation...
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Thanks all for help,

I need to know what is a best way to do it, nothing of special, just test some math operations with byte, integer, float and double values with sum, subtraction, division and multiplication, then report in a TextArea the results.

It is not important to get a precise time in nanoseconds, but that results do not continue to change, actually I test Double and Int, sometime Double use more time (like it should be) but sometimes the result is inversed... so no good, Or I need to sample 10 or more values and then get a median point by dividing the total by 10. But not a best way....

I want make this just to compare the CPU speed between two or more computers using java enviroment so in my case to test the math speed B4J apps, even compare these on more Raspberry types, like PI3, PI Zero W, PI4 with PC results.

Can someone help to make this ?

But the problem is that it should use all CPU threads to get resonable results, not only one, so 4, 8, 16, 32 etc depending of used PC.

Many thanks
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
  • There is a nanotime lib by @stevel05 I remeber can reach nano precision? should also work on B4J
@kimstudio I even developed a library (in java) for B4J and B4A, that manage time from nanoseconds to years, but it is for delay.

The library is pretty finished, it even have a DelayNanosecond function (that should have 10 ns to 50 ns precision) but here thee is a small sub calling overhead, and even DelayMilliseconds, DelaySeconds, DelayMinutes, DelayHours, DelayDays, DelayMonths and DelayYears (if I remember) but the problem is that it work on the main thread blocking the GUI so for small delays it is acceptable, if you delay for some years, may the pc will crash or enter sleep mode....
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
So, I repurpose my question...

There are ways to do simple math operations and calculate an elapsed time value that not change from time to time ?

None of proposed advices worked.

It not need to be precise, but at least that not continue to change from time to time.

Thanks
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
least that not continue to change from time to time
That's going to be nearly impossible. If you need such consistency, then you need to run your project on a RTOS (real time operating system) and a language that supports deterministic outcomes. Neither the OS that you are running your project on, nor Java have those qualities.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Thanks for reply @OliverA , I abandon the idea to do it.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Actually, my previous answer may be off mark. For benchmarking, a longer period of benchmarking can smoothen out / average out some of the noise introduced by the underlying OS, or the inefficiencies introduced by the OS can just be a part of the result of the benchmark (and it's up to the user to tweak the OS for optimal benchmark results). The actual issue for you here is that I don't think you can target specific OS cores/threads via Java, so Java may not be suitable for this type of undertaking.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Thanks for clear explanation @OliverA I will start to develop in C++ on desktop devices, I already manage C++ on ESP32 and Arduino IDE (and note it works on top of RTOS), I've some acknowledgment but never used it on desktop side.
 
Last edited:
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…