Github user dszeto commented on a diff in the pull request: https://github.com/apache/incubator-predictionio/pull/424#discussion_r134588503 --- Diff: data/src/main/scala/org/apache/predictionio/data/store/Common.scala --- @@ -19,35 +19,46 @@ package org.apache.predictionio.data.store import org.apache.predictionio.data.storage.Storage +import scala.collection.mutable import grizzled.slf4j.Logger private[predictionio] object Common { @transient lazy val logger = Logger[this.type] @transient lazy private val appsDb = Storage.getMetaDataApps() @transient lazy private val channelsDb = Storage.getMetaDataChannels() + // Memoize app & channel name-to-ID resolution to avoid excessive storage IO + @transient lazy val appNameToIdCache = + mutable.Map[(String, Option[String]), (Int, Option[Int])]() /* throw exception if invalid app name or channel name */ def appNameToId(appName: String, channelName: Option[String]): (Int, Option[Int]) = { - val appOpt = appsDb.getByName(appName) - - appOpt.map { app => - val channelMap: Map[String, Int] = channelsDb.getByAppid(app.id) - .map(c => (c.name, c.id)).toMap - - val channelId: Option[Int] = channelName.map { ch => - if (channelMap.contains(ch)) { - channelMap(ch) - } else { - logger.error(s"Invalid channel name ${ch}.") - throw new IllegalArgumentException(s"Invalid channel name ${ch}.") + val cacheHit = appNameToIdCache.get(appName, channelName) + cacheHit match { + case Some((a: Int, c: Option[Int])) => (a,c) + case None => { + val appOpt = appsDb.getByName(appName) + + appOpt.map { app => + val channelMap: Map[String, Int] = channelsDb.getByAppid(app.id) + .map(c => (c.name, c.id)).toMap + + val channelId: Option[Int] = channelName.map { ch => + if (channelMap.contains(ch)) { + channelMap(ch) + } else { + logger.error(s"Invalid channel name ${ch}.") + throw new IllegalArgumentException(s"Invalid channel name ${ch}.") + } + } + + appNameToIdCache((appName, channelName)) = (app.id, channelId) + (app.id, channelId) + }.getOrElse { + logger.error(s"Invalid app name ${appName}") + throw new IllegalArgumentException(s"Invalid app name ${appName}") --- End diff -- It looks like this whole block can be simplified to ```scala appNameToIdCache.getOrElseUpdate((appName, channelName), { val appOpt = ... appOpt map { app => ... val channelId: Option[Int] = ... // do not need to set appNameToIdCache here manually (app.id, channelId) } getOrElse { ... } }) ```
--- If your project is set up for it, you can reply to this email and have your reply appear on GitHub as well. If your project does not have this feature enabled and wishes so, or if the feature is enabled but not working, please contact infrastructure at infrastruct...@apache.org or file a JIRA ticket with INFRA. ---