Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 104 additions & 10 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,40 @@ open Fake.DotNetCli
open Fake.DocFxHelper

// Information about the project for Nuget and Assembly info files
let product = "Akka.Streams.Kafka"
let product = "Helios.DedicatedThreadPool"
let configuration = "Release"

// Metadata used when signing packages and DLLs
let signingName = "Akka.Streams.Kafka"
let signingDescription = "Apache Kafka adapter for Akka.NET Streams"
let signingUrl = "https://github.com/akkadotnet/Akka.Streams.Kafka"
let signingName = "Helios.DedicatedThreadPool"
let signingDescription = "Stand-alone .NET Threadpool"
let signingUrl = "https://github.com/helios-io/DedicatedThreadPool"

// Read release notes and version
let codeDirectory = __SOURCE_DIRECTORY__ @@ "src"
let solutionFile = FindFirstMatchingFile "*.sln" codeDirectory // dynamically look up the solution
let buildNumber = environVarOrDefault "BUILD_NUMBER" "0"
let hasTeamCity = (not (buildNumber = "0")) // check if we have the TeamCity environment variable for build # set
let preReleaseVersionSuffix = "beta" + (if (not (buildNumber = "0")) then (buildNumber) else DateTime.UtcNow.Ticks.ToString())
let versionSuffix =
match (getBuildParam "nugetprerelease") with
| "dev" -> preReleaseVersionSuffix
| "" -> ""
| str -> str

let releaseNotes =
File.ReadLines (__SOURCE_DIRECTORY__ @@ "RELEASE_NOTES.md")
|> ReleaseNotesHelper.parseReleaseNotes

let dockerTagVersion =
match versionSuffix with
| "" -> releaseNotes.AssemblyVersion
| str -> releaseNotes.AssemblyVersion + "-" + versionSuffix

let versionFromReleaseNotes =
match releaseNotes.SemVer.PreRelease with
| Some r -> r.Origin
| None -> ""

let versionSuffix =
match (getBuildParam "nugetprerelease") with
| "dev" -> preReleaseVersionSuffix
| "" -> versionFromReleaseNotes
| str -> str

// Directories
let toolsDir = __SOURCE_DIRECTORY__ @@ "tools"
let output = __SOURCE_DIRECTORY__ @@ "bin"
Expand Down Expand Up @@ -252,6 +256,92 @@ Target "PublishNuget" (fun _ ->
projects |> Seq.iter (runSingleProject)
)

//--------------------------------------------------------------------------------
// Docker images
//--------------------------------------------------------------------------------
let GetDockerProjects =
let dockerFiles = !! "src/**/Dockerfile" // folders with Dockerfiles in it

let projects = dockerFiles
|> Seq.map (fun dFile -> Path.GetDirectoryName(dFile))
|> Seq.map (fun folder -> !! (folder + "/*.csproj"))
|> Seq.concat

projects

Target "PublishCode" (fun _ ->
ActivateFinalTarget "KillCreatedProcesses"
let projects = GetDockerProjects

let runSingleProject project =
DotNetCli.Publish
(fun p ->
{ p with
Project = project
Configuration = configuration
})

projects|> Seq.iter (runSingleProject)
)

let mapDockerImageName (projectName:string) =
match projectName with
| str -> Some(str.ToLowerInvariant())

Target "BuildDockerImages" (fun _ ->
let projects = GetDockerProjects

let remoteRegistryUrl = getBuildParamOrDefault "remoteRegistry" ""

let composedGetFileNameWithoutExtension (p:string) =
System.IO.Path.GetFileNameWithoutExtension p

let buildDockerImage imageName projectPath =

let args =
if(hasBuildParam "remoteRegistry") then
StringBuilder()
|> append "build"
|> append "-t"
|> append (imageName + ":" + dockerTagVersion)
|> append "-t"
|> append (imageName + ":latest")
|> append "-t"
|> append (remoteRegistryUrl + "/" + imageName + ":" + dockerTagVersion)
|> append "-t"
|> append (remoteRegistryUrl + "/" + imageName + ":latest")
|> append "."
|> toText
else
StringBuilder()
|> append "build"
|> append "-t"
|> append (imageName + ":" + dockerTagVersion)
|> append "-t"
|> append (imageName + ":latest")
|> append "."
|> toText

let composedGetDirName (p:string) =
System.IO.Path.GetDirectoryName p


ExecProcess(fun info ->
info.FileName <- "docker"
info.WorkingDirectory <- composedGetDirName projectPath
info.Arguments <- args) (System.TimeSpan.FromMinutes 5.0) (* Reasonably long-running task. *)

let runSingleProject project =
let projectName = composedGetFileNameWithoutExtension project
let imageName = mapDockerImageName projectName
let result = match imageName with
| None -> 0
| Some(name) -> buildDockerImage name project
if result <> 0 then failwithf "docker build failed. %s" project

projects |> Seq.iter (runSingleProject)
)

//--------------------------------------------------------------------------------
// Documentation
//--------------------------------------------------------------------------------
Expand Down Expand Up @@ -308,6 +398,7 @@ Target "Help" <| fun _ ->

Target "BuildRelease" DoNothing
Target "All" DoNothing
Target "Docker" DoNothing
Target "Nuget" DoNothing

// build dependencies
Expand All @@ -323,6 +414,9 @@ Target "Nuget" DoNothing
// docs
"Clean" ==> "RestorePackages" ==> "BuildRelease" ==> "Docfx"

// Docker
"BuildRelease" ==> "PublishCode" ==> "BuildDockerImages" ==> "Docker"

// all
"BuildRelease" ==> "All"
"RunTests" ==> "All"
Expand Down
25 changes: 25 additions & 0 deletions src/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
27 changes: 22 additions & 5 deletions src/Helios.DedicatedThreadPool.sln
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
# Visual Studio Version 16
VisualStudioVersion = 16.0.30717.126
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Helios.DedicatedThreadPool", "core\Helios.DedicatedThreadPool\Helios.DedicatedThreadPool.csproj", "{6C8F359E-E479-44D5-8FA0-02BFD38C3860}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Helios.DedicatedThreadPool", "core\Helios.DedicatedThreadPool\Helios.DedicatedThreadPool.csproj", "{6C8F359E-E479-44D5-8FA0-02BFD38C3860}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Helios.DedicatedThreadPool.Tests", "tests\Helios.DedicatedThreadPool.Tests\Helios.DedicatedThreadPool.Tests.csproj", "{BD7B3C66-14D8-4F01-AECE-F7F3F440A899}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Helios.DedicatedThreadPool.Tests", "tests\Helios.DedicatedThreadPool.Tests\Helios.DedicatedThreadPool.Tests.csproj", "{BD7B3C66-14D8-4F01-AECE-F7F3F440A899}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{741F51D5-FB48-4AE3-837E-3C32FAC6584E}"
EndProject
Expand All @@ -23,7 +23,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{39EF5B
.nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Helios.DedicatedThreadPool.Tests.Performance", "tests\Helios.DedicatedThreadPool.Tests.Performance\Helios.DedicatedThreadPool.Tests.Performance.csproj", "{428DF580-1734-4AB6-B80E-F5ABABCE61D6}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Helios.DedicatedThreadPool.Tests.Performance", "tests\Helios.DedicatedThreadPool.Tests.Performance\Helios.DedicatedThreadPool.Tests.Performance.csproj", "{428DF580-1734-4AB6-B80E-F5ABABCE61D6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Helios.DedicatedThreadPool.IdleCpu.Program", "tests\Helios.DedicatedThreadPool.IdleCpu.Program\Helios.DedicatedThreadPool.IdleCpu.Program.csproj", "{876973A9-060F-402E-9434-733F8320AA6B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Helios.DedicatedThreadPool.IdleCpu.Tests", "tests\Helios.DedicatedThreadPool.IdleCpu.Tests\Helios.DedicatedThreadPool.IdleCpu.Tests.csproj", "{F0A0B730-337D-4FE2-AA41-54535CF70726}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -43,6 +47,14 @@ Global
{428DF580-1734-4AB6-B80E-F5ABABCE61D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{428DF580-1734-4AB6-B80E-F5ABABCE61D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{428DF580-1734-4AB6-B80E-F5ABABCE61D6}.Release|Any CPU.Build.0 = Release|Any CPU
{876973A9-060F-402E-9434-733F8320AA6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{876973A9-060F-402E-9434-733F8320AA6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{876973A9-060F-402E-9434-733F8320AA6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{876973A9-060F-402E-9434-733F8320AA6B}.Release|Any CPU.Build.0 = Release|Any CPU
{F0A0B730-337D-4FE2-AA41-54535CF70726}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0A0B730-337D-4FE2-AA41-54535CF70726}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0A0B730-337D-4FE2-AA41-54535CF70726}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F0A0B730-337D-4FE2-AA41-54535CF70726}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -51,5 +63,10 @@ Global
{6C8F359E-E479-44D5-8FA0-02BFD38C3860} = {E86B275F-E912-47C5-8F5E-BA62D5959EBD}
{BD7B3C66-14D8-4F01-AECE-F7F3F440A899} = {741F51D5-FB48-4AE3-837E-3C32FAC6584E}
{428DF580-1734-4AB6-B80E-F5ABABCE61D6} = {741F51D5-FB48-4AE3-837E-3C32FAC6584E}
{876973A9-060F-402E-9434-733F8320AA6B} = {741F51D5-FB48-4AE3-837E-3C32FAC6584E}
{F0A0B730-337D-4FE2-AA41-54535CF70726} = {741F51D5-FB48-4AE3-837E-3C32FAC6584E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DD52A4C9-1308-4946-82E0-9AD4884CAA85}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -304,18 +304,18 @@ public void Dispose()
/// <summary>
/// TBD
/// </summary>
public void WaitForThreadsExit()
public async Task WaitForThreadsExit()
{
WaitForThreadsExit(Timeout.InfiniteTimeSpan);
await WaitForThreadsExit(Timeout.InfiniteTimeSpan);
}

/// <summary>
/// TBD
/// </summary>
/// <param name="timeout">TBD</param>
public void WaitForThreadsExit(TimeSpan timeout)
public async Task WaitForThreadsExit(TimeSpan timeout)
{
Task.WaitAll(_workers.Select(worker => worker.ThreadExit).ToArray(), timeout);
await Task.WhenAll(_workers.Select(worker => worker.ThreadExit));
}

#region Pool worker implementation
Expand Down
3 changes: 1 addition & 2 deletions src/core/Helios.DedicatedThreadPool/_Visibility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@

[assembly: InternalsVisibleTo("Helios.DedicatedThreadPool.Tests")]
[assembly: InternalsVisibleTo("Helios.DedicatedThreadPool.Tests.Performance")]
[assembly: InternalsVisibleTo("Helios.DedicatedThreadPool.VsThreadpoolBenchmark")]
[assembly: InternalsVisibleTo("Helios.DedicatedThreadPool.VsDedicatedThreadFiber")]
[assembly: InternalsVisibleTo("Helios.DedicatedThreadPool.IdleCpu.Program")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim AS base
WORKDIR /app

COPY ./bin/Release/netcoreapp3.1/publish /app

ENTRYPOINT ["dotnet", "Helios.DedicatedThreadPool.IdleCpu.Program.dll"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerfileContext>..\..</DockerfileContext>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.9" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\core\Helios.DedicatedThreadPool\Helios.DedicatedThreadPool.csproj" />
</ItemGroup>
</Project>
77 changes: 77 additions & 0 deletions src/tests/Helios.DedicatedThreadPool.IdleCpu.Program/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Helios.Concurrency;

namespace Helios.DedicatedThreadPool.IdleCpu.Program
{
/// <summary>
/// Create random numbers with Thread-specific seeds.
///
/// Borrowed form Jon Skeet's brilliant C# in Depth: http://csharpindepth.com/Articles/Chapter12/Random.aspx
/// </summary>
public static class ThreadLocalRandom
{
private static int _seed = Environment.TickCount;

private static ThreadLocal<Random> _rng = new ThreadLocal<Random>(() => new Random(Interlocked.Increment(ref _seed)));

/// <summary>
/// The current random number seed available to this thread
/// </summary>
public static Random Current
{
get
{
return _rng.Value;
}
}
}

class Program
{
static async Task Main(string[] args)
{
// set a huge number of threads per core to exaggerate idle CPU effects when we pre-allocate
var maxThreads = Math.Max(4, Environment.ProcessorCount)*100;

Console.WriteLine("Starting Idle Cpu Test with Following Configuration");
Console.WriteLine("MaxThreads: {0}", maxThreads);

var settings = new DedicatedThreadPoolSettings(maxThreads);
var threadPool = new Concurrency.DedicatedThreadPool(settings);
var concurrentBag = new ConcurrentBag<int>();

void DoWork(int count)
{
Console.WriteLine("Count: {0}", count);
Thread.Sleep(100);
concurrentBag.Add(Thread.CurrentThread.ManagedThreadId);
if (count % 3 == 0)
threadPool.QueueUserWorkItem(() => DoWork(ThreadLocalRandom.Current.Next(0,7)));
}



foreach (var i in Enumerable.Range(0, maxThreads*100))
{
threadPool.QueueUserWorkItem(() =>
{
DoWork(i);
});
}

threadPool.QueueUserWorkItem(() =>
{
Console.WriteLine("Found {0} active threads", concurrentBag.ToArray().Distinct().Count());
});

// force background Helios threads to run
await Task.Delay(TimeSpan.FromMinutes(3));

Console.WriteLine("Exited with {0} active threads", concurrentBag.ToArray().Distinct().Count());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"profiles": {
"Helios.DedicatedThreadPool.IdleCpu.Program": {
"commandName": "Project"
},
"Docker": {
"commandName": "Docker"
}
}
}
Loading