Skip to content
This repository has been archived by the owner on Aug 5, 2024. It is now read-only.

Commit

Permalink
[feature] create BEP connection on demands instead of keeping it as a…
Browse files Browse the repository at this point in the history
… service (#356)

Create BEP connection on demands instead of keeping it as a service

- Background
Significantly reduces memory footprint of the application, because the
never-cleaned BepServer instance was holding a `BepOutputBuilder bepOutputBuilder`
field which in turn was holding all BEP messages that has been received since the
prevous build.

So the reason for this change is:
1. There's no point of having a socket handle and other sources laying in memory,
   in particular because it's easy to make a mistake of keeping too much data.
2. BepServer setup is cheap
3. It will be easier to provide different peb handlers for different calls.

- Memory footprint comparison
The heap size in of this app in idle, for a project containing 2000 targets, is reduced from
more than ~2GB to ~0.5GB.

Bazel BSP 2.5.1 (idle, after 2000k targets import)
```
$ jcmd 11429 GC.heap_info
11429:
 garbage-first heap   total 5382144K, used 3219933K [0x0000000673800000, 0x0000000800000000)
  region size 4096K, 40 young (163840K), 39 survivors (159744K)
 Metaspace       used 45658K, committed 46016K, reserved 1097728K
  class space    used 5045K, committed 5248K, reserved 1048576K
$ jcmd 11429 GC.run
11429:
Command executed successfully
$ jcmd 11429 GC.heap_info
11429:
 garbage-first heap   total 5382144K, used 2161982K [0x0000000673800000, 0x0000000800000000)
  region size 4096K, 0 young (0K), 0 survivors (0K)
 Metaspace       used 45658K, committed 46016K, reserved 1097728K
  class space    used 5045K, committed 5248K, reserved 1048576K

```

Bazel BSP now:
```
$ jcmd 9381 GC.heap_info
9381:
 garbage-first heap   total 4001792K, used 2190915K [0x0000000673800000, 0x0000000800000000)
  region size 4096K, 48 young (196608K), 47 survivors (192512K)
 Metaspace       used 46417K, committed 46784K, reserved 1097728K
  class space    used 5114K, committed 5312K, reserved 1048576K
$ jcmd 9381 GC.run
9381:
Command executed successfully
$ jcmd 9381 GC.heap_info
9381:
 garbage-first heap   total 1900544K, used 556282K [0x0000000673800000, 0x0000000800000000)
  region size 4096K, 0 young (0K), 0 survivors (0K)
 Metaspace       used 46417K, committed 46784K, reserved 1097728K
  class space    used 5114K, committed 5312K, reserved 1048576K

```
  • Loading branch information
tpasternak authored Mar 13, 2023
1 parent dd33bc2 commit 4252736
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 28 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

- Project view file flag for disabling trace log.
| [#344](https://github.com/JetBrains/bazel-bsp/pull/344)
- Create BEP connection on demands instead of keeping it as a service (reduces memory footprint)
| [#356](https://github.com/JetBrains/bazel-bsp/pull/356)

## [2.5.1] - 08.02.2023

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
package org.jetbrains.bsp.bazel.server

import ch.epfl.scala.bsp4j.BuildClient
import io.grpc.ServerBuilder
import org.eclipse.lsp4j.jsonrpc.Launcher
import org.jetbrains.bsp.bazel.bazelrunner.BazelRunner
import org.jetbrains.bsp.bazel.logger.BspClientLogger
import org.jetbrains.bsp.bazel.logger.BspClientTestNotifier
import org.jetbrains.bsp.bazel.server.bep.BepServer
import org.jetbrains.bsp.bazel.server.bsp.*
import org.jetbrains.bsp.bazel.server.bsp.info.BspInfo
import org.jetbrains.bsp.bazel.server.bsp.managers.BazelBspCompilationManager
import org.jetbrains.bsp.bazel.server.common.ServerContainer
import org.jetbrains.bsp.bazel.server.diagnostics.DiagnosticsService
import org.jetbrains.bsp.bazel.server.sync.BspProjectMapper
import org.jetbrains.bsp.bazel.server.sync.ExecuteService
import org.jetbrains.bsp.bazel.server.sync.ProjectSyncService
Expand Down Expand Up @@ -72,9 +69,8 @@ class BazelBspServer(
val client = launcher.remoteProxy
bspClientLogger.initialize(client)
bspClientTestNotifier.initialize(client)
val bepServer = BepServer(client, DiagnosticsService(workspaceRoot))
compilationManager.setBepServer(bepServer)
bspIntegrationData.server = ServerBuilder.forPort(0).addService(bepServer).build()
compilationManager.setClient(client)
compilationManager.setWorkspaceRoot(workspaceRoot)
}

private fun createLauncher(bspIntegrationData: BspIntegrationData): Launcher.Builder<BuildClient> {
Expand All @@ -89,8 +85,4 @@ class BazelBspServer(

return builder
}

fun setBesBackendPort(port: Int) {
bazelRunner.setBesBackendPort(port)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@ object ServerInitializer {
)
val bspServer = BazelBspServer(bspInfo, workspaceContextProvider, Path(cliArgs.bazelWorkspaceRoot))
bspServer.startServer(bspIntegrationData)
val server = bspIntegrationData.server.start()
bspServer.setBesBackendPort(server.port)
bspIntegrationData.launcher.startListening()
server.awaitTermination()
bspIntegrationData.launcher.startListening().get()
} catch (e: Exception) {
e.printStackTrace(System.err)
hasErrors = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ private void initializeClient(ServerContainer serverContainer, BloopBuildClient
var bepServer =
new BepServer(
client, new DiagnosticsService(serverContainer.getBazelInfo().getWorkspaceRoot()));
serverContainer.getCompilationManager().setBepServer(bepServer);

var grpcServer = ServerBuilder.forPort(0).addService(bepServer).build();
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@ data class BspIntegrationData(
val traceWriter: PrintWriter?,
) {
lateinit var launcher: Launcher<BuildClient>
lateinit var server: Server
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ java_library(
"//executioncontext/workspacecontext",
"//server/src/main/java/org/jetbrains/bsp/bazel/server/bep",
"//server/src/main/java/org/jetbrains/bsp/bazel/server/bsp/utils",
"//server/src/main/java/org/jetbrains/bsp/bazel/server/diagnostics",
"@io_bazel//third_party/grpc:grpc-jar_checked_in",
"@maven//:org_eclipse_lsp4j_org_eclipse_lsp4j_jsonrpc",
],
)
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
package org.jetbrains.bsp.bazel.server.bsp.managers;

import ch.epfl.scala.bsp4j.BuildClient;
import io.grpc.ServerBuilder;
import io.vavr.collection.List;
import io.vavr.collection.Seq;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.jetbrains.bsp.bazel.bazelrunner.BazelRunner;
import org.jetbrains.bsp.bazel.server.bep.BepServer;
import org.jetbrains.bsp.bazel.server.diagnostics.DiagnosticsService;
import org.jetbrains.bsp.bazel.workspacecontext.TargetsSpec;

import java.io.IOException;
import java.nio.file.Path;

public class BazelBspCompilationManager {

private final BazelRunner bazelRunner;
private BepServer bepServer;
private BuildClient client;
private Path workspaceRoot;

public BazelBspCompilationManager(BazelRunner bazelRunner) {
this.bazelRunner = bazelRunner;
Expand All @@ -23,18 +30,34 @@ public BepBuildResult buildTargetsWithBep(CancelChecker cancelChecker, TargetsSp
public BepBuildResult buildTargetsWithBep(
CancelChecker cancelChecker,
TargetsSpec targetSpecs, Seq<String> extraFlags, String originId) {
var result =
bazelRunner
.commandBuilder()
.build()
.withFlags(extraFlags.asJava())
.withTargets(targetSpecs)
.executeBazelBesCommand(originId)
.waitAndGetResult(cancelChecker, false);
return new BepBuildResult(result, bepServer.getBepOutput());
var bepServer = new BepServer(client, new DiagnosticsService(workspaceRoot));
var server = ServerBuilder.forPort(0).addService(bepServer).build();
try {
server.start();
} catch (IOException e) {
throw new RuntimeException(e);
}
bazelRunner.setBesBackendPort(server.getPort());
try {
var result =
bazelRunner
.commandBuilder()
.build()
.withFlags(extraFlags.asJava())
.withTargets(targetSpecs)
.executeBazelBesCommand(originId)
.waitAndGetResult(cancelChecker, true);
return new BepBuildResult(result, bepServer.getBepOutput());
} finally {
server.shutdown();
}
}

public void setClient(BuildClient client) {
this.client = client;
}

public void setBepServer(BepServer bepServer) {
this.bepServer = bepServer;
public void setWorkspaceRoot(Path workspaceRoot) {
this.workspaceRoot = workspaceRoot;
}
}

0 comments on commit 4252736

Please sign in to comment.