Skip to content

Commit 02ffadd

Browse files
committed
Pull out ActionThrottler into class and fix delay bug.
1 parent 5cfbec4 commit 02ffadd

File tree

2 files changed

+65
-23
lines changed

2 files changed

+65
-23
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading;
10+
using System.Threading.Tasks;
11+
12+
namespace Microsoft.ML.AutoML
13+
{
14+
internal class ActionThrottler
15+
{
16+
private readonly Action _action;
17+
private readonly TimeSpan _minDelay;
18+
19+
private DateTime _nextUpdateTime = DateTime.MinValue;
20+
private int _updatePending = 0;
21+
22+
/// <summary>
23+
/// This constructor initializes an ActionThrottler that ensures <paramref name="action"/> runs no more than once per <paramref name="minDelay"/>.
24+
/// </summary>
25+
/// <param name="action">The action to thorttle.</param>
26+
/// <param name="minDelay">Timespan to indicate the minimum delay between each time action is executed.</param>
27+
public ActionThrottler(Action action, TimeSpan minDelay)
28+
{
29+
_minDelay = minDelay;
30+
_action = action;
31+
}
32+
33+
34+
public async Task ExecuteAsync()
35+
{
36+
if (Interlocked.CompareExchange(ref _updatePending, 1, 0) == 0) // _updatePending is int initialized with 0
37+
{
38+
DateTime currentTime = DateTime.UtcNow;
39+
40+
if (_nextUpdateTime > currentTime)
41+
{
42+
await Task.Delay(_nextUpdateTime - currentTime);
43+
}
44+
_action();
45+
_nextUpdateTime = DateTime.UtcNow + _minDelay;
46+
_updatePending = 0;
47+
}
48+
}
49+
}
50+
}

src/Microsoft.ML.AutoML.Interactive/NotebookMonitor.cs

+15-23
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ namespace Microsoft.ML.AutoML
1414
{
1515
public class NotebookMonitor : IMonitor
1616
{
17+
private readonly ActionThrottler _updateThrottler;
1718
private DisplayedValue _valueToUpdate;
18-
private DateTime _lastUpdate = DateTime.MinValue;
1919

2020
public TrialResult BestTrial { get; set; }
2121
public TrialResult MostRecentTrial { get; set; }
@@ -27,12 +27,14 @@ public NotebookMonitor()
2727
{
2828
CompletedTrials = new List<TrialResult>();
2929
TrialData = new DataFrame(new PrimitiveDataFrameColumn<int>("Trial"), new PrimitiveDataFrameColumn<float>("Metric"), new StringDataFrameColumn("Trainer"), new StringDataFrameColumn("Parameters"));
30+
_updateThrottler = new ActionThrottler(Update, TimeSpan.FromSeconds(5));
3031
}
3132

3233
public void ReportBestTrial(TrialResult result)
3334
{
3435
BestTrial = result;
35-
Update();
36+
37+
ThrottledUpdate();
3638
}
3739

3840
public void ReportCompletedTrial(TrialResult result)
@@ -49,46 +51,36 @@ public void ReportCompletedTrial(TrialResult result)
4951
new KeyValuePair<string, object>("Trainer",result.TrialSettings.Pipeline.ToString().Replace("Unknown=>","")),
5052
new KeyValuePair<string, object>("Parameters",activeRunParam),
5153
}, true);
52-
Update();
54+
55+
ThrottledUpdate();
5356
}
5457

5558
public void ReportFailTrial(TrialResult result)
5659
{
5760
// TODO figure out what to do with failed trials.
58-
Update();
61+
ThrottledUpdate();
5962
}
6063

6164
public void ReportRunningTrial(TrialSettings setting)
6265
{
6366
ActiveTrial = setting;
64-
Update();
67+
ThrottledUpdate();
6568
}
6669

67-
private int _updatePending = 0;
68-
public void Update()
70+
private void ThrottledUpdate()
6971
{
70-
Task.Run(async () =>
71-
{
72-
if (Interlocked.CompareExchange(ref _updatePending, 1, 0) == 0) // _updatePending is int initialized with 0
73-
{
74-
DateTime n = DateTime.UtcNow;
75-
if (n - _lastUpdate < TimeSpan.FromSeconds(5))
76-
{
77-
await Task.Delay(n - _lastUpdate);
78-
}
79-
80-
_valueToUpdate.Update(this);
81-
_lastUpdate = n;
82-
_updatePending = 0;
83-
}
84-
});
72+
Task.Run(async () => await _updateThrottler.ExecuteAsync());
73+
}
8574

75+
public void Update()
76+
{
77+
_valueToUpdate.Update(this);
8678
}
8779

8880
public void SetUpdate(DisplayedValue valueToUpdate)
8981
{
9082
_valueToUpdate = valueToUpdate;
91-
Update();
83+
ThrottledUpdate();
9284
}
9385
}
9486
}

0 commit comments

Comments
 (0)