From 031bd1a73a6bbb1e9703bcfb96f706f9f3560cc7 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 16 Jun 2016 13:07:23 +0200 Subject: [PATCH] compiler.shared.event.group --- .../compiler/server/BuildManager.java | 29 +++++++++++++++---- .../src/org/jetbrains/io/SubServer.java | 4 +-- .../src/org/jetbrains/io/BuiltInServer.java | 18 +++++------- .../org/jetbrains/io/ChannelRegistrar.java | 11 ++++--- .../intellij/testFramework/ThreadTracker.java | 1 + .../util/resources/misc/registry.properties | 2 ++ 6 files changed, 43 insertions(+), 22 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index 67f9a73663a0..de76d32e054f 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -36,6 +36,7 @@ import com.intellij.execution.process.ProcessHandler; import com.intellij.ide.DataManager; import com.intellij.ide.PowerSaveMode; import com.intellij.ide.file.BatchFileChangeListener; +import com.intellij.idea.StartupUtil; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.application.Application; @@ -90,7 +91,9 @@ import gnu.trove.THashSet; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.oio.OioEventLoopGroup; import io.netty.handler.codec.protobuf.ProtobufDecoder; import io.netty.handler.codec.protobuf.ProtobufEncoder; import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder; @@ -98,6 +101,7 @@ import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; import io.netty.util.internal.ThreadLocalRandom; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.io.BuiltInServer; import org.jetbrains.io.ChannelRegistrar; import org.jetbrains.io.NettyKt; import org.jetbrains.jps.api.*; @@ -160,7 +164,7 @@ public class BuildManager implements Disposable { private final ExecutorService myRequestsProcessor = SequentialTaskExecutor.createSequentialApplicationPoolExecutor(); private final Map myProjectDataMap = Collections.synchronizedMap(new HashMap()); - private final BuildManagerPeriodicTask myAutoMakeTask = new BuildManagerPeriodicTask() { + private final BuildManagerPeriodicTask myAutoMakeTask = new BuildManagerPeriodicTask(this) { @Override protected int getDelay() { return Registry.intValue("compiler.automake.trigger.delay"); @@ -172,7 +176,7 @@ public class BuildManager implements Disposable { } }; - private final BuildManagerPeriodicTask myDocumentSaveTask = new BuildManagerPeriodicTask() { + private final BuildManagerPeriodicTask myDocumentSaveTask = new BuildManagerPeriodicTask(this) { @Override protected int getDelay() { return Registry.intValue("compiler.document.save.trigger.delay"); @@ -1293,11 +1297,20 @@ public class BuildManager implements Disposable { @NotNull private Future stopListening() { myListenPort = -1; - return myChannelRegistrar.close(true); + return myChannelRegistrar.close(); } private int startListening() throws Exception { - final ServerBootstrap bootstrap = NettyKt.serverBootstrap(new NioEventLoopGroup(1, ConcurrencyUtil.newNamedThreadFactory("External compiler"))); + EventLoopGroup group; + BuiltInServer mainServer = StartupUtil.getServer(); + boolean isOwnEventLoopGroup = !Registry.is("compiler.shared.event.group", false) || mainServer == null || mainServer.getEventLoopGroup() instanceof OioEventLoopGroup; + if (isOwnEventLoopGroup) { + group = new NioEventLoopGroup(1, ConcurrencyUtil.newNamedThreadFactory("External compiler")); + } + else { + group = mainServer.getEventLoopGroup(); + } + final ServerBootstrap bootstrap = NettyKt.serverBootstrap(group); bootstrap.childHandler(new ChannelInitializer() { @Override protected void initChannel(@NotNull Channel channel) throws Exception { @@ -1310,7 +1323,7 @@ public class BuildManager implements Disposable { } }); Channel serverChannel = bootstrap.bind(InetAddress.getLoopbackAddress(), 0).syncUninterruptibly().channel(); - myChannelRegistrar.add(serverChannel); + myChannelRegistrar.add(serverChannel, isOwnEventLoopGroup); return ((InetSocketAddress)serverChannel.localAddress()).getPort(); } @@ -1337,7 +1350,7 @@ public class BuildManager implements Disposable { } private abstract static class BuildManagerPeriodicTask implements Runnable { - private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD); + private final Alarm myAlarm; private final AtomicBoolean myInProgress = new AtomicBoolean(false); private final Runnable myTaskRunnable = () -> { try { @@ -1348,6 +1361,10 @@ public class BuildManager implements Disposable { } }; + protected BuildManagerPeriodicTask(@NotNull Disposable disposable) { + myAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, disposable); + } + public final void schedule() { cancelPendingExecution(); final int delay = Math.max(100, getDelay()); diff --git a/platform/built-in-server/src/org/jetbrains/io/SubServer.java b/platform/built-in-server/src/org/jetbrains/io/SubServer.java index 67a52d832d21..62aab4d2fec3 100644 --- a/platform/built-in-server/src/org/jetbrains/io/SubServer.java +++ b/platform/built-in-server/src/org/jetbrains/io/SubServer.java @@ -76,7 +76,7 @@ public final class SubServer implements CustomPortServerManager.CustomPortServic try { bootstrap.localAddress(user.isAvailableExternally() ? new InetSocketAddress(port) : NetKt.loopbackSocketAddress(port)); - channelRegistrar.add(bootstrap.bind().syncUninterruptibly().channel()); + channelRegistrar.add(bootstrap.bind().syncUninterruptibly().channel(), false); return true; } catch (Exception e) { @@ -97,7 +97,7 @@ public final class SubServer implements CustomPortServerManager.CustomPortServic private void stop() { if (channelRegistrar != null) { - channelRegistrar.close(false); + channelRegistrar.close(); } } diff --git a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java index 7f5bf8f055bc..d432bcd9088e 100644 --- a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java +++ b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java @@ -41,7 +41,6 @@ public class BuiltInServer implements Disposable { private final EventLoopGroup eventLoopGroup; private final int port; private final ChannelRegistrar channelRegistrar; - private final boolean isOwnerOfEventLoopGroup; static { // IDEA-120811 @@ -54,12 +53,10 @@ public class BuiltInServer implements Disposable { private BuiltInServer(@NotNull EventLoopGroup eventLoopGroup, int port, - @NotNull ChannelRegistrar channelRegistrar, - boolean isOwnerOfEventLoopGroup) { + @NotNull ChannelRegistrar channelRegistrar) { this.eventLoopGroup = eventLoopGroup; this.port = port; this.channelRegistrar = channelRegistrar; - this.isOwnerOfEventLoopGroup = isOwnerOfEventLoopGroup; } @NotNull @@ -77,7 +74,7 @@ public class BuiltInServer implements Disposable { @Override public void dispose() { - channelRegistrar.close(isOwnerOfEventLoopGroup); + channelRegistrar.close(); Logger.getInstance(BuiltInServer.class).info("web server stopped"); } @@ -118,8 +115,8 @@ public class BuiltInServer implements Disposable { ChannelRegistrar channelRegistrar = new ChannelRegistrar(); ServerBootstrap bootstrap = NettyKt.serverBootstrap(eventLoopGroup); configureChildHandler(bootstrap, channelRegistrar, handler); - int port = bind(firstPort, portsCount, tryAnyPort, bootstrap, channelRegistrar); - return new BuiltInServer(eventLoopGroup, port, channelRegistrar, isEventLoopGroupOwner); + int port = bind(firstPort, portsCount, tryAnyPort, bootstrap, channelRegistrar, isEventLoopGroupOwner); + return new BuiltInServer(eventLoopGroup, port, channelRegistrar); } static void configureChildHandler(@NotNull ServerBootstrap bootstrap, @@ -138,7 +135,8 @@ public class BuiltInServer implements Disposable { int portsCount, boolean tryAnyPort, @NotNull ServerBootstrap bootstrap, - @NotNull ChannelRegistrar channelRegistrar) throws Exception { + @NotNull ChannelRegistrar channelRegistrar, + boolean isEventLoopGroupOwner) throws Exception { InetAddress address = InetAddress.getLoopbackAddress(); for (int i = 0; i < portsCount; i++) { @@ -150,7 +148,7 @@ public class BuiltInServer implements Disposable { ChannelFuture future = bootstrap.bind(address, port).awaitUninterruptibly(); if (future.isSuccess()) { - channelRegistrar.add(future.channel()); + channelRegistrar.add(future.channel(), isEventLoopGroupOwner); return port; } else if (!tryAnyPort && i == portsCount - 1) { @@ -161,7 +159,7 @@ public class BuiltInServer implements Disposable { Logger.getInstance(BuiltInServer.class).info("We cannot bind to our default range, so, try to bind to any free port"); ChannelFuture future = bootstrap.bind(address, 0).awaitUninterruptibly(); if (future.isSuccess()) { - channelRegistrar.add(future.channel()); + channelRegistrar.add(future.channel(), isEventLoopGroupOwner); return ((InetSocketAddress)future.channel().localAddress()).getPort(); } ExceptionUtil.rethrowAll(future.cause()); diff --git a/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java index 7af34eed8df3..e0698341d4dc 100644 --- a/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java +++ b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java @@ -32,12 +32,14 @@ public final class ChannelRegistrar extends ChannelInboundHandlerAdapter { private static final Logger LOG = Logger.getInstance(ChannelRegistrar.class); private final ChannelGroup openChannels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); + private boolean isEventLoopGroupOwner; public boolean isEmpty() { return openChannels.isEmpty(); } - public void add(@NotNull Channel serverChannel) { + public void add(@NotNull Channel serverChannel, boolean isOwnEventLoopGroup) { + this.isEventLoopGroupOwner = isOwnEventLoopGroup; assert serverChannel instanceof ServerChannel; openChannels.add(serverChannel); } @@ -50,12 +52,13 @@ public final class ChannelRegistrar extends ChannelInboundHandlerAdapter { super.channelActive(context); } - public void close() { - close(true); + @NotNull + public Future close() { + return close(isEventLoopGroupOwner); } @NotNull - public Future close(boolean shutdownEventLoopGroup) { + private Future close(boolean shutdownEventLoopGroup) { EventLoopGroup eventLoopGroup = null; if (shutdownEventLoopGroup) { for (Channel channel : openChannels) { diff --git a/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java b/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java index 5ed6d1a04b94..a22bab6b4e57 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java +++ b/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java @@ -82,6 +82,7 @@ public class ThreadTracker { wellKnownOffenders.add("main"); wellKnownOffenders.add("Monitor Ctrl-Break"); wellKnownOffenders.add("Netty "); + wellKnownOffenders.add("External compiler"); wellKnownOffenders.add("Reference Handler"); wellKnownOffenders.add("RMI TCP Connection"); wellKnownOffenders.add("Signal Dispatcher"); diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 462bff4781d1..0c74a455cf0b 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -255,6 +255,8 @@ compiler.document.save.trigger.delay.description=Delay in milliseconds before tr compiler.build.data.unused.threshold=30 compiler.build.data.unused.threshold.description=If project is not opened for the specified number of days, its build data will be cleared to save disk space +compiler.shared.event.group=false + vcs.annotations.preload=false vcs.showConsole=true vcs.log.bek.sort.disabled=false