Skip to content

Commit 946d53e

Browse files
committed
Sane progress
2 parents 43f4b02 + c1abe6d commit 946d53e

File tree

6 files changed

+45
-24
lines changed

6 files changed

+45
-24
lines changed

module/PSParallel.psd1

0 Bytes
Binary file not shown.

src/PSParallel/InvokeParallelCommand.cs

+3-5
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ public override void EndProcessing()
286286
_progressManager.TotalCount = _input.Count;
287287
foreach (var i in _input)
288288
{
289-
var processed = Pool.ProcessedCount + Pool.GetPartiallyProcessedCount();
289+
var processed = Pool.GetEstimatedProgressCount();
290290
_progressManager.UpdateCurrentProgressRecord($"Starting processing of {i}", processed);
291291
WriteProgress(_progressManager.ProgressRecord);
292292
while (!Pool.TryAddInput(ScriptBlock, i))
@@ -298,7 +298,7 @@ public override void EndProcessing()
298298
while (!Pool.WaitForAllPowershellCompleted(100))
299299
{
300300

301-
_progressManager.UpdateCurrentProgressRecord("All work queued. Waiting for remaining work to complete.", Pool.ProcessedCount);
301+
_progressManager.UpdateCurrentProgressRecord("All work queued. Waiting for remaining work to complete.", Pool.GetEstimatedProgressCount());
302302
WriteProgress(_progressManager.ProgressRecord);
303303

304304
if (Stopping)
@@ -322,11 +322,9 @@ public override void WriteProgress(Collection<ProgressRecord> progress)
322322
p.ParentActivityId = _progressManager.ActivityId;
323323
WriteProgress(p);
324324
}
325-
_progressManager.UpdateCurrentProgressRecord(Pool.ProcessedCount + Pool.GetPartiallyProcessedCount());
325+
_progressManager.UpdateCurrentProgressRecord(Pool.GetEstimatedProgressCount());
326326
WriteProgress(_progressManager.ProgressRecord);
327327
}
328328
}
329-
330-
331329
}
332330
}

src/PSParallel/PowerShellPoolMember.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ class PowerShellPoolMember : IDisposable
1515
private readonly PSDataCollection<PSObject> m_input =new PSDataCollection<PSObject>();
1616
private PSDataCollection<PSObject> m_output;
1717
private int m_percentComplete;
18-
public int PercentComplete => m_percentComplete;
19-
18+
public int PercentComplete
19+
{
20+
get { return m_percentComplete; }
21+
set { m_percentComplete = value; }
22+
}
23+
2024

2125
public PowerShellPoolMember(PowershellPool pool, int index)
2226
{

src/PSParallel/PowershellPool.cs

+22-12
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,27 @@
33
using System.Collections.Generic;
44
using System.Diagnostics;
55
using System.Diagnostics.Contracts;
6-
using System.Linq;
76
using System.Management.Automation;
87
using System.Management.Automation.Runspaces;
98
using System.Threading;
109

10+
1111
namespace PSParallel
1212
{
1313
sealed class PowershellPool : IDisposable
1414
{
15+
private readonly object _countLock = new object();
1516
private int _busyCount;
16-
private int _processedCount;
1717
private readonly CancellationToken _cancellationToken;
1818
private readonly RunspacePool _runspacePool;
1919
private readonly List<PowerShellPoolMember> _poolMembers;
2020
private readonly BlockingCollection<PowerShellPoolMember> _availablePoolMembers = new BlockingCollection<PowerShellPoolMember>(new ConcurrentQueue<PowerShellPoolMember>());
2121
public readonly PowerShellPoolStreams Streams = new PowerShellPoolStreams();
22-
23-
public int ProcessedCount => _processedCount;
22+
private int _processedCount;
2423

2524
public PowershellPool(int poolSize, InitialSessionState initialSessionState, CancellationToken cancellationToken)
2625
{
2726
_poolMembers= new List<PowerShellPoolMember>(poolSize);
28-
_processedCount = 0;
2927
_cancellationToken = cancellationToken;
3028

3129
for (var i = 0; i < poolSize; i++)
@@ -39,7 +37,7 @@ public PowershellPool(int poolSize, InitialSessionState initialSessionState, Can
3937
_runspacePool.SetMaxRunspaces(poolSize);
4038
}
4139

42-
public int GetPartiallyProcessedCount()
40+
private int GetPartiallyProcessedCount()
4341
{
4442
var totalPercentComplete = 0;
4543
var count = _poolMembers.Count;
@@ -55,16 +53,24 @@ public int GetPartiallyProcessedCount()
5553
percentComplete = 100;
5654
}
5755
totalPercentComplete += percentComplete;
58-
}
59-
return totalPercentComplete / 100;
56+
}
57+
var partiallyProcessedCount = totalPercentComplete / 100;
58+
return partiallyProcessedCount;
59+
}
60+
61+
public int GetEstimatedProgressCount()
62+
{
63+
lock(_countLock) {
64+
return _processedCount + GetPartiallyProcessedCount();
65+
}
6066
}
6167

6268
public bool TryAddInput(ScriptBlock scriptblock,PSObject inputObject)
6369
{
6470
PowerShellPoolMember poolMember;
6571
if(!TryWaitForAvailablePowershell(100, out poolMember))
6672
{
67-
return false;
73+
return false;
6874
}
6975

7076
Interlocked.Increment(ref _busyCount);
@@ -110,7 +116,6 @@ private bool TryWaitForAvailablePowershell(int milliseconds, out PowerShellPoolM
110116
}
111117

112118
poolMember.PowerShell.RunspacePool = _runspacePool;
113-
Debug.WriteLine($"WaitForAvailablePowershell - Busy: {_busyCount} _processed {_processedCount}, member = {poolMember.Index}");
114119
return true;
115120
}
116121

@@ -125,13 +130,18 @@ public void Dispose()
125130
public void ReportAvailable(PowerShellPoolMember poolmember)
126131
{
127132
Interlocked.Decrement(ref _busyCount);
128-
Interlocked.Increment(ref _processedCount);
133+
lock (_countLock)
134+
{
135+
_processedCount++;
136+
poolmember.PercentComplete = 0;
137+
}
138+
139+
poolmember.PercentComplete = 0;
129140
while (!_availablePoolMembers.TryAdd(poolmember, 1000, _cancellationToken))
130141
{
131142
_cancellationToken.ThrowIfCancellationRequested();
132143
Debug.WriteLine("WaitForAvailablePowershell - TryAdd failed");
133144
}
134-
Debug.WriteLine($"ReportAvailable - Busy: {_busyCount} _processed {_processedCount}, member = {poolmember.Index}");
135145
}
136146

137147
public void ReportStopped(PowerShellPoolMember powerShellPoolMember)

src/PSParallel/ProgressManager.cs

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Diagnostics;
33
using System.Management.Automation;
4-
54
namespace PSParallel
65
{
76
class ProgressManager
@@ -33,7 +32,7 @@ public void UpdateCurrentProgressRecord(int count)
3332
_progressRecord.PercentComplete = percentComplete;
3433
_progressRecord.SecondsRemaining = GetSecondsRemaining(count);
3534
}
36-
}
35+
}
3736
}
3837

3938
public void UpdateCurrentProgressRecord(string currentOperation, int count)
@@ -54,8 +53,18 @@ public ProgressRecord Completed()
5453
return _progressRecord;
5554
}
5655

57-
private int GetSecondsRemaining(int count) => count == 0 ? -1 : (int) ((TotalCount - count)*_stopwatch.ElapsedMilliseconds/1000/count);
58-
private int GetPercentComplete(int count) => count*100/TotalCount;
56+
private int GetSecondsRemaining(int count)
57+
{
58+
var secondsRemaining = count == 0 ? -1 : (int) ((TotalCount - count)*_stopwatch.ElapsedMilliseconds/1000/count);
59+
return secondsRemaining;
60+
}
61+
62+
private int GetPercentComplete(int count)
63+
{
64+
var percentComplete = count*100/TotalCount;
65+
return percentComplete;
66+
}
67+
5968
public int ActivityId => _progressRecord.ActivityId;
6069
}
6170

src/PSParallel/Properties/AssemblyInfo.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@
3232
// by using the '*' as shown below:
3333
// [assembly: AssemblyVersion("1.0.*")]
3434
[assembly: AssemblyVersion("1.0.0.0")]
35-
[assembly: AssemblyFileVersion("2.2.0.0")]
35+
[assembly: AssemblyFileVersion("2.2.2.0")]

0 commit comments

Comments
 (0)