简体   繁体   中英

How to cache results in scala?

This page has a description of Map's getOrElseUpdate usage method:

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

So you can use catchedFun1 which will check if cacheFun1 contains key and return value associated with it. Otherwise, it will invoke fun1 , then cache fun1 's result in cacheFun1 , then return fun1 's result.

I can see one potential danger - cacheFun1 can became to large. So cacheFun1 must be cleaned somehow by garbage collector?

PS What about scala.collection.mutable.WeakHashMap and java.lang.ref.* ?

See the Memo pattern and the Scalaz implementation of said paper.

Also check out a STM implementation such as Akka .

Not that this is only local caching so you might want to lookinto a distributed cache or STM such as CCSTM , Terracotta or Hazelcast

Take a look at spray caching (super simple to use)

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

makes the job easy and has some nice features

for example :

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

On the scala mailing list they sometimes point to the MapMaker in the Google collections library . You might want to have a look at that.

For simple caching needs, I'm still using Guava cache solution in Scala as well. Lightweight and battle tested.

If it fit's your requirements and constraints generally outlined below, it could be a great option:

  • Willing to spend some memory to improve speed.
  • Expecting that keys will sometimes get queried more than once.
  • Your cache will not need to store more data than what would fit in RAM. (Guava caches are local to a single run of your application. They do not store data in files, or on outside servers.)

Example for using it will be something like this:

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

To read from it, you can use something like:

  def cachedData(ketToData: Key): Data = {
    try {
      return cachedData.get(ketToData)
    } catch {
      case ee: Exception => throw new YourSpecialException(ee.getMessage);
    }
  }

由于之前没有提到过,让我把可以独立于 Spray 使用的轻量级Spray-Caching放在桌面上,并提供预期的大小、生存时间、空闲时间驱逐策略。

We are using Scaffeine (Scala + Caffeine), and you can read abouts its pros/cons compared to other frameworks over here .

You add your sbt,

"com.github.blemale" %% "scaffeine" % "4.0.1"

Build you cache

import com.github.blemale.scaffeine.{Cache, Scaffeine}
import scala.concurrent.duration._

val cachedItems: Cache[String, Int] = 
  Scaffeine()
    .recordStats()
    .expireAtferWrite(60.seconds)
    .maximumSize(500)
    .buid[String, Int]()

cachedItems.put("key", 1) // Add items

cache.getIfPresent("key") // Returns an option

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM