Как кешировать результаты в scala? - PullRequest
21 голосов
/ 06 сентября 2010

На этой странице есть описание метода использования getOrElseUpdate Карты:

object WithCache{
  val cacheFun1 = collection.mutable.Map[Int, Int]()
  def fun1(i:Int) = i*i
  def catchedFun1(i:Int) = cacheFun1.getOrElseUpdate(i, fun1(i))
}

Таким образом, вы можете использовать catchedFun1, который проверит, содержит ли cacheFun1 ключ и возвращаемое значениесвязано с этим.В противном случае он вызовет fun1, затем кеширует результат fun1 в cacheFun1, затем возвращает результат fun1.

Я вижу одну потенциальную опасность - cacheFun1 может статьбольшой.Так что cacheFun1 надо как-то чистить сборщиком мусора?

PS А как же scala.collection.mutable.WeakHashMap and java.lang.ref.*?

Ответы [ 5 ]

16 голосов
/ 06 сентября 2010

См. Шаблон заметки и Реализация Scalaz указанной бумаги.

Также ознакомьтесь с реализацией STM, такой как Akka .

Не то чтобы это было только локальное кэширование, поэтому вы можете захотеть посмотреть в распределенный кеш или STM , например CCSTM , Terracotta или Hazelcast

8 голосов
/ 05 марта 2014

Взгляните на спрей кеширования (супер прост в использовании)

http://spray.io/documentation/1.1-SNAPSHOT/spray-caching/

облегчает работу и имеет некоторые приятные функции

например:

      import spray.caching.{LruCache, Cache}

      //this is using Play for a controller example getting something from a user and caching it
      object CacheExampleWithPlay extends Controller{

        //this will actually create a ExpiringLruCache and hold data for 48 hours
        val myCache: Cache[String] = LruCache(timeToLive = new FiniteDuration(48, HOURS))

        def putSomeThingInTheCache(@PathParam("getSomeThing") someThing: String) = Action {
          //put received data from the user in the cache
          myCache(someThing, () => future(someThing))
          Ok(someThing)
        }

        def checkIfSomeThingInTheCache(@PathParam("checkSomeThing") someThing: String) = Action {
          if (myCache.get(someThing).isDefined)
            Ok(s"just $someThing found this in the cache")
          else
            NotFound(s"$someThing NOT found this in the cache")
        }
      }
6 голосов
/ 06 сентября 2010

В списке рассылки scala они иногда указывают на MapMaker в библиотеке коллекций Google .Возможно, вы захотите взглянуть на это.

3 голосов
/ 03 апреля 2017

Для простого кеширования я все еще использую решение для кэширования Guava в Scala.Легкий и проверенный в бою.

Если он соответствует вашим требованиям и ограничениям, как правило, изложенным ниже, это может быть отличным вариантом:

  • Желание потратить немного памяти для повышения скорости.
  • Ожидается, что ключи иногда будут запрашиваться более одного раза.
  • В вашем кеше не нужно хранить больше данных, чем умещается в оперативной памяти.(Кэши Guava являются локальными для одного запуска вашего приложения. Они не хранят данные в файлах или на внешних серверах.)

Пример использования этого будет примерно таким:

  lazy val cachedData = CacheBuilder.newBuilder()
    .expireAfterWrite(60, TimeUnit.MINUTES)
    .maximumSize(10)
    .build(
      new CacheLoader[Key, Data] {
        def load(key: Key): Data = {
          veryExpansiveDataCreation(key)
        }
      }
    )

Чтобы читать из него, вы можете использовать что-то вроде:

  def cachedData(ketToData: Key): Data = {
    try {
      return cachedData.get(ketToData)
    } catch {
      case ee: Exception => throw new YourSpecialException(ee.getMessage);
    }
  }
2 голосов
/ 03 января 2014

Поскольку это не было упомянуто ранее, позвольте мне поставить на стол свет Spray-Caching , который можно использовать независимо от Spray и обеспечивает ожидаемый размер, время жизни, время жизнистратегии холостого выселения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...