Guest User

Untitled

a guest
Jun 17th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.90 KB | None | 0 0
  1. # All this C# is to synthesize a signal that corresponds to when a runspace is
  2. # ready to be used.
  3. # see also PowerShell/PowerShell#7034
  4. Add-Type '
  5. using System.Management.Automation;
  6. using System.Management.Automation.Runspaces;
  7. using System.Threading.Tasks;
  8. using System.Collections.Concurrent;
  9. using System.Linq;
  10. using System;
  11.  
  12. namespace ns
  13. {
  14. public class RunspaceStateTransition : IEquatable<RunspaceStateTransition>
  15. {
  16. public Nullable<RunspaceAvailability> Availability { get; private set; }
  17. public Nullable<RunspaceState> State { get; private set; }
  18.  
  19. public RunspaceStateTransition
  20. (
  21. Nullable<RunspaceAvailability> availability,
  22. Nullable<RunspaceState> state
  23. )
  24. {
  25. Availability = availability;
  26. State = state;
  27. }
  28.  
  29. public bool Equals(RunspaceStateTransition other)
  30. {
  31. if (other==null) return false;
  32. return Availability == other.Availability &&
  33. State == other.State;
  34. }
  35. }
  36.  
  37. public static class OpenRunspaceWaiterTask
  38. {
  39. public static Task Create(Runspace runspace)
  40. {
  41. var tcs = new TaskCompletionSource<object>();
  42.  
  43. System.EventHandler<RunspaceAvailabilityEventArgs> availabilityHandler = null;
  44. System.EventHandler<RunspaceStateEventArgs> stateHandler = null;
  45.  
  46. var log = new ConcurrentQueue<RunspaceStateTransition>();
  47.  
  48. availabilityHandler = (s,e) => {
  49. log.Enqueue( new RunspaceStateTransition(e.RunspaceAvailability,null));
  50.  
  51. if ( RunspaceIsOpen(runspace.InitialSessionState,log.ToArray()) )
  52. {
  53. runspace.AvailabilityChanged -= availabilityHandler;
  54. runspace.StateChanged -= stateHandler;
  55.  
  56. tcs.SetResult(null);
  57. }
  58. };
  59. stateHandler = (s,e) => {
  60. log.Enqueue( new RunspaceStateTransition(null,e.RunspaceStateInfo.State));
  61.  
  62. if ( RunspaceIsOpen(runspace.InitialSessionState,log.ToArray()) )
  63. {
  64. runspace.AvailabilityChanged -= availabilityHandler;
  65. runspace.StateChanged -= stateHandler;
  66.  
  67. tcs.SetResult(null);
  68. }
  69. };
  70.  
  71. runspace.AvailabilityChanged += availabilityHandler;
  72. runspace.StateChanged += stateHandler;
  73. return tcs.Task;
  74. }
  75.  
  76. public static bool RunspaceIsOpen(
  77. InitialSessionState initialSessionState,
  78. RunspaceStateTransition[] log
  79. )
  80. {
  81. RunspaceStateTransition[] expected = null;
  82.  
  83. if ( initialSessionState == null ||
  84. initialSessionState.Modules.Count == 0 )
  85. {
  86. expected = new[] {
  87. new RunspaceStateTransition(null,RunspaceState.Opening),
  88. new RunspaceStateTransition(RunspaceAvailability.Available,null),
  89. new RunspaceStateTransition(null,RunspaceState.Opened )
  90. };
  91. }
  92. else
  93. {
  94. expected = new [] {
  95. new RunspaceStateTransition(null,RunspaceState.Opening),
  96. new RunspaceStateTransition(RunspaceAvailability.Available,null),
  97. new RunspaceStateTransition(null,RunspaceState.Opened ),
  98. new RunspaceStateTransition(RunspaceAvailability.Busy,null),
  99. new RunspaceStateTransition(RunspaceAvailability.Available,null)
  100. };
  101. }
  102.  
  103. return log.SequenceEqual(expected);
  104. }
  105. }
  106. }
  107. ' -ReferencedAssemblies @(
  108. 'System.Threading.Tasks'
  109. 'System.Management.Automation'
  110. 'System.Collections.Concurrent'
  111. 'System.Linq'
  112. )
  113.  
  114. # Create a module the invokation of whose scriptblock is slow and CPU-bound.
  115. $moduleContent = {
  116. function fibonacci {
  117. param([int]$n)
  118. [bigint]$a=0
  119. [bigint]$b=1
  120. foreach ($x in 0..$n)
  121. {
  122. $a,$b = $b,($a+$b)
  123. }
  124. $b
  125. }
  126. fibonacci 100000
  127. }
  128. $modulePath = "$([System.IO.Path]::GetTempPath())slowLoading.psm1"
  129. $moduleContent | Set-Content $modulePath
  130.  
  131. $p = [System.Environment]::ProcessorCount
  132. "ProcessorCount: $p"
  133.  
  134. $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
  135.  
  136. $initialSessionState = [initialsessionstate]::CreateDefault()
  137. $initialSessionState.ImportPSModule($modulePath)
  138.  
  139. $runspace = 1..$p | % { [runspacefactory]::CreateRunspace($initialSessionState) }
  140.  
  141. $awaiter = $runspace | % { [ns.OpenRunspaceWaiterTask]::Create($_) }
  142.  
  143. "$($stopwatch.ElapsedMilliseconds)ms : OpenAsync()"
  144. $runspace.OpenAsync()
  145.  
  146. "$($stopwatch.ElapsedMilliseconds)ms : WaitAll()"
  147. [System.Threading.Tasks.Task]::WaitAll($awaiter)
  148.  
  149. "$($stopwatch.ElapsedMilliseconds)ms : done"
Add Comment
Please, Sign In to add comment