You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by ra...@apache.org on 2017/09/22 12:03:19 UTC

[incubator-openwhisk] branch master updated: Compute UUIDs in a non-blocking fashion. (#2785)

This is an automated email from the ASF dual-hosted git repository.

rabbah pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git


The following commit(s) were added to refs/heads/master by this push:
     new 77ea5b2  Compute UUIDs in a non-blocking fashion. (#2785)
77ea5b2 is described below

commit 77ea5b250c4eb55c1063995be5cb9e90e51becd0
Author: Markus Thömmes <ma...@me.com>
AuthorDate: Fri Sep 22 14:03:16 2017 +0200

    Compute UUIDs in a non-blocking fashion. (#2785)
    
    Java's UUID.randomUUID() is known the be synchronized and blocking which causes thread-contention and thus performance problems.
    
    SecureRandom.nextBytes is the synchronized piece, so using a ThreadLocal instance resolves thread contention there. Switching Java's randomness source to the non-blocking /dev/urandom resolves blocking of the computation itself.
---
 common/scala/build.gradle                          |  1 +
 .../connector/kafka/KafkaProducerConnector.scala   |  6 ++----
 .../scala/whisk/core/entity/ActivationId.scala     |  4 ++--
 .../src/main/scala/whisk/core/entity/UUID.scala    | 23 ++++++++++++++++++++--
 core/controller/build.gradle                       |  2 +-
 5 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/common/scala/build.gradle b/common/scala/build.gradle
index 935d839..03ef713 100644
--- a/common/scala/build.gradle
+++ b/common/scala/build.gradle
@@ -26,6 +26,7 @@ dependencies {
     compile 'org.apache.zookeeper:zookeeper:3.4.10'
     compile 'org.apache.kafka:kafka-clients:0.10.2.1'
     compile 'org.apache.httpcomponents:httpclient:4.4.1'
+    compile 'com.fasterxml.uuid:java-uuid-generator:3.1.3'
     compile 'com.github.ben-manes.caffeine:caffeine:2.4.0'
     compile 'com.google.code.findbugs:jsr305:3.0.2'
 }
diff --git a/common/scala/src/main/scala/whisk/connector/kafka/KafkaProducerConnector.scala b/common/scala/src/main/scala/whisk/connector/kafka/KafkaProducerConnector.scala
index 3f524a8..8e8289d 100644
--- a/common/scala/src/main/scala/whisk/connector/kafka/KafkaProducerConnector.scala
+++ b/common/scala/src/main/scala/whisk/connector/kafka/KafkaProducerConnector.scala
@@ -18,29 +18,27 @@
 package whisk.connector.kafka
 
 import java.util.Properties
-import java.util.UUID
 
 import scala.concurrent.ExecutionContext
 import scala.concurrent.Future
 import scala.concurrent.Promise
 import scala.util.Failure
 import scala.util.Success
-
 import org.apache.kafka.clients.producer.Callback
 import org.apache.kafka.clients.producer.KafkaProducer
 import org.apache.kafka.clients.producer.ProducerConfig
 import org.apache.kafka.clients.producer.ProducerRecord
 import org.apache.kafka.clients.producer.RecordMetadata
 import org.apache.kafka.common.serialization.StringSerializer
-
 import whisk.common.Counter
 import whisk.common.Logging
 import whisk.core.connector.Message
 import whisk.core.connector.MessageProducer
+import whisk.core.entity.UUIDs
 
 class KafkaProducerConnector(kafkahost: String,
                              implicit val executionContext: ExecutionContext,
-                             id: String = UUID.randomUUID().toString)(implicit logging: Logging)
+                             id: String = UUIDs.randomUUID().toString)(implicit logging: Logging)
     extends MessageProducer {
 
   override def sentCount() = sentCounter.cur
diff --git a/common/scala/src/main/scala/whisk/core/entity/ActivationId.scala b/common/scala/src/main/scala/whisk/core/entity/ActivationId.scala
index 4ad917f..0a1cb25 100644
--- a/common/scala/src/main/scala/whisk/core/entity/ActivationId.scala
+++ b/common/scala/src/main/scala/whisk/core/entity/ActivationId.scala
@@ -49,7 +49,7 @@ protected[whisk] class ActivationId private (private val id: java.util.UUID) ext
 protected[core] object ActivationId extends ArgNormalizer[ActivationId] {
 
   protected[core] trait ActivationIdGenerator {
-    def make(): ActivationId = new ActivationId(java.util.UUID.randomUUID())
+    def make(): ActivationId = new ActivationId(UUIDs.randomUUID())
   }
 
   /**
@@ -77,7 +77,7 @@ protected[core] object ActivationId extends ArgNormalizer[ActivationId] {
    *
    * @return new ActivationId
    */
-  protected[core] def apply(): ActivationId = new ActivationId(java.util.UUID.randomUUID())
+  protected[core] def apply(): ActivationId = new ActivationId(UUIDs.randomUUID())
 
   /**
    * Overrides factory method so that string is not interpreted as number
diff --git a/common/scala/src/main/scala/whisk/core/entity/UUID.scala b/common/scala/src/main/scala/whisk/core/entity/UUID.scala
index 11b56b4..3518077 100644
--- a/common/scala/src/main/scala/whisk/core/entity/UUID.scala
+++ b/common/scala/src/main/scala/whisk/core/entity/UUID.scala
@@ -17,8 +17,11 @@
 
 package whisk.core.entity
 
-import scala.util.Try
+import java.security.SecureRandom
+
+import com.fasterxml.uuid.Generators
 
+import scala.util.Try
 import spray.json.JsString
 import spray.json.JsValue
 import spray.json.RootJsonFormat
@@ -59,7 +62,7 @@ protected[core] object UUID extends ArgNormalizer[UUID] {
    *
    * @return new UUID
    */
-  protected[core] def apply(): UUID = new UUID(java.util.UUID.randomUUID())
+  protected[core] def apply(): UUID = new UUID(UUIDs.randomUUID())
 
   implicit val serdes = new RootJsonFormat[UUID] {
     def write(u: UUID) = u.toJson
@@ -71,3 +74,19 @@ protected[core] object UUID extends ArgNormalizer[UUID] {
       } getOrElse deserializationError("uuid malformed")
   }
 }
+
+object UUIDs {
+  private val generator = new ThreadLocal[SecureRandom] {
+    override def initialValue() = new SecureRandom()
+  }
+
+  /**
+   * Static factory to retrieve a type 4 (pseudo randomly generated) UUID.
+   *
+   * The {@code java.util.UUID} is generated using a pseudo random number
+   * generator local to the thread.
+   *
+   * @return  A randomly generated {@code java.util.UUID}
+   */
+  def randomUUID(): java.util.UUID = Generators.randomBasedGenerator(generator.get()).generate()
+}
diff --git a/core/controller/build.gradle b/core/controller/build.gradle
index c4abec3..f9d7726 100644
--- a/core/controller/build.gradle
+++ b/core/controller/build.gradle
@@ -20,4 +20,4 @@ tasks.withType(ScalaCompile) {
 }
 
 mainClassName = "whisk.core.controller.Controller"
-applicationDefaultJvmArgs = ["-XX:+CrashOnOutOfMemoryError"]
+applicationDefaultJvmArgs = ["-XX:+CrashOnOutOfMemoryError", "-Djava.security.egd=file:/dev/./urandom"]

-- 
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].