mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 01:07:18 +03:00
caching | kvutils | sandbox: Use a size-based cache for LF value translation. (#6432)
* caching: Split caches into new files. * caching: Rename `Cache.from` to `WeightedCache.from`. * caching: Move `Configuration` inside `WeightedCache`. * caching: Add test cases. * caching: Allow for Caffeine builders to be covariant. * caching: When instrumenting the Caffeine cache, compose, don't inherit. * caching: Add a size-based cache. * caching: Extract out common test cases into base classes. * caching: Use the size-based cache for LF value translation. CHANGELOG_BEGIN CHANGELOG_END * caching: Simplify the eviction tests. * caching: Increase the encapsulation in CaffeineCache. * caching: Commas are important. Co-authored-by: Stefano Baghino <43749967+stefanobaghino-da@users.noreply.github.com> Co-authored-by: Stefano Baghino <43749967+stefanobaghino-da@users.noreply.github.com>
This commit is contained in:
parent
ec8c209b65
commit
6496ddd903
@ -4,6 +4,7 @@
|
||||
load(
|
||||
"//bazel_tools:scala.bzl",
|
||||
"da_scala_library",
|
||||
"da_scala_test_suite",
|
||||
)
|
||||
|
||||
da_scala_library(
|
||||
@ -20,3 +21,24 @@ da_scala_library(
|
||||
"@maven//:org_scala_lang_modules_scala_java8_compat_2_12",
|
||||
],
|
||||
)
|
||||
|
||||
da_scala_library(
|
||||
name = "caching-test-lib",
|
||||
srcs = glob(["src/test/lib/scala/**/*.scala"]),
|
||||
deps = [
|
||||
":caching",
|
||||
"@maven//:org_scalactic_scalactic_2_12",
|
||||
"@maven//:org_scalatest_scalatest_2_12",
|
||||
],
|
||||
)
|
||||
|
||||
da_scala_test_suite(
|
||||
name = "caching-tests",
|
||||
srcs = glob(["src/test/suite/scala/**/*.scala"]),
|
||||
deps = [
|
||||
":caching",
|
||||
":caching-test-lib",
|
||||
"@maven//:org_scalactic_scalactic_2_12",
|
||||
"@maven//:org_scalatest_scalatest_2_12",
|
||||
],
|
||||
)
|
||||
|
@ -3,13 +3,7 @@
|
||||
|
||||
package com.daml.caching
|
||||
|
||||
import com.codahale.metrics.Gauge
|
||||
import com.daml.metrics.CacheMetrics
|
||||
import com.github.benmanes.caffeine.{cache => caffeine}
|
||||
|
||||
import scala.compat.java8.OptionConverters._
|
||||
|
||||
sealed abstract class Cache[Key, Value] {
|
||||
abstract class Cache[Key, Value] {
|
||||
def put(key: Key, value: Value): Unit
|
||||
|
||||
def get(key: Key, acquire: Key => Value): Value
|
||||
@ -23,79 +17,4 @@ object Cache {
|
||||
|
||||
def none[Key, Value]: Cache[Key, Value] = new NoCache
|
||||
|
||||
def from[Key <: AnyRef: Weight, Value <: AnyRef: Weight](
|
||||
configuration: Configuration,
|
||||
): Cache[Key, Value] =
|
||||
from(configuration, None)
|
||||
|
||||
def from[Key <: AnyRef: Weight, Value <: AnyRef: Weight](
|
||||
configuration: Configuration,
|
||||
metrics: CacheMetrics,
|
||||
): Cache[Key, Value] =
|
||||
from(configuration, Some(metrics))
|
||||
|
||||
private def from[Key <: AnyRef: Weight, Value <: AnyRef: Weight](
|
||||
configuration: Configuration,
|
||||
metrics: Option[CacheMetrics],
|
||||
): Cache[Key, Value] =
|
||||
configuration match {
|
||||
case Configuration(maximumWeight) if maximumWeight <= 0 =>
|
||||
none
|
||||
case Configuration(maximumWeight) =>
|
||||
val builder =
|
||||
caffeine.Caffeine
|
||||
.newBuilder()
|
||||
.maximumWeight(maximumWeight)
|
||||
.weigher(Weight.weigher[Key, Value])
|
||||
metrics.fold(new CaffeineCache(builder))(new InstrumentedCaffeineCache(builder, _))
|
||||
}
|
||||
|
||||
final class NoCache[Key, Value] private[Cache] extends Cache[Key, Value] {
|
||||
override def put(key: Key, value: Value): Unit = ()
|
||||
|
||||
override def get(key: Key, acquire: Key => Value): Value = acquire(key)
|
||||
|
||||
override def getIfPresent(key: Key): Option[Value] = None
|
||||
}
|
||||
|
||||
sealed class CaffeineCache[Key, Value] private[Cache] (builder: caffeine.Caffeine[Key, Value])
|
||||
extends Cache[Key, Value] {
|
||||
|
||||
private val cache = init(builder)
|
||||
|
||||
protected def init(builder: caffeine.Caffeine[Key, Value]): caffeine.Cache[Key, Value] =
|
||||
builder.build()
|
||||
|
||||
override def put(key: Key, value: Value): Unit = cache.put(key, value)
|
||||
|
||||
override def get(key: Key, acquire: Key => Value): Value =
|
||||
cache.get(key, key => acquire(key))
|
||||
|
||||
override def getIfPresent(key: Key): Option[Value] =
|
||||
Option(cache.getIfPresent(key))
|
||||
|
||||
}
|
||||
|
||||
private def size(cache: caffeine.Cache[_, _]): Gauge[Long] =
|
||||
() => cache.estimatedSize()
|
||||
|
||||
private def weight(cache: caffeine.Cache[_, _]): Gauge[Long] =
|
||||
() => cache.policy().eviction().asScala.flatMap(_.weightedSize.asScala).getOrElse(0)
|
||||
|
||||
final class InstrumentedCaffeineCache[Key, Value] private[Cache] (
|
||||
builder: caffeine.Caffeine[Key, Value],
|
||||
metrics: CacheMetrics,
|
||||
) extends CaffeineCache[Key, Value](builder) {
|
||||
|
||||
override protected def init(
|
||||
builder: caffeine.Caffeine[Key, Value],
|
||||
): caffeine.Cache[Key, Value] = {
|
||||
val cache = super.init(builder.recordStats(() => new DropwizardStatsCounter(metrics)))
|
||||
metrics.registerSizeGauge(size(cache))
|
||||
metrics.registerWeightGauge(weight(cache))
|
||||
cache
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.caching
|
||||
|
||||
import com.daml.metrics.CacheMetrics
|
||||
import com.github.benmanes.caffeine.{cache => caffeine}
|
||||
|
||||
import scala.compat.java8.OptionConverters._
|
||||
|
||||
object CaffeineCache {
|
||||
|
||||
def apply[Key <: AnyRef, Value <: AnyRef](
|
||||
builder: caffeine.Caffeine[_ >: Key, _ >: Value],
|
||||
metrics: Option[CacheMetrics],
|
||||
): Cache[Key, Value] = {
|
||||
val cache = builder.build[Key, Value]
|
||||
metrics match {
|
||||
case None => new SimpleCaffeineCache(cache)
|
||||
case Some(metrics) => new InstrumentedCaffeineCache(cache, metrics)
|
||||
}
|
||||
}
|
||||
|
||||
private final class SimpleCaffeineCache[Key <: AnyRef, Value <: AnyRef](
|
||||
cache: caffeine.Cache[Key, Value],
|
||||
) extends Cache[Key, Value] {
|
||||
override def put(key: Key, value: Value): Unit = cache.put(key, value)
|
||||
|
||||
override def get(key: Key, acquire: Key => Value): Value =
|
||||
cache.get(key, key => acquire(key))
|
||||
|
||||
override def getIfPresent(key: Key): Option[Value] =
|
||||
Option(cache.getIfPresent(key))
|
||||
}
|
||||
|
||||
private final class InstrumentedCaffeineCache[Key <: AnyRef, Value <: AnyRef](
|
||||
cache: caffeine.Cache[Key, Value],
|
||||
metrics: CacheMetrics,
|
||||
) extends Cache[Key, Value] {
|
||||
metrics.registerSizeGauge(() => cache.estimatedSize())
|
||||
metrics.registerWeightGauge(() =>
|
||||
cache.policy().eviction().asScala.flatMap(_.weightedSize.asScala).getOrElse(0))
|
||||
|
||||
private val delegate = new SimpleCaffeineCache(cache)
|
||||
|
||||
override def get(key: Key, acquire: Key => Value): Value =
|
||||
delegate.get(key, acquire)
|
||||
|
||||
override def getIfPresent(key: Key): Option[Value] =
|
||||
delegate.getIfPresent(key)
|
||||
|
||||
override def put(key: Key, value: Value): Unit =
|
||||
delegate.put(key, value)
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.caching
|
||||
|
||||
final case class Configuration(maximumWeight: Long) extends AnyVal
|
||||
|
||||
object Configuration {
|
||||
|
||||
val none: Configuration = Configuration(maximumWeight = 0)
|
||||
|
||||
}
|
12
ledger/caching/src/main/scala/com/daml/caching/NoCache.scala
Normal file
12
ledger/caching/src/main/scala/com/daml/caching/NoCache.scala
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.caching
|
||||
|
||||
final class NoCache[Key, Value] private[caching] extends Cache[Key, Value] {
|
||||
override def put(key: Key, value: Value): Unit = ()
|
||||
|
||||
override def get(key: Key, acquire: Key => Value): Value = acquire(key)
|
||||
|
||||
override def getIfPresent(key: Key): Option[Value] = None
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.caching
|
||||
|
||||
import com.daml.metrics.CacheMetrics
|
||||
import com.github.benmanes.caffeine.{cache => caffeine}
|
||||
|
||||
object SizedCache {
|
||||
|
||||
def from[Key <: AnyRef, Value <: AnyRef](configuration: Configuration): Cache[Key, Value] =
|
||||
from(configuration, None)
|
||||
|
||||
def from[Key <: AnyRef, Value <: AnyRef](
|
||||
configuration: Configuration,
|
||||
metrics: CacheMetrics,
|
||||
): Cache[Key, Value] =
|
||||
from(configuration, Some(metrics))
|
||||
|
||||
private def from[Key <: AnyRef, Value <: AnyRef](
|
||||
configuration: Configuration,
|
||||
metrics: Option[CacheMetrics],
|
||||
): Cache[Key, Value] =
|
||||
configuration match {
|
||||
case Configuration(maximumSize) if maximumSize <= 0 =>
|
||||
Cache.none
|
||||
case Configuration(maximumSize) =>
|
||||
val builder = caffeine.Caffeine
|
||||
.newBuilder()
|
||||
.maximumSize(maximumSize)
|
||||
CaffeineCache[Key, Value](builder, metrics)
|
||||
}
|
||||
|
||||
final case class Configuration(maximumSize: Long) extends AnyVal
|
||||
|
||||
object Configuration {
|
||||
|
||||
val none: Configuration = Configuration(maximumSize = 0)
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.caching
|
||||
|
||||
import com.daml.metrics.CacheMetrics
|
||||
import com.github.benmanes.caffeine.{cache => caffeine}
|
||||
|
||||
object WeightedCache {
|
||||
|
||||
def from[Key <: AnyRef: Weight, Value <: AnyRef: Weight](
|
||||
configuration: Configuration,
|
||||
): Cache[Key, Value] =
|
||||
from(configuration, None)
|
||||
|
||||
def from[Key <: AnyRef: Weight, Value <: AnyRef: Weight](
|
||||
configuration: Configuration,
|
||||
metrics: CacheMetrics,
|
||||
): Cache[Key, Value] =
|
||||
from(configuration, Some(metrics))
|
||||
|
||||
private def from[Key <: AnyRef: Weight, Value <: AnyRef: Weight](
|
||||
configuration: Configuration,
|
||||
metrics: Option[CacheMetrics],
|
||||
): Cache[Key, Value] =
|
||||
configuration match {
|
||||
case Configuration(maximumWeight) if maximumWeight <= 0 =>
|
||||
Cache.none
|
||||
case Configuration(maximumWeight) =>
|
||||
val builder =
|
||||
caffeine.Caffeine
|
||||
.newBuilder()
|
||||
.maximumWeight(maximumWeight)
|
||||
.weigher(Weight.weigher[Key, Value])
|
||||
CaffeineCache(builder, metrics)
|
||||
}
|
||||
|
||||
final case class Configuration(maximumWeight: Long) extends AnyVal
|
||||
|
||||
object Configuration {
|
||||
|
||||
val none: Configuration = Configuration(maximumWeight = 0)
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.caching
|
||||
|
||||
import org.scalatest.{Matchers, WordSpec}
|
||||
|
||||
abstract class CacheBehaviorSpecBase(name: String) extends WordSpec with Matchers {
|
||||
protected def newCache(): Cache[Integer, String]
|
||||
|
||||
name should {
|
||||
"compute the correct results" in {
|
||||
val cache = newCache()
|
||||
|
||||
cache.get(1, _.toString) should be("1")
|
||||
cache.get(2, _.toString) should be("2")
|
||||
cache.get(3, _.toString) should be("3")
|
||||
cache.get(2, _.toString) should be("2")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.caching
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
abstract class CacheSpecBase(name: String) extends CacheBehaviorSpecBase(name) {
|
||||
name should {
|
||||
"compute once, and cache" in {
|
||||
val cache = newCache()
|
||||
val counter = new AtomicInteger(0)
|
||||
|
||||
def compute(value: Integer): String = {
|
||||
counter.incrementAndGet()
|
||||
value.toString
|
||||
}
|
||||
|
||||
cache.get(1, compute)
|
||||
cache.get(1, compute)
|
||||
cache.get(1, compute)
|
||||
cache.get(2, compute)
|
||||
|
||||
counter.get() should be(2)
|
||||
}
|
||||
|
||||
"return `None` on `getIfPresent` if the value is not present" in {
|
||||
val cache = newCache()
|
||||
|
||||
cache.getIfPresent(7) should be(None)
|
||||
}
|
||||
|
||||
"return the value on `getIfPresent` if the value is present" in {
|
||||
val cache = newCache()
|
||||
|
||||
cache.get(7, _.toString) should be("7")
|
||||
cache.getIfPresent(7) should be(Some("7"))
|
||||
}
|
||||
|
||||
"`put` values" in {
|
||||
val cache = newCache()
|
||||
|
||||
cache.put(7, "7")
|
||||
cache.getIfPresent(7) should be(Some("7"))
|
||||
|
||||
val counter = new AtomicInteger(0)
|
||||
|
||||
def compute(value: Integer): String = {
|
||||
counter.incrementAndGet()
|
||||
value.toString
|
||||
}
|
||||
|
||||
cache.get(7, compute) should be("7")
|
||||
counter.get() should be(0)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.caching
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
class NoCacheSpec extends CacheBehaviorSpecBase("a non-existent cache") {
|
||||
override protected def newCache(): Cache[Integer, String] =
|
||||
Cache.none
|
||||
|
||||
"a non-existent cache" should {
|
||||
"compute every time" in {
|
||||
val cache = newCache()
|
||||
val counter = new AtomicInteger(0)
|
||||
|
||||
def compute(value: Integer): String = {
|
||||
counter.incrementAndGet()
|
||||
value.toString
|
||||
}
|
||||
|
||||
cache.get(1, compute)
|
||||
cache.get(1, compute)
|
||||
cache.get(1, compute)
|
||||
cache.get(2, compute)
|
||||
|
||||
counter.get() should be(4)
|
||||
}
|
||||
|
||||
"always return `None` on `getIfPresent`" in {
|
||||
val cache = Cache.none[Integer, String]
|
||||
|
||||
cache.getIfPresent(7) should be(None)
|
||||
cache.get(7, _.toString) should be("7")
|
||||
cache.getIfPresent(7) should be(None)
|
||||
}
|
||||
|
||||
"do nothing on `put`" in {
|
||||
val cache = Cache.none[Integer, String]
|
||||
|
||||
cache.put(7, "7")
|
||||
cache.getIfPresent(7) should be(None)
|
||||
|
||||
val counter = new AtomicInteger(0)
|
||||
|
||||
def compute(value: Integer): String = {
|
||||
counter.incrementAndGet()
|
||||
value.toString
|
||||
}
|
||||
|
||||
cache.get(7, compute) should be("7")
|
||||
counter.get() should be(1)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.caching
|
||||
|
||||
import scala.util.Random
|
||||
|
||||
class SizedCacheSpec extends CacheSpecBase("a sized cache") {
|
||||
override protected def newCache(): Cache[Integer, String] =
|
||||
SizedCache.from[Integer, String](SizedCache.Configuration(maximumSize = 16))
|
||||
|
||||
"a sized cache" should {
|
||||
"evict values eventually, once the size limit has been reached" in {
|
||||
val cache =
|
||||
SizedCache.from[Integer, String](SizedCache.Configuration(maximumSize = 256))
|
||||
val values = Iterator.continually[Integer](Random.nextInt).take(1000).toSet.toVector
|
||||
|
||||
values.foreach { value =>
|
||||
cache.get(value, _.toString)
|
||||
}
|
||||
val cachedValues = values.map(cache.getIfPresent).filter(_.isDefined)
|
||||
|
||||
cachedValues.length should (be > 16 and be < 500)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.caching
|
||||
|
||||
import scala.util.Random
|
||||
|
||||
class WeightedCacheSpec extends CacheSpecBase("a weighted cache") {
|
||||
implicit val `Int Weight`: Weight[Integer] = (_: Integer) => 1
|
||||
implicit val `String Weight`: Weight[String] = _.length.toLong
|
||||
|
||||
override protected def newCache(): Cache[Integer, String] =
|
||||
WeightedCache.from[Integer, String](WeightedCache.Configuration(maximumWeight = 16))
|
||||
|
||||
"a weighted cache" should {
|
||||
"evict values eventually, once the weight limit has been reached" in {
|
||||
val cache =
|
||||
WeightedCache.from[Integer, String](WeightedCache.Configuration(maximumWeight = 256))
|
||||
val values = Iterator.continually[Integer](Random.nextInt).take(1000).toSet.toVector
|
||||
|
||||
values.foreach { value =>
|
||||
cache.get(value, _.toString)
|
||||
}
|
||||
val cachedValues = values.map(cache.getIfPresent).filter(_.isDefined)
|
||||
|
||||
cachedValues.length should (be > 16 and be < 500)
|
||||
}
|
||||
}
|
||||
}
|
@ -68,7 +68,7 @@ object Main {
|
||||
config.extra.batchingLedgerWriterConfig,
|
||||
participantId = participantConfig.participantId,
|
||||
metrics = metrics,
|
||||
stateValueCache = caching.Cache.from(
|
||||
stateValueCache = caching.WeightedCache.from(
|
||||
configuration = config.stateValueCache,
|
||||
metrics = metrics.daml.kvutils.submission.validator.stateValueCache,
|
||||
),
|
||||
|
@ -70,7 +70,7 @@ object SqlLedgerFactory extends LedgerFactory[ReadWriteService, ExtraConfig] {
|
||||
metrics = metrics,
|
||||
engine,
|
||||
jdbcUrl,
|
||||
stateValueCache = caching.Cache.from(
|
||||
stateValueCache = caching.WeightedCache.from(
|
||||
configuration = config.stateValueCache,
|
||||
metrics = metrics.daml.kvutils.submission.validator.stateValueCache,
|
||||
),
|
||||
|
@ -25,9 +25,9 @@ final case class Config[Extra](
|
||||
participants: Seq[ParticipantConfig],
|
||||
maxInboundMessageSize: Int,
|
||||
eventsPageSize: Int,
|
||||
stateValueCache: caching.Configuration,
|
||||
lfValueTranslationEventCache: caching.Configuration,
|
||||
lfValueTranslationContractCache: caching.Configuration,
|
||||
stateValueCache: caching.WeightedCache.Configuration,
|
||||
lfValueTranslationEventCache: caching.SizedCache.Configuration,
|
||||
lfValueTranslationContractCache: caching.SizedCache.Configuration,
|
||||
seeding: Seeding,
|
||||
metricsReporter: Option[MetricsReporter],
|
||||
metricsReportingInterval: Duration,
|
||||
@ -65,9 +65,9 @@ object Config {
|
||||
participants = Vector.empty,
|
||||
maxInboundMessageSize = DefaultMaxInboundMessageSize,
|
||||
eventsPageSize = IndexConfiguration.DefaultEventsPageSize,
|
||||
stateValueCache = caching.Configuration.none,
|
||||
lfValueTranslationEventCache = caching.Configuration.none,
|
||||
lfValueTranslationContractCache = caching.Configuration.none,
|
||||
stateValueCache = caching.WeightedCache.Configuration.none,
|
||||
lfValueTranslationEventCache = caching.SizedCache.Configuration.none,
|
||||
lfValueTranslationContractCache = caching.SizedCache.Configuration.none,
|
||||
seeding = Seeding.Strong,
|
||||
metricsReporter = None,
|
||||
metricsReportingInterval = Duration.ofSeconds(10),
|
||||
@ -176,9 +176,9 @@ object Config {
|
||||
.action((maximumLfValueTranslationCacheEntries, config) =>
|
||||
config.copy(
|
||||
lfValueTranslationEventCache = config.lfValueTranslationEventCache.copy(
|
||||
maximumWeight = maximumLfValueTranslationCacheEntries),
|
||||
maximumSize = maximumLfValueTranslationCacheEntries),
|
||||
lfValueTranslationContractCache = config.lfValueTranslationContractCache.copy(
|
||||
maximumWeight = maximumLfValueTranslationCacheEntries),
|
||||
maximumSize = maximumLfValueTranslationCacheEntries),
|
||||
))
|
||||
|
||||
private val seedingMap =
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
package com.daml.ledger.validator.caching
|
||||
|
||||
import com.daml.caching.{Cache, Configuration}
|
||||
import com.daml.caching.{Cache, WeightedCache}
|
||||
import com.daml.ledger.participant.state.kvutils.DamlKvutils.{
|
||||
DamlLogEntry,
|
||||
DamlLogEntryId,
|
||||
@ -51,7 +51,7 @@ class CachingCommitStrategySpec extends AsyncWordSpec with Matchers with Mockito
|
||||
}
|
||||
|
||||
private def newCache(): Cache[DamlStateKey, DamlStateValue] =
|
||||
Cache.from[DamlStateKey, DamlStateValue](Configuration(1024))
|
||||
WeightedCache.from[DamlStateKey, DamlStateValue](WeightedCache.Configuration(1024))
|
||||
|
||||
private def createInstance(
|
||||
cache: Cache[DamlStateKey, DamlStateValue],
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
package com.daml.ledger.validator.caching
|
||||
|
||||
import com.daml.caching.{Cache, Configuration}
|
||||
import com.daml.caching.WeightedCache
|
||||
import com.daml.ledger.participant.state.kvutils.DamlKvutils.{DamlStateKey, DamlStateValue}
|
||||
import com.daml.ledger.participant.state.kvutils.caching.`Message Weight`
|
||||
import com.daml.ledger.validator.{DamlLedgerStateReader, DefaultStateKeySerializationStrategy}
|
||||
@ -81,7 +81,7 @@ class CachingDamlLedgerStateReaderSpec
|
||||
|
||||
private def newInstance(damlLedgerStateReader: DamlLedgerStateReader, shouldCache: Boolean)(
|
||||
implicit executionContext: ExecutionContext): CachingDamlLedgerStateReader = {
|
||||
val cache = Cache.from[DamlStateKey, DamlStateValue](Configuration(1024))
|
||||
val cache = WeightedCache.from[DamlStateKey, DamlStateValue](WeightedCache.Configuration(1024))
|
||||
new CachingDamlLedgerStateReader(
|
||||
cache,
|
||||
_ => shouldCache,
|
||||
|
@ -290,10 +290,10 @@ object Cli {
|
||||
config.copy(
|
||||
lfValueTranslationEventCacheConfiguration =
|
||||
config.lfValueTranslationEventCacheConfiguration
|
||||
.copy(maximumWeight = maximumLfValueTranslationCacheEntries),
|
||||
.copy(maximumSize = maximumLfValueTranslationCacheEntries),
|
||||
lfValueTranslationContractCacheConfiguration =
|
||||
config.lfValueTranslationContractCacheConfiguration
|
||||
.copy(maximumWeight = maximumLfValueTranslationCacheEntries)
|
||||
.copy(maximumSize = maximumLfValueTranslationCacheEntries)
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -8,7 +8,7 @@ import java.nio.file.Path
|
||||
import java.time.Duration
|
||||
|
||||
import ch.qos.logback.classic.Level
|
||||
import com.daml.caching
|
||||
import com.daml.caching.SizedCache
|
||||
import com.daml.ledger.api.auth.AuthService
|
||||
import com.daml.ledger.api.tls.TlsConfiguration
|
||||
import com.daml.ledger.participant.state.v1.SeedService.Seeding
|
||||
@ -41,8 +41,8 @@ final case class SandboxConfig(
|
||||
metricsReporter: Option[MetricsReporter],
|
||||
metricsReportingInterval: Duration,
|
||||
eventsPageSize: Int,
|
||||
lfValueTranslationEventCacheConfiguration: caching.Configuration,
|
||||
lfValueTranslationContractCacheConfiguration: caching.Configuration,
|
||||
lfValueTranslationEventCacheConfiguration: SizedCache.Configuration,
|
||||
lfValueTranslationContractCacheConfiguration: SizedCache.Configuration,
|
||||
profileDir: Option[Path],
|
||||
)
|
||||
|
||||
@ -55,7 +55,8 @@ object SandboxConfig {
|
||||
|
||||
val DefaultTimeProviderType: TimeProviderType = TimeProviderType.WallClock
|
||||
|
||||
val DefaultLfValueTranslationCacheConfiguration = caching.Configuration.none
|
||||
val DefaultLfValueTranslationCacheConfiguration: SizedCache.Configuration =
|
||||
SizedCache.Configuration.none
|
||||
|
||||
lazy val nextDefault: SandboxConfig =
|
||||
SandboxConfig(
|
||||
|
@ -142,8 +142,8 @@ class Runner(config: SandboxConfig) extends ResourceOwner[Port] {
|
||||
resetOnStartup = isReset,
|
||||
timeProvider = timeServiceBackend.getOrElse(TimeProvider.UTC),
|
||||
seedService = SeedService(seeding),
|
||||
stateValueCache = caching.Cache.from(
|
||||
caching.Configuration(
|
||||
stateValueCache = caching.WeightedCache.from(
|
||||
caching.WeightedCache.Configuration(
|
||||
maximumWeight = MaximumStateValueCacheSize,
|
||||
)),
|
||||
engine = engine
|
||||
|
@ -5,9 +5,9 @@ package com.daml.platform.store.dao.events
|
||||
|
||||
import anorm.NamedParameter
|
||||
import com.daml.caching
|
||||
import com.daml.ledger.api.v1.value.{Record => ApiRecord, Value => ApiValue}
|
||||
import com.daml.ledger.EventId
|
||||
import com.daml.ledger.api.v1.event.{CreatedEvent, ExercisedEvent}
|
||||
import com.daml.ledger.api.v1.value.{Record => ApiRecord, Value => ApiValue}
|
||||
import com.daml.metrics.Metrics
|
||||
import com.daml.platform.participant.util.LfEngineToApi
|
||||
import com.daml.platform.store.dao.events.{Value => LfValue}
|
||||
@ -185,17 +185,19 @@ object LfValueTranslation {
|
||||
def none: Cache = Cache(caching.Cache.none, caching.Cache.none)
|
||||
|
||||
def newInstance(
|
||||
eventConfiguration: caching.Configuration,
|
||||
contractConfiguration: caching.Configuration): Cache =
|
||||
eventConfiguration: caching.SizedCache.Configuration,
|
||||
contractConfiguration: caching.SizedCache.Configuration
|
||||
): Cache =
|
||||
Cache(
|
||||
events = EventCache.newInstance(eventConfiguration),
|
||||
contracts = ContractCache.newInstance(contractConfiguration),
|
||||
)
|
||||
|
||||
def newInstrumentedInstance(
|
||||
eventConfiguration: caching.Configuration,
|
||||
contractConfiguration: caching.Configuration,
|
||||
metrics: Metrics): Cache =
|
||||
eventConfiguration: caching.SizedCache.Configuration,
|
||||
contractConfiguration: caching.SizedCache.Configuration,
|
||||
metrics: Metrics
|
||||
): Cache =
|
||||
Cache(
|
||||
events = EventCache.newInstrumentedInstance(eventConfiguration, metrics),
|
||||
contracts = ContractCache.newInstrumentedInstance(contractConfiguration, metrics),
|
||||
@ -204,23 +206,14 @@ object LfValueTranslation {
|
||||
|
||||
object EventCache {
|
||||
|
||||
private implicit object `Key Weight` extends caching.Weight[Key] {
|
||||
override def weigh(value: Key): caching.Cache.Size =
|
||||
0 // make sure that only the value is counted
|
||||
}
|
||||
|
||||
private implicit object `Value Weight` extends caching.Weight[Value] {
|
||||
override def weigh(value: Value): caching.Cache.Size =
|
||||
1 // TODO replace this with something to avoid weights entirely
|
||||
}
|
||||
|
||||
def newInstance(configuration: caching.Configuration): EventCache =
|
||||
caching.Cache.from(configuration)
|
||||
def newInstance(configuration: caching.SizedCache.Configuration): EventCache =
|
||||
caching.SizedCache.from(configuration)
|
||||
|
||||
def newInstrumentedInstance(
|
||||
configuration: caching.Configuration,
|
||||
metrics: Metrics): EventCache =
|
||||
caching.Cache.from(
|
||||
configuration: caching.SizedCache.Configuration,
|
||||
metrics: Metrics
|
||||
): EventCache =
|
||||
caching.SizedCache.from(
|
||||
configuration = configuration,
|
||||
metrics = metrics.daml.index.db.translation.cache,
|
||||
)
|
||||
@ -250,23 +243,14 @@ object LfValueTranslation {
|
||||
|
||||
object ContractCache {
|
||||
|
||||
private implicit object `Key Weight` extends caching.Weight[Key] {
|
||||
override def weigh(value: Key): caching.Cache.Size =
|
||||
0 // make sure that only the value is counted
|
||||
}
|
||||
|
||||
private implicit object `Value Weight` extends caching.Weight[Value] {
|
||||
override def weigh(value: Value): caching.Cache.Size =
|
||||
1 // TODO replace this with something to avoid weights entirely
|
||||
}
|
||||
|
||||
def newInstance(configuration: caching.Configuration): ContractCache =
|
||||
caching.Cache.from(configuration)
|
||||
def newInstance(configuration: caching.SizedCache.Configuration): ContractCache =
|
||||
caching.SizedCache.from(configuration)
|
||||
|
||||
def newInstrumentedInstance(
|
||||
configuration: caching.Configuration,
|
||||
metrics: Metrics): ContractCache =
|
||||
caching.Cache.from(
|
||||
configuration: caching.SizedCache.Configuration,
|
||||
metrics: Metrics
|
||||
): ContractCache =
|
||||
caching.SizedCache.from(
|
||||
configuration = configuration,
|
||||
metrics = metrics.daml.index.db.translation.cache,
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user