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>'].