diff --git a/SchedulingPractice.SubWorkerRunner/Program.cs b/SchedulingPractice.SubWorkerRunner/Program.cs index ea5924b..0207645 100644 --- a/SchedulingPractice.SubWorkerRunner/Program.cs +++ b/SchedulingPractice.SubWorkerRunner/Program.cs @@ -50,7 +50,9 @@ static void Main(string[] args) }); } else if (mode == "acetaxxxx") services.AddHostedService(); + else if (mode == "jackie82422") services.AddHostedService(); else { throw new ArgumentOutOfRangeException($"Mode: {mode} not is not valid."); } + }) .Build(); diff --git a/SchedulingPractice.SubWorkerRunner/SchedulingPractice.SubWorkerRunner.csproj b/SchedulingPractice.SubWorkerRunner/SchedulingPractice.SubWorkerRunner.csproj index dfad027..cd1c302 100644 --- a/SchedulingPractice.SubWorkerRunner/SchedulingPractice.SubWorkerRunner.csproj +++ b/SchedulingPractice.SubWorkerRunner/SchedulingPractice.SubWorkerRunner.csproj @@ -14,6 +14,7 @@ + diff --git a/SchedulingPractice.sln b/SchedulingPractice.sln index 10fa63e..6ec9239 100644 --- a/SchedulingPractice.sln +++ b/SchedulingPractice.sln @@ -36,6 +36,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SubWorker.AndyDemo", "SubWo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SchedulingPractice.SubWorkerRunner", "SchedulingPractice.SubWorkerRunner\SchedulingPractice.SubWorkerRunner.csproj", "{5D349423-56A0-4E03-A59F-7D1AF95B78E7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SubWorker.ChachaDemo", "SubWorker.ChachaDemo\SubWorker.ChachaDemo.csproj", "{67ECD76F-8410-436C-AF45-B783EDB7D59E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -86,6 +88,10 @@ Global {5D349423-56A0-4E03-A59F-7D1AF95B78E7}.Debug|Any CPU.Build.0 = Debug|Any CPU {5D349423-56A0-4E03-A59F-7D1AF95B78E7}.Release|Any CPU.ActiveCfg = Release|Any CPU {5D349423-56A0-4E03-A59F-7D1AF95B78E7}.Release|Any CPU.Build.0 = Release|Any CPU + {67ECD76F-8410-436C-AF45-B783EDB7D59E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {67ECD76F-8410-436C-AF45-B783EDB7D59E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {67ECD76F-8410-436C-AF45-B783EDB7D59E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {67ECD76F-8410-436C-AF45-B783EDB7D59E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -99,6 +105,7 @@ Global {7D80EF21-E6C8-46EC-8179-67D328B15335} = {5A225F28-B864-4306-B0C7-83D9CBDABF5B} {32F4B1E1-4A5B-4695-9BCD-1A76F8566420} = {5A225F28-B864-4306-B0C7-83D9CBDABF5B} {29711E67-24F9-4736-AAC8-BBE6831A4DEF} = {5A225F28-B864-4306-B0C7-83D9CBDABF5B} + {67ECD76F-8410-436C-AF45-B783EDB7D59E} = {5A225F28-B864-4306-B0C7-83D9CBDABF5B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {43B102A2-F68E-4926-9EAA-6763FDDEF0B4} diff --git a/SubWorker.ChachaDemo/ChachaSubWorkerBackgroundService.cs b/SubWorker.ChachaDemo/ChachaSubWorkerBackgroundService.cs new file mode 100644 index 0000000..5164bf7 --- /dev/null +++ b/SubWorker.ChachaDemo/ChachaSubWorkerBackgroundService.cs @@ -0,0 +1,78 @@ +using System; +using System.Linq; +using System.Threading; +using System.Threading.Channels; +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using SchedulingPractice.Core; + +namespace SubWorker.ChachaDemo +{ + public class ChachaSubWorkerBackgroundService : BackgroundService + { + private readonly int _channelCount = Environment.ProcessorCount; + private readonly Channel[] _channels; + + public ChachaSubWorkerBackgroundService() { + _channels = new Channel[_channelCount]; + for (var i = 0; i < _channelCount; i++) { + _channels[i] = Channel.CreateUnbounded(); + } + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) { + await Task.Delay(1, stoppingToken); + try { + var getJobs = Task.Run(async () => { await GetJobs(stoppingToken); }, stoppingToken); + Parallel.For((long)0, _channels.Length, new ParallelOptions() { + MaxDegreeOfParallelism = Environment.ProcessorCount, + CancellationToken = stoppingToken + }, async i => { + while (!stoppingToken.IsCancellationRequested) { + try { + var item = await _channels[i].Reader.ReadAsync(stoppingToken); + await ProcessJob(item, stoppingToken); + } + catch { + Console.WriteLine($"channel #{i} exit."); + } + } + }); + await Task.WhenAny(getJobs, Task.Delay(Timeout.Infinite, stoppingToken)); + } + catch { + Console.WriteLine("Application shut down."); + } + } + + private async Task GetJobs(CancellationToken cts) { + using var jobRepo = new JobsRepo(); + while (!cts.IsCancellationRequested) { + var jobs = jobRepo.GetReadyJobs(JobSettings.MinPrepareTime).ToList(); + for (var i = 0; i < jobs.Count; i++) { + var index = i % _channelCount; + await _channels[index].Writer.WriteAsync(jobs[i], cts); + } + + await Task.Delay(JobSettings.MinPrepareTime, cts); + } + } + + private async Task ProcessJob(JobInfo jobInfo, CancellationToken cts) { + using var jobsRepo = new JobsRepo(); + var now = DateTime.Now; + if (jobInfo.RunAt > now) + try { + await Task.Delay(jobInfo.RunAt.Subtract(now), cts); + } + catch { + Console.WriteLine($"X - Leave unlock job. job id {jobInfo.Id}"); + } + + if (jobsRepo.GetJob(jobInfo.Id).State != 0) return; + if (jobsRepo.AcquireJobLock(jobInfo.Id)) + jobsRepo.ProcessLockedJob(jobInfo.Id); + Console.WriteLine("O"); + } + } +} \ No newline at end of file diff --git a/SubWorker.ChachaDemo/Program.cs b/SubWorker.ChachaDemo/Program.cs new file mode 100644 index 0000000..4df1773 --- /dev/null +++ b/SubWorker.ChachaDemo/Program.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.DependencyInjection; + + +namespace SubWorker.ChachaDemo +{ + class Program + { + static void Main(string[] args) + { + var host = new HostBuilder() + .ConfigureServices((context, services) => + { + //services.AddHostedService(); + services.AddHostedService(); + }) + .Build(); + using (host) + { + host.Start(); + host.WaitForShutdown(); + } + } + } +} \ No newline at end of file diff --git a/SubWorker.ChachaDemo/README.md b/SubWorker.ChachaDemo/README.md new file mode 100644 index 0000000..c1425d8 --- /dev/null +++ b/SubWorker.ChachaDemo/README.md @@ -0,0 +1,192 @@ +## Version 1.0 + +Without early lock. + +Environment : + +| Item | Configuration | +|----------|----------------------| +| OS | Windows 11 Pro | +| CPU | AMD Ryzen 3700X | +| RAM | ADATA DDR4 3200 32GB | +| Storage | ADATA 1TB M.2 | +| Database | LocalDB | +| Runtime | Net 6 | + +### One Instance + +``` +Jobs Scheduling Metrics: + +--(action count)---------------------------------------------- +- CREATE: 1736 +- ACQUIRE_SUCCESS: 1736 +- ACQUIRE_FAILURE: 0 +- COMPLETE: 1736 +- QUERYJOB: 1737 +- QUERYLIST: 65 + +--(state count)---------------------------------------------- +- COUNT(CREATE): 0 +- COUNT(LOCK): 0 +- COUNT(COMPLETE): 1736 + +--(statistics)---------------------------------------------- +- DELAY(Average): 113 +- DELAY(Stdev): 31.2237044096519 + +--(test result)---------------------------------------------- +- Complete Job: True, 1736 / 1736 +- Delay Too Long: 0 +- Fail Job: True, 0 + +--(benchmark score)---------------------------------------------- +- Exec Cost Score: 8237 (querylist x 100 + acquire-failure x 10 + queryjob x 1) +- Efficient Score: 144.22 (average + stdev) + +``` + +### Three Instance + +```Jobs Scheduling Metrics: + +--(action count)---------------------------------------------- +- CREATE: 1758 +- ACQUIRE_SUCCESS: 1758 +- ACQUIRE_FAILURE: 2445 +- COMPLETE: 1758 +- QUERYJOB: 5275 +- QUERYLIST: 195 + +--(state count)---------------------------------------------- +- COUNT(CREATE): 0 +- COUNT(LOCK): 0 +- COUNT(COMPLETE): 1758 + +--(statistics)---------------------------------------------- +- DELAY(Average): 101 +- DELAY(Stdev): 6.79669291539491 + +--(test result)---------------------------------------------- +- Complete Job: True, 1758 / 1758 +- Delay Too Long: 0 +- Fail Job: True, 0 + +--(benchmark score)---------------------------------------------- +- Exec Cost Score: 49225 (querylist x 100 + acquire-failure x 10 + queryjob x 1) +- Efficient Score: 107.8 (average + stdev) + +Process finished with exit code 0. +``` +Environment : + +| Item | Configuration | +|----------|----------------------| +| OS | Windows 11 Pro | +| CPU | AMD Ryzen 3700X | +| RAM | ADATA DDR4 3200 32GB | +| Storage | ADATA 1TB M.2 | +| Database | LocalDB | +| Runtime | Net Core 2.2 | + +### One Instance + +``` +Jobs Scheduling Metrics: + +--(action count)---------------------------------------------- +- CREATE: 1749 +- ACQUIRE_SUCCESS: 1749 +- ACQUIRE_FAILURE: 1 +- COMPLETE: 1749 +- QUERYJOB: 1754 +- QUERYLIST: 65 + +--(state count)---------------------------------------------- +- COUNT(CREATE): 0 +- COUNT(LOCK): 0 +- COUNT(COMPLETE): 1749 + +--(statistics)---------------------------------------------- +- DELAY(Average): 113 +- DELAY(Stdev): 30.7915205815142 + +--(test result)---------------------------------------------- +- Complete Job: True, 1749 / 1749 +- Delay Too Long: 0 +- Fail Job: True, 0 + +--(benchmark score)---------------------------------------------- +- Exec Cost Score: 8264 (querylist x 100 + acquire-failure x 10 + queryjob x 1) +- Efficient Score: 143.79 (average + stdev) + +Process finished with exit code 0. +``` + +### Three Instance + +``` +Jobs Scheduling Metrics: + +--(action count)---------------------------------------------- +- CREATE: 1736 +- ACQUIRE_SUCCESS: 1736 +- ACQUIRE_FAILURE: 2767 +- COMPLETE: 1736 +- QUERYJOB: 5209 +- QUERYLIST: 195 + +--(state count)---------------------------------------------- +- COUNT(CREATE): 0 +- COUNT(LOCK): 0 +- COUNT(COMPLETE): 1736 + +--(statistics)---------------------------------------------- +- DELAY(Average): 101 +- DELAY(Stdev): 8.04448627812101 + +--(test result)---------------------------------------------- +- Complete Job: True, 1736 / 1736 +- Delay Too Long: 0 +- Fail Job: True, 0 + +--(benchmark score)---------------------------------------------- +- Exec Cost Score: 52379 (querylist x 100 + acquire-failure x 10 + queryjob x 1) +- Efficient Score: 109.04 (average + stdev) + +Process finished with exit code 0. +``` + +### Five Instances +``` +Jobs Scheduling Metrics: + +--(action count)---------------------------------------------- +- CREATE: 1740 +- ACQUIRE_SUCCESS: 1740 +- ACQUIRE_FAILURE: 5264 +- COMPLETE: 1740 +- QUERYJOB: 8699 +- QUERYLIST: 323 + +--(state count)---------------------------------------------- +- COUNT(CREATE): 0 +- COUNT(LOCK): 0 +- COUNT(COMPLETE): 1740 + +--(statistics)---------------------------------------------- +- DELAY(Average): 102 +- DELAY(Stdev): 8.63974181166169 + +--(test result)---------------------------------------------- +- Complete Job: True, 1740 / 1740 +- Delay Too Long: 0 +- Fail Job: True, 0 + +--(benchmark score)---------------------------------------------- +- Exec Cost Score: 93639 (querylist x 100 + acquire-failure x 10 + queryjob x 1) +- Efficient Score: 110.64 (average + stdev) + +Process finished with exit code 0. + +``` diff --git a/SubWorker.ChachaDemo/SubWorker.ChachaDemo.csproj b/SubWorker.ChachaDemo/SubWorker.ChachaDemo.csproj new file mode 100644 index 0000000..47f19cb --- /dev/null +++ b/SubWorker.ChachaDemo/SubWorker.ChachaDemo.csproj @@ -0,0 +1,18 @@ + + + + Exe + netcoreapp2.2 + latest + + + + + + + + + + + +