Подтвердить что ты не робот

Как кэшировать результаты в scala?

Эта страница содержит описание метода использования карты 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 нужно как-то очистить сборщик мусора?

P.S. Что насчет scala.collection.mutable.WeakHashMap and java.lang.ref.*?

4b9b3361

Ответ 1

См. шаблон памятки и реализация Scalaz указанной статьи.

Также проверьте реализацию STM, например Akka.

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

Ответ 2

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

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")
        }
      }

Ответ 4

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

Ответ 5

Для простых запросов кэширования я все еще использую Guava cache solution в 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);
    }
  }