The answer to this question states that we can make a reliable and precise metronome on Android using AudioTrack. We can use MediaPlayer, SoundPool, Thread and Timer as well, but they are always causing a delay. Instead of generating a synthesized sound using AudioTrack, how can we achieve the same effect using custom audio files?
You can try to create your own time counter using System.nanoTime(), when you need precision, you always can use this.
public static long nanoTime()
Returns the current value of the most
precise available system timer, in nanoseconds. This method can only
be used to measure elapsed time and is not related to any other notion
of system or wall-clock time. The value returned represents
nanoseconds since some fixed but arbitrary time (perhaps in the
future, so values may be negative). This method provides nanosecond
precision, but not necessarily nanosecond accuracy. No guarantees are
made about how frequently values change. Differences in successive
calls that span greater than approximately 292 years (263 nanoseconds)
will not accurately compute elapsed time due to numerical overflow.
For example, to measure how long some code takes to execute:
long startTime = System.nanoTime(); // ... the code being
measured ... long estimatedTime = System.nanoTime() - startTime;
Returns: The current value of the system timer, in nanoseconds. Since:
1.5
Source:
Oracle Documentation https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#nanoTime()
Related
I currently do this to successfully get the current epoch time in nanos:
Instant inst = Instant.now();
long time = inst.getEpochSecond();
time *= 1000000000l;
time += inst.getNano();
However, it's a bit too slow for my use case, taking around 1us each call after the JVM has warmed up.
Is there a faster way to do it?
I'm happy with a solution that gives me the microseconds since epoch, as long as it's faster than the above.
What may work is to run:
long n1 = System.nanoTime();
long m = System.currentTimeMillis();
long n2 = System.nanoTime();
a number of times until the difference between n1 and n2 is less than the resolution you want (it's about 400 ns on my PC after a couple of iterations).
You can then use the difference between n1 (or n2 or an average of the 2...) and m * 1e6 as an offset that you need to add to System.nanoTime() to get the current epoch nanos.
Disclaimer:
System.nanoTime doc explicitly states that the resolution is at least that of System.currentTimeMillis(), which may be > 1 ms. So no guarantee that you will get microsecond resolution.
Corollary: this probably doesn't work in all environments (you may never get n2-n1 small enough - or it may be 0 just because the resolution of your system is too low).
System.nanoTime() may be out of sync over long periods - so this is a trade off between precision and performance.
You also need to account for possible arithmetic overflow.
See also: Current time in microseconds in java
According to java.lang.System API
currentTimeMillis() Returns the current time in milliseconds
nanoTime() Returns the current value of the running Java Virtual
Machine's high resolution time source, in nanoseconds.
Strictly speaking a nanosecond is 1e-9 and millisecond is 1e-3. Therefore, a duration in nanosecs must be a multiple of 1e6 of the same duration in millisecs. This is not the case in practice, what is the reason?
scala> System.nanoTime / System.currentTimeMillis
res0: Long = 107
System.nanoTime() has an arbitrary start point; it's not unix epoch. From the Javadoc:
The value returned represents nanoseconds since some fixed but arbitrary origin time
So what you're actually calculating there is:
(unknownOffset + offsetFromEpochInNanos) / offsetFromEpochInMillis
which will almost certainly not be 1e6, unless unknownOffset happens to be arbitrarily zero.
If you can remove the effect of the unknown offset by subtracting the two times, you can see that the ratio is around 1e6:
long nanoStart = System.nanoTime();
long milliStart = System.currentTimeMillis();
Thread.sleep(2000);
long nanoEnd = System.nanoTime();
long milliEnd = System.currentTimeMillis();;
long nanoDelta = nanoEnd - nanoStart;
long milliDelta = milliEnd - milliStart;
System.out.println((double) nanoDelta / milliDelta);
Output (running 5 times):
1000058.3725
1000045.4705
999549.1579210395
1000046.101
1000038.1045
Ideone demo
So, pretty close to 1e6.
Note that it might not be this, because System.currentTimeMillis() doesn't progress smoothly, owing to corrections for clock skew. However, these should be infrequent, so most of the time when you run this code, you'll see roughly 1e6.
Everything is in the title:
Is there an infinite Duration in Java 8 equivalent to the C# Timeout.InfiniteTimeSpan Field?
A bit like:
https://msdn.microsoft.com/en-us/library/system.threading.timeout.infinitetimespan(v=vs.110).aspx
I don't think -1 ms is understood across the all java libraries as an infinite timespan, so it might be more a problem of definition.
In order to clarify a bit the context, let's say I want to make a thread asleep for an infinite amount of time without performing an infinite loop, note that this not necessarily a realistic practical use though.
I'm just wondering is there anything built-in in the Java libraries?
As an extension to #Misha's answer, this is essentially the largest duration value allowed:
public static final Duration MAX_DURATION = Duration.ofSeconds(
Long.MAX_VALUE, // Max allowed seconds
999999999L // Max nanoseconds less than a second
);
Anything more than this leads to
java.lang.ArithmeticException: long overflow
From Duration javadoc:
A physical duration could be of infinite length. For practicality, the duration is stored with constraints similar to Instant. The duration uses nanosecond resolution with a maximum value of the seconds that can be held in a long. This is greater than the current estimated age of the universe.
You certainly don't need to do an infinite loop to suspend a thread. Consider LockSupport.park() or another one of the many available mechanisms in java.util.concurrent. Can you describe your problem in more detail?
I want to return microseconds from linux as java only has wall clock times to millisecond accuracy on systems with a monotonic clock.
My exposure to jni is limited so apologies if it's a silly question.
I believe I can either make a call in the c layer to gettimeofday and return the value as jlong:
private native long getMicros();
Or perhaps alternatively take a pointer to an address and then write the value to this address:
private native void getMicros(Long ptr);
The latter throws up lots of questions in my mind like "how does c know what the binary format of jlong is" and "how would I even do this!".
I just wondered if the latter might be faster than returning a value back across the jni layer.
Any thoughts most welcome.
http://docs.oracle.com/javase/6/docs/api/java/lang/System.html#nanoTime()
"Returns the current value of the most precise available system timer, in nanoseconds.
This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary time (perhaps in the future, so values may be negative). This method provides nanosecond precision, but not necessarily nanosecond accuracy. No guarantees are made about how frequently values change. Differences in successive calls that span greater than approximately 292 years (263 nanoseconds) will not accurately compute elapsed time due to numerical overflow.
For example, to measure how long some code takes to execute:"
long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;
I'm in and android widget and checking elapsed time between two calls of System.nanoTime() and the number is huge. How do you measure elapsed time with this? it should be a fraaction of a second and instead its much more. Thanks
The System.nanoTime() returns a time value whose granularity is a nanosecond; i.e. 10-9 seconds, as described in the javadoc. The difference between two calls to System.nanoTime() that are a substantial fraction of a second apart is bound to be a large number.
If you want a time measure with a larger granularity, consider System.currentTimeMillis() ... or just divide the nanosecond values by an appropriate power of 10 to suit your application.
Note that on the Android platform there are 3 distinct system clocks that support different "measures" of time; see SystemClock. If you are programming explicitly for the Android platform, you should read the javadoc and decide which measure is most appropriate to what you are doing.
For your information, "nano-" is one of the standard prefixes defines by the International System of Units (SI) - see http://physics.nist.gov/cuu/Units/prefixes.html.
If you really think that "they" got it wrong and that "nano-" is too small, you could always write a letter to the NIST. I'm sure someone would appreciate it ... :-)
One seconds contains 1,000,000,000 nanoseconds, so as long as your number is in that range, it's reasonable.
If you want it in fractional form, just take your value / 10^9 where value is your difference in nanoTime()s.
long nanoSeconds = 500000000;
float seconds = nanoSeconds / 1000000000;
Log.i("NanoTime", nanoSeconds + " ns is the same as " + seconds + " seconds");
Your output would be:
07-27 11:35:47.196: INFO/NanoTime(14237): 500000000 ns is the same as 0.5 seconds