diff --git a/src/tye/Program.RunCommand.cs b/src/tye/Program.RunCommand.cs index 3fde790e..b4413362 100644 --- a/src/tye/Program.RunCommand.cs +++ b/src/tye/Program.RunCommand.cs @@ -2,11 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.CommandLine; using System.CommandLine.Invocation; using System.IO; -using Tye.Hosting; +using System.Threading; using Tye.ConfigModel; +using Tye.Hosting; namespace Tye { @@ -62,11 +64,30 @@ namespace Tye } var application = ConfigFactory.FromFile(path); + var serviceCount = application.Services.Count; + + InitializeThreadPoolSettings(serviceCount); + var host = new TyeHost(application.ToHostingApplication(), args); return host.RunAsync(); }); return command; } + + private static void InitializeThreadPoolSettings(int serviceCount) + { + ThreadPool.GetMinThreads(out var workerThreads, out var completionPortThreads); + + // We need to bump up the min threads to something reasonable so that the dashboard doesn't take forever + // to serve requests. All console IO is blocking in .NET so capturing stdoutput and stderror results in blocking thread pool threads. + // The thread pool handles bursts poorly and HTTP requests end up getting stuck behind spinning up docker containers and processes. + + // Bumping the min threads doesn't mean we'll have min threads to start, it just means don't add a threads very slowly up to + // min threads + ThreadPool.SetMinThreads(Math.Max(workerThreads, serviceCount * 4), completionPortThreads); + + // We use serviceCount * 4 because we currently launch multiple processes per service, this gives the dashboard some breathing room + } } }