Skip to content

Commit

Permalink
use BinaryFen also in in-memory caches
Browse files Browse the repository at this point in the history
  • Loading branch information
niklasf committed Apr 14, 2024
1 parent a673945 commit 4ebf67a
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 56 deletions.
25 changes: 14 additions & 11 deletions src/main/scala/evalCache/EvalCacheApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@ final class EvalCacheApi(mongo: Mongo)(using
import EvalCacheBsonHandlers.given

def get(sri: Sri, e: EvalGet, emit: Emit[ClientIn]): Unit =
Id.from(e.variant, e.fen).foreach: id =>
getEntry(id)
.map:
_.flatMap(_.makeBestMultiPvEval(e.multiPv))
.map(monitorRequest(e.fen, Monitor.evalCache.single))
.foreach:
_.foreach: eval =>
emit:
ClientIn.EvalHit:
EvalCacheJsonHandlers.writeEval(eval, e.fen) + ("path" -> JsString(e.path.value))
Id.from(e.variant, e.fen)
.foreach: id =>
getEntry(id)
.map:
_.flatMap(_.makeBestMultiPvEval(e.multiPv))
.map(monitorRequest(e.fen, Monitor.evalCache.single))
.foreach:
_.foreach: eval =>
emit:
ClientIn.EvalHit:
EvalCacheJsonHandlers.writeEval(eval, e.fen) + ("path" -> JsString(e.path.value))
if e.up then upgrade.register(sri, e)

def getMulti(sri: Sri, e: EvalGetMulti, emit: Emit[ClientIn]): Unit =
Expand Down Expand Up @@ -130,4 +131,6 @@ final class EvalCacheApi(mongo: Mongo)(using
private object EvalCacheValidator:

def apply(in: EvalCacheEntry.Input): Either[ErrorStr, Unit] =
in.eval.pvs.traverse_(pv => chess.Replay.boardsFromUci(pv.moves.value.toList, in.fen.some, in.situation.variant))
in.eval.pvs.traverse_(pv =>
chess.Replay.boardsFromUci(pv.moves.value.toList, in.fen.some, in.situation.variant)
)
2 changes: 1 addition & 1 deletion src/main/scala/evalCache/EvalCacheBsonHandlers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ object EvalCacheBsonHandlers:
def readTry(bson: BSONValue) =
bson match
case v: BSONBinary => Success(BinaryFen(v.byteArray))
case _ => handlerBadType(bson)
case _ => handlerBadType(bson)
def writeTry(v: BinaryFen) = Success(BSONBinary(v.value, Subtype.GenericBinarySubtype))
given BSONHandler[Id] = Macros.handler

Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/evalCache/EvalCacheEntry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ object EvalCacheEntry:
case class Input(id: Id, fen: Fen.Full, situation: Situation, eval: Eval)

def makeInput(variant: Variant, fen: Fen.Full, eval: Eval) =
Fen.read(variant, fen)
Fen
.read(variant, fen)
.filter(_.playable(false))
.ifTrue(eval.looksValid)
.map: situation =>
Expand Down
20 changes: 8 additions & 12 deletions src/main/scala/evalCache/EvalCacheMulti.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ final private class EvalCacheMulti(using
scheduler: org.apache.pekko.actor.typed.Scheduler
):
import EvalCacheMulti.*
import EvalCacheUpgrade.{ EvalState, SetupId, SriString }
import EvalCacheUpgrade.{ EvalState, SriString }

private val members = ConcurrentHashMap[SriString, WatchingMember](4096)
private val evals = ConcurrentHashMap[SetupId, EvalState](1024)
private val evals = ConcurrentHashMap[EvalCacheEntry.Id, EvalState](1024)
private val expirableSris = ExpireCallbackMemo[Sri](scheduler, 1 minute, expire)

private val upgradeMon = Monitor.evalCache.multi.upgrade
Expand All @@ -36,15 +36,14 @@ final private class EvalCacheMulti(using
WatchingMember(sri, e.variant, e.fens)
)
.setups
.foreach: setupId =>
evals.compute(setupId, (_, prev) => Option(prev).fold(EvalState(Set(sri), Depth(0)))(_.addSri(sri)))
.foreach: id =>
evals.compute(id, (_, prev) => Option(prev).fold(EvalState(Set(sri), Depth(0)))(_.addSri(sri)))
expirableSris.put(sri)

def onEval(input: EvalCacheEntry.Input, fromSri: Sri): Unit =
val setupId = makeSetupId(input.situation.variant, input.fen)
Option(
evals.computeIfPresent(
setupId,
input.id,
(_, ev) =>
if ev.depth >= input.eval.depth then ev
else ev.copy(depth = input.eval.depth)
Expand All @@ -63,9 +62,9 @@ final private class EvalCacheMulti(using
Option(members.remove(sri.value)).foreach:
_.setups.foreach(unregisterEval(_, sri))

private def unregisterEval(setupId: SetupId, sri: Sri): Unit =
private def unregisterEval(id: EvalCacheEntry.Id, sri: Sri): Unit =
evals.computeIfPresent(
setupId,
id,
(_, eval) =>
val newSris = eval.sris - sri
if newSris.isEmpty then null
Expand All @@ -81,8 +80,5 @@ private object EvalCacheMulti:

import EvalCacheUpgrade.*

def makeSetupId(variant: Variant, fen: Fen.Full): SetupId =
s"${variant.id}${SmallFen.make(variant, fen.simple)}"

case class WatchingMember(sri: Sri, variant: Variant, fens: List[Fen.Full]):
def setups: List[SetupId] = fens.map(makeSetupId(variant, _))
def setups: List[EvalCacheEntry.Id] = fens.flatMap(EvalCacheEntry.Id.from(variant, _))
35 changes: 18 additions & 17 deletions src/main/scala/evalCache/EvalCacheUpgrade.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package lila.ws
package evalCache

import chess.format.{ Fen, UciPath }
import chess.variant.Variant
import chess.format.UciPath
import play.api.libs.json.JsString

import java.util.concurrent.ConcurrentHashMap
Expand All @@ -28,20 +27,24 @@ final private class EvalCacheUpgrade(using
private val upgradeMon = Monitor.evalCache.single.upgrade

def register(sri: Sri, e: EvalGet): Unit =
members.compute(
sri.value,
(_, prev) =>
Option(prev).foreach: member =>
unregisterEval(member.setupId, sri)
val setupId = makeSetupId(e.variant, e.fen, e.multiPv)
evals.compute(setupId, (_, eval) => Option(eval).fold(EvalState(Set(sri), Depth(0)))(_.addSri(sri)))
WatchingMember(sri, setupId, e.path)
)
expirableSris.put(sri)
EvalCacheEntry.Id
.from(e.variant, e.fen)
.foreach: entryId =>
members.compute(
sri.value,
(_, prev) =>
Option(prev).foreach: member =>
unregisterEval(member.setupId, sri)
val setupId = SetupId(entryId, e.multiPv)
evals
.compute(setupId, (_, eval) => Option(eval).fold(EvalState(Set(sri), Depth(0)))(_.addSri(sri)))
WatchingMember(sri, setupId, e.path)
)
expirableSris.put(sri)

def onEval(input: EvalCacheEntry.Input, fromSri: Sri): Unit =
(1 to input.eval.multiPv.value).foreach: multiPv =>
val setupId = makeSetupId(input.situation.variant, input.fen, MultiPv(multiPv))
val setupId = SetupId(input.id, MultiPv(multiPv))
Option(
evals.computeIfPresent(
setupId,
Expand Down Expand Up @@ -82,12 +85,10 @@ final private class EvalCacheUpgrade(using
private object EvalCacheUpgrade:

type SriString = String
type SetupId = String

case class SetupId(entryId: EvalCacheEntry.Id, multiPv: MultiPv)

case class EvalState(sris: Set[Sri], depth: Depth):
def addSri(sri: Sri) = copy(sris = sris + sri)

def makeSetupId(variant: Variant, fen: Fen.Full, multiPv: MultiPv): SetupId =
s"${variant.id}${SmallFen.make(variant, fen.simple)}^$multiPv"

case class WatchingMember(sri: Sri, setupId: SetupId, path: UciPath)
15 changes: 1 addition & 14 deletions src/main/scala/evalCache/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ package lila.ws
package evalCache

import cats.data.NonEmptyList
import chess.format.{ Fen, Uci }
import chess.variant.Variant
import chess.format.Uci

val MIN_KNODES = Knodes(3000)
val MIN_DEPTH = Depth(20)
Expand All @@ -26,15 +25,3 @@ object Moves extends TotalWrapper[Moves, NonEmptyList[Uci]]:
opaque type Trust = Double
object Trust extends OpaqueDouble[Trust]:
extension (a: Trust) def isEnough = a > -1

opaque type SmallFen = String
object SmallFen extends OpaqueString[SmallFen]:
def make(variant: Variant, fen: Fen.Simple): SmallFen =
val base = fen.value.split(' ').take(4).mkString("").filter { c =>
c != '/' && c != '-' && c != 'w'
}
if variant == chess.variant.ThreeCheck
then fen.value.split(' ').lift(6).foldLeft(base)(_ + _)
else base
def validate(variant: Variant, fen: Fen.Full): Option[SmallFen] =
Fen.read(variant, fen).exists(_.playable(false)).option(make(variant, fen.simple))

0 comments on commit 4ebf67a

Please sign in to comment.