Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
Delay Random allocation in ConcurrentStack
Browse files Browse the repository at this point in the history
ConcurrentStack currently uses a randomized-backoff scheme, where under contention it spins for increasingly longer periods of time, with a duration influenced by some randomness.  If the initial attempt at popping an item fails due to contention, it allocates a Random, then tries again one or more times, and then uses the randomness to influence backoff for subsequent attempts.  While it's not clear to me that this scheme is optimal, we can at least delay the allocation of the Random (and the underlying cost it entails, like an int[] in its ctor) until it's actually used.  Since it's typically not used for a few attempts, this significantly decreases the number of instances that get created under heavy contention.
  • Loading branch information
stephentoub committed Feb 18, 2017
1 parent f0ccd97 commit c0a0c55
Showing 1 changed file with 13 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@ private int TryPopCore(int count, out Node poppedHead)
Node head;
Node next;
int backoff = 1;
Random r = new Random(Environment.TickCount & Int32.MaxValue); // avoid the case where TickCount could return Int32.MinValue
Random r = null;
while (true)
{
head = _head;
Expand Down Expand Up @@ -694,7 +694,18 @@ private int TryPopCore(int count, out Node poppedHead)
spin.SpinOnce();
}

backoff = spin.NextSpinWillYield ? r.Next(1, BACKOFF_MAX_YIELDS) : backoff * 2;
if (spin.NextSpinWillYield)
{
if (r == null)
{
r = new Random();
}
backoff = r.Next(1, BACKOFF_MAX_YIELDS);
}
else
{
backoff *= 2;
}
}
}
#pragma warning restore 0420
Expand Down

0 comments on commit c0a0c55

Please sign in to comment.