//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test void shouldRegisterConcurrentAllocationsAndDeallocations() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        internal virtual void ShouldRegisterConcurrentAllocationsAndDeallocations()
        {
            // given
            ThreadSafePeakMemoryAllocationTracker tracker = new ThreadSafePeakMemoryAllocationTracker(GlobalMemoryTracker.Instance);
            Race race = new Race();

            race.AddContestants(10, () =>
            {
                for (int i = 1; i < 100; i++)
                {
                    tracker.Allocated(i);
                    assertThat(tracker.UsedDirectMemory(), greaterThan(0L));
                }
                for (int i = 1; i < 100; i++)
                {
                    assertThat(tracker.UsedDirectMemory(), greaterThan(0L));
                    tracker.Deallocated(i);
                }
            }, 1);

            // when
            race.Go();

            // then
            assertEquals(0, tracker.UsedDirectMemory());
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test void shouldRegisterPeakMemoryUsage() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        internal virtual void ShouldRegisterPeakMemoryUsage()
        {
            // given
            ThreadSafePeakMemoryAllocationTracker tracker = new ThreadSafePeakMemoryAllocationTracker(GlobalMemoryTracker.Instance);
            int threads = 200;

            long[]            allocations = new long[threads];
            ThreadLocalRandom random      = ThreadLocalRandom.current();
            long sum = 0;

            for (int i = 0; i < allocations.Length; i++)
            {
                allocations[i] = random.Next(1, 10_000);
                sum           += allocations[i];
            }

            // when
            Race race = new Race();

            for (int i = 0; i < threads; i++)
            {
                int id = i;
                race.AddContestant(() => tracker.allocated(allocations[id]));
            }
            race.Go();
            long peakAfterAllocation = tracker.PeakMemoryUsage();

            LongStream.of(allocations).forEach(tracker.deallocated);
            long peakAfterDeallocation = tracker.PeakMemoryUsage();

            LongStream.of(allocations).forEach(tracker.allocated);
            tracker.Allocated(10);                 // <-- 10 more than previous peak
            long peakAfterHigherReallocation = tracker.PeakMemoryUsage();

            LongStream.of(allocations).forEach(tracker.deallocated);
            tracker.Deallocated(10);
            long peakAfterFinalDeallocation = tracker.PeakMemoryUsage();

            // then
            assertEquals(sum, peakAfterAllocation);
            assertEquals(sum, peakAfterDeallocation);
            assertEquals(sum + 10, peakAfterHigherReallocation);
            assertEquals(sum + 10, peakAfterFinalDeallocation);
        }