From b0f2aa70fa83f5107308ea5491dba4698ac189a3 Mon Sep 17 00:00:00 2001 From: Aimeast Date: Sun, 13 Dec 2015 22:10:00 +0800 Subject: [PATCH] improve scheduler and git cache --- GitCandy/Git/Cache/GitCacheAccessor.cs | 29 +++++++++++++------------- GitCandy/GitCandy.csproj | 1 + GitCandy/Schedules/IJob.cs | 2 +- GitCandy/Schedules/JobType.cs | 8 +++++++ GitCandy/Schedules/LogJob.cs | 6 +++--- GitCandy/Schedules/Runner.cs | 26 +++++++++-------------- GitCandy/Schedules/Scheduler.cs | 28 +++++++++++-------------- GitCandy/Schedules/SingleJob.cs | 16 +++++++------- 8 files changed, 58 insertions(+), 58 deletions(-) create mode 100644 GitCandy/Schedules/JobType.cs diff --git a/GitCandy/Git/Cache/GitCacheAccessor.cs b/GitCandy/Git/Cache/GitCacheAccessor.cs index 33520bb..c56ecc1 100644 --- a/GitCandy/Git/Cache/GitCacheAccessor.cs +++ b/GitCandy/Git/Cache/GitCacheAccessor.cs @@ -98,7 +98,7 @@ public static void Initialize() Logger.Info("Delete cache directory {0}", dir); Directory.Delete(dir, true); } - }, 60)); + }, JobType.LongRunning)); enabled = true; } @@ -126,7 +126,7 @@ public static void Delete(string project) Directory.Delete(path, true); } - }, 60)); + }, JobType.LongRunning)); } protected void RemoveFromRunningPool() @@ -143,7 +143,7 @@ protected virtual void LoadOrCalculate() { var loaded = enabled && Load(); task = loaded - ? Task.Run(() => { }) + ? new Task(() => { }) : new Task(() => { try @@ -164,16 +164,17 @@ protected virtual void LoadOrCalculate() RemoveFromRunningPool(); }); - if (!loaded) + if (loaded) { - if (IsAsync) - { - Scheduler.Instance.AddJob(new SingleJob(task)); - } - else - { - task.Start(); - } + task.Start(); + } + else if (IsAsync) + { + Scheduler.Instance.AddJob(new SingleJob(task)); + } + else + { + task.Start(); } } @@ -200,12 +201,12 @@ protected virtual void LoadOrCalculate() public override bool Equals(object obj) { - return base.Equals(obj); + throw new NotImplementedException("Must override this method"); } public override int GetHashCode() { - return base.GetHashCode(); + throw new NotImplementedException("Must override this method"); } } diff --git a/GitCandy/GitCandy.csproj b/GitCandy/GitCandy.csproj index 3b5b030..d24fe28 100644 --- a/GitCandy/GitCandy.csproj +++ b/GitCandy/GitCandy.csproj @@ -382,6 +382,7 @@ + diff --git a/GitCandy/Schedules/IJob.cs b/GitCandy/Schedules/IJob.cs index 190d7c3..79686e1 100644 --- a/GitCandy/Schedules/IJob.cs +++ b/GitCandy/Schedules/IJob.cs @@ -6,6 +6,6 @@ public interface IJob { void Execute(JobContext jobContext); TimeSpan GetNextInterval(JobContext jobContext); - TimeSpan Due { get; } + JobType JobType { get; } } } \ No newline at end of file diff --git a/GitCandy/Schedules/JobType.cs b/GitCandy/Schedules/JobType.cs new file mode 100644 index 0000000..67a8254 --- /dev/null +++ b/GitCandy/Schedules/JobType.cs @@ -0,0 +1,8 @@ +namespace GitCandy.Schedules +{ + public enum JobType + { + RealTime, + LongRunning, + } +} diff --git a/GitCandy/Schedules/LogJob.cs b/GitCandy/Schedules/LogJob.cs index 04fa78c..139f862 100644 --- a/GitCandy/Schedules/LogJob.cs +++ b/GitCandy/Schedules/LogJob.cs @@ -7,7 +7,7 @@ public class LogJob : IJob { public void Execute(JobContext jobContext) { - if (jobContext.ExecutionTimes != 0) + if (jobContext.ExecutionTimes > 1) Logger.SetLogPath(); } @@ -16,9 +16,9 @@ public TimeSpan GetNextInterval(JobContext jobContext) return TimeSpan.FromSeconds(24 * 3600) - DateTime.Now.TimeOfDay; } - public TimeSpan Due + public JobType JobType { - get { return TimeSpan.FromSeconds(1.0); } + get { return JobType.RealTime; } } } } \ No newline at end of file diff --git a/GitCandy/Schedules/Runner.cs b/GitCandy/Schedules/Runner.cs index a81de25..316804b 100644 --- a/GitCandy/Schedules/Runner.cs +++ b/GitCandy/Schedules/Runner.cs @@ -7,7 +7,7 @@ namespace GitCandy.Schedules { internal sealed class Runner { - private readonly static int IntervalOfTask = Environment.ProcessorCount * 1000; + private readonly static int IntervalOfTask = 100; private readonly object _syncRoot = new object(); private readonly Scheduler _scheduler; @@ -17,10 +17,10 @@ internal sealed class Runner private CancellationTokenSource _tokenSource; private Task _task; - public Runner(Scheduler scheduler, RunnerType runnerType) + public Runner(Scheduler scheduler, JobType jobType) { _scheduler = scheduler; - RunnerType = runnerType; + JobType = jobType; ID = Interlocked.Increment(ref _id); } @@ -39,7 +39,8 @@ public void Start() } public int ID { get; private set; } - public RunnerType RunnerType { get; private set; } + public JobType JobType { get; private set; } + public DateTime LastExecution { get; private set; } public void Stop() { @@ -64,7 +65,7 @@ private void RunnerLoop() if (_tokenSource.IsCancellationRequested) break; - var context = _scheduler.GetNextJobContext(RunnerType); + var context = _scheduler.GetNextJobContext(JobType); if (context != null) { var jobName = context.Job.GetType().FullName; @@ -73,6 +74,8 @@ private void RunnerLoop() try { var utcStart = DateTime.UtcNow; + LastExecution = utcStart; + context.UtcStart = utcStart; context.OnExecuting(this, context); @@ -95,21 +98,12 @@ private void RunnerLoop() } context.Scheduler.JobExecuted(context); } - - if (_tokenSource.IsCancellationRequested) - break; - - Task.Delay(IntervalOfTask).Wait(); + else + Task.Delay(IntervalOfTask).Wait(); } _tokenSource = null; Logger.Info("Exit schedule runner #{0} loop", ID); } } - - internal enum RunnerType - { - RealTime, - LongRunning, - } } \ No newline at end of file diff --git a/GitCandy/Schedules/Scheduler.cs b/GitCandy/Schedules/Scheduler.cs index a9abe6d..1a7fcf0 100644 --- a/GitCandy/Schedules/Scheduler.cs +++ b/GitCandy/Schedules/Scheduler.cs @@ -6,13 +6,11 @@ namespace GitCandy.Schedules { public sealed class Scheduler { - const double RealTimeDuration = 3.0; - private readonly static Scheduler _instance = new Scheduler(); private readonly object _syncRoot = new object(); - private readonly LinkedList _jobs = new LinkedList(); - private readonly Runner[] _runners; + internal readonly LinkedList _jobs = new LinkedList(); + internal readonly Runner[] _runners; public static Scheduler Instance { get { return _instance; } } @@ -22,7 +20,7 @@ public Scheduler() var div = Math.Min(_runners.Length / 4, 3); for (int i = 0; i < _runners.Length; i++) { - _runners[i] = new Runner(this, i < div ? RunnerType.RealTime : RunnerType.LongRunning); + _runners[i] = new Runner(this, i < div ? JobType.RealTime : JobType.LongRunning); } } @@ -40,7 +38,7 @@ public void StartAll() for (int i = 0; i < _runners.Length; i++) { _runners[i].Start(); - Logger.Info("Schedule runner #{0} {1} started", _runners[i].ID, _runners[i].RunnerType); + Logger.Info("Schedule runner #{0} {1} started", _runners[i].ID, _runners[i].JobType); } } @@ -80,8 +78,7 @@ private void InsertJobContext(JobContext context) var node = _jobs.First; while (node != null) { - if ((node.Previous == null || context.UtcNextExecution <= context.UtcNextExecution) - && context.UtcNextExecution < node.Value.UtcNextExecution) + if (context.UtcNextExecution < node.Value.UtcNextExecution) { _jobs.AddBefore(node, context); break; @@ -93,21 +90,20 @@ private void InsertJobContext(JobContext context) } } - internal JobContext GetNextJobContext(RunnerType runnerType) + internal JobContext GetNextJobContext(JobType jobType) { lock (_syncRoot) { + var utcNow = DateTime.UtcNow; var node = _jobs.First; - while (node != null) + + while (node != null && utcNow >= node.Value.UtcNextExecution) { - var context = node.Value; - var due = context.Job.Due.Seconds; - if (DateTime.UtcNow >= context.UtcNextExecution - && (runnerType == RunnerType.RealTime && due < RealTimeDuration - || runnerType == RunnerType.LongRunning)) + if (jobType == JobType.RealTime && node.Value.Job.JobType == JobType.RealTime + || jobType == JobType.LongRunning) { _jobs.Remove(node); - return context; + return node.Value; } node = node.Next; diff --git a/GitCandy/Schedules/SingleJob.cs b/GitCandy/Schedules/SingleJob.cs index 3310c61..ff8d429 100644 --- a/GitCandy/Schedules/SingleJob.cs +++ b/GitCandy/Schedules/SingleJob.cs @@ -8,27 +8,27 @@ namespace GitCandy.Schedules public class SingleJob : IJob { private Task _task; - private double _secondDue; + private JobType _jobType; [ImportingConstructor] public SingleJob() - : this(() => { }, 1.0) + : this(() => { }, JobType.RealTime) { } - public SingleJob(Action action, double secondDue = 4.0) + public SingleJob(Action action, JobType jobType = JobType.LongRunning) { Contract.Requires(action != null); _task = new Task(action); - _secondDue = secondDue; + _jobType = jobType; } - public SingleJob(Task task, double secondDue = 4.0) + public SingleJob(Task task, JobType jobType = JobType.LongRunning) { Contract.Requires(task != null); _task = task; - _secondDue = secondDue; + _jobType = jobType; } public void Execute(JobContext jobContext) @@ -42,9 +42,9 @@ public TimeSpan GetNextInterval(JobContext jobContext) return TimeSpan.MaxValue; } - public TimeSpan Due + public JobType JobType { - get { return TimeSpan.FromSeconds(_secondDue); } + get { return _jobType; } } } } \ No newline at end of file