Reduce sbt memory utilization

The sbt Server is initialized with a callback onIncomingSocket. That
callback was created in CommandExchange and held references to a build
structure and a state. Neither the state nor structure would ever go out
of scope so they effectively leaked. It is possible for each
NetworkChannel to access a recent instance of state through the
CommandExchange.withState method. Using this, we can eliminate the
references to state and build structure in the onIncomingSocket
callback. In the sbt project, this reduced the memory utilization by
about 50mb on startup.
This commit is contained in:
Ethan Atkins 2020-08-23 16:58:05 -07:00
parent 8fe7e33a31
commit 1c21f13b99
2 changed files with 11 additions and 13 deletions

View File

@ -195,13 +195,10 @@ private[sbt] final class CommandExchange {
new NetworkChannel(
name,
socket,
Project structure s,
auth,
instance,
handlers,
s.log,
mkAskUser(name),
Option(lastState.get),
)
subscribe(channel)
}

View File

@ -54,13 +54,10 @@ import sbt.internal.util.ProgressState
final class NetworkChannel(
val name: String,
connection: Socket,
protected val structure: BuildStructure,
auth: Set[ServerAuthentication],
instance: ServerInstance,
handlers: Seq[ServerHandler],
val log: Logger,
mkUIThreadImpl: (State, CommandChannel) => UITask,
state: Option[State],
) extends CommandChannel { self =>
def this(
name: String,
@ -74,15 +71,14 @@ final class NetworkChannel(
this(
name,
connection,
structure,
auth,
instance,
handlers,
log,
new UITask.AskUserTask(_, _),
None
)
def log: Logger = StandardMain.exchange.withState(_.log)
private val running = new AtomicBoolean(true)
private val delimiter: Byte = '\n'.toByte
private val out = connection.getOutputStream
@ -411,9 +407,12 @@ final class NetworkChannel(
protected def onSettingQuery(execId: Option[String], req: SettingQuery) = {
if (initialized) {
import sbt.protocol.codec.JsonProtocol._
SettingQuery.handleSettingQueryEither(req, structure) match {
case Right(x) => respondResult(x, execId)
case Left(s) => respondError(ErrorCodes.InvalidParams, s, execId)
StandardMain.exchange.withState { s =>
val structure = Project.extract(s).structure
SettingQuery.handleSettingQueryEither(req, structure) match {
case Right(x) => respondResult(x, execId)
case Left(s) => respondError(ErrorCodes.InvalidParams, s, execId)
}
}
} else {
log.warn(s"ignoring query $req before initialization")
@ -792,7 +791,9 @@ final class NetworkChannel(
private[this] val blockedThreads = ConcurrentHashMap.newKeySet[Thread]
override private[sbt] val progressState: ProgressState = new ProgressState(
1,
state.flatMap(_.get(Keys.superShellMaxTasks.key)).getOrElse(SysProp.supershellMaxTasks)
StandardMain.exchange
.withState(_.get(Keys.superShellMaxTasks.key))
.getOrElse(SysProp.supershellMaxTasks)
)
override def getWidth: Int = getProperty(_.width, 0).getOrElse(0)
override def getHeight: Int = getProperty(_.height, 0).getOrElse(0)