Permalink
Browse files

SI-7546 Use likely monotonic clock source for durations

System.currentTimeMillis is affected by wall-clock time, which means
things can appear to jump back in time.
Use System.nanoTime which is more likely¹ to be monotonic instead.

¹ See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6458294
  "nanoTime affected by system clock change on Linux (RH9) or in
   general lacks monotonicity".
  • Loading branch information...
1 parent b345b42 commit a3a5e4a6f548bf8b9d2874a5d6578c8364a1984f @soc soc committed Dec 11, 2013
View
5 src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -8,6 +8,7 @@ package tools.nsc
package backend.icode.analysis
import scala.collection.{mutable, immutable}
+import java.util.concurrent.TimeUnit
/** A data-flow analysis on types, that works on `ICode`.
*
@@ -709,14 +710,14 @@ abstract class TypeFlowAnalysis {
private var lastStart = 0L
def start() {
- lastStart = System.currentTimeMillis
+ lastStart = System.nanoTime()
}
/** Stop the timer and return the number of milliseconds since the last
* call to start. The 'millis' field is increased by the elapsed time.
*/
def stop: Long = {
- val elapsed = System.currentTimeMillis - lastStart
+ val elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - lastStart)
millis += elapsed
elapsed
}
View
6 src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
@@ -5,6 +5,8 @@
package scala.tools.nsc
package backend.opt
+import java.util.concurrent.TimeUnit
+
/**
* This optimization phase inlines the exception handlers so that further phases can optimize the code better
*
@@ -91,12 +93,12 @@ abstract class InlineExceptionHandlers extends SubComponent {
/** Apply exception handler inlining to a class */
override def apply(c: IClass): Unit =
if (settings.inlineHandlers) {
- val startTime = System.currentTimeMillis
+ val startTime = System.nanoTime()
currentClass = c
debuglog("Starting InlineExceptionHandlers on " + c)
c.methods foreach applyMethod
- debuglog("Finished InlineExceptionHandlers on " + c + "... " + (System.currentTimeMillis - startTime) + "ms")
+ debuglog("Finished InlineExceptionHandlers on " + c + "... " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + "ms")
currentClass = null
}
View
16 src/library/scala/concurrent/SyncVar.scala
@@ -8,6 +8,8 @@
package scala.concurrent
+import java.util.concurrent.TimeUnit
+
/** A class to provide safe concurrent access to a mutable cell.
* All methods are synchronized.
*
@@ -23,14 +25,16 @@ class SyncVar[A] {
value.get
}
- /** Waits `timeout` millis. If `timeout <= 0` just returns 0. If the system clock
- * went backward, it will return 0, so it never returns negative results.
- */
+ /** Waits `timeout` millis. If `timeout <= 0` just returns 0.
+ * It never returns negative results.
+ */
private def waitMeasuringElapsed(timeout: Long): Long = if (timeout <= 0) 0 else {
- val start = System.currentTimeMillis
+ val start = System.nanoTime()
wait(timeout)
- val elapsed = System.currentTimeMillis - start
- if (elapsed < 0) 0 else elapsed
+ val elapsed = System.nanoTime() - start
+ // nanoTime should be monotonic, but it's not possible to rely on that.
+ // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6458294.
+ if (elapsed < 0) 0 else TimeUnit.NANOSECONDS.toMillis(elapsed)
}
/** Waits for this SyncVar to become defined at least for
View
3 src/reflect/scala/reflect/internal/SymbolTable.scala
@@ -10,6 +10,7 @@ package internal
import scala.annotation.elidable
import scala.collection.{ mutable, immutable }
import util._
+import java.util.concurrent.TimeUnit
abstract class SymbolTable extends macros.Universe
with Collections
@@ -55,7 +56,7 @@ abstract class SymbolTable extends macros.Universe
def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg))
protected def elapsedMessage(msg: String, start: Long) =
- msg + " in " + (System.currentTimeMillis() - start) + "ms"
+ msg + " in " + (TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) - start) + "ms"
def informProgress(msg: String) = if (settings.verbose) inform("[" + msg + "]")
def informTime(msg: String, start: Long) = informProgress(elapsedMessage(msg, start))

0 comments on commit a3a5e4a

Please sign in to comment.