2
2
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
3
4
4
using System . Collections . Concurrent ;
5
- using System . Diagnostics ;
6
- using System . Runtime . InteropServices ;
7
- using System . Threading ;
8
5
9
6
#nullable enable
10
7
@@ -20,13 +17,6 @@ internal sealed class SlabMemoryPool : MemoryPool<byte>
20
17
/// </summary>
21
18
private const int _blockSize = 4096 ;
22
19
23
- /// <summary>
24
- /// Allocating 32 contiguous blocks per slab makes the slab size 128k. This is larger than the 85k size which will place the memory
25
- /// in the large object heap. This means the GC will not try to relocate this array, so the fact it remains pinned does not negatively
26
- /// affect memory management's compactification.
27
- /// </summary>
28
- private const int _blockCount = 32 ;
29
-
30
20
/// <summary>
31
21
/// Max allocation block size for pooled blocks,
32
22
/// larger values can be leased but they will be disposed after use rather than returned to the pool.
@@ -38,30 +28,17 @@ internal sealed class SlabMemoryPool : MemoryPool<byte>
38
28
/// </summary>
39
29
public static int BlockSize => _blockSize ;
40
30
41
- /// <summary>
42
- /// 4096 * 32 gives you a slabLength of 128k contiguous bytes allocated per slab
43
- /// </summary>
44
- private static readonly int _slabLength = _blockSize * _blockCount ;
45
-
46
31
/// <summary>
47
32
/// Thread-safe collection of blocks which are currently in the pool. A slab will pre-allocate all of the block tracking objects
48
33
/// and add them to this collection. When memory is requested it is taken from here first, and when it is returned it is re-added.
49
34
/// </summary>
50
35
private readonly ConcurrentQueue < MemoryPoolBlock > _blocks = new ConcurrentQueue < MemoryPoolBlock > ( ) ;
51
36
52
- /// <summary>
53
- /// Thread-safe collection of slabs which have been allocated by this pool. As long as a slab is in this collection and slab.IsActive,
54
- /// the blocks will be added to _blocks when returned.
55
- /// </summary>
56
- private readonly ConcurrentStack < MemoryPoolSlab > _slabs = new ConcurrentStack < MemoryPoolSlab > ( ) ;
57
-
58
37
/// <summary>
59
38
/// This is part of implementing the IDisposable pattern.
60
39
/// </summary>
61
40
private bool _isDisposed ; // To detect redundant calls
62
41
63
- private int _totalAllocatedBlocks ;
64
-
65
42
private readonly object _disposeSync = new object ( ) ;
66
43
67
44
/// <summary>
@@ -76,16 +53,6 @@ public override IMemoryOwner<byte> Rent(int size = AnySize)
76
53
MemoryPoolThrowHelper . ThrowArgumentOutOfRangeException_BufferRequestTooLarge ( _blockSize ) ;
77
54
}
78
55
79
- var block = Lease ( ) ;
80
- return block ;
81
- }
82
-
83
- /// <summary>
84
- /// Called to take a block from the pool.
85
- /// </summary>
86
- /// <returns>The block that is reserved for the called. It must be passed to Return when it is no longer being used.</returns>
87
- private MemoryPoolBlock Lease ( )
88
- {
89
56
if ( _isDisposed )
90
57
{
91
58
MemoryPoolThrowHelper . ThrowObjectDisposedException ( MemoryPoolThrowHelper . ExceptionArgument . MemoryPool ) ;
@@ -94,53 +61,9 @@ private MemoryPoolBlock Lease()
94
61
if ( _blocks . TryDequeue ( out var block ) )
95
62
{
96
63
// block successfully taken from the stack - return it
97
-
98
- block . Lease ( ) ;
99
64
return block ;
100
65
}
101
- // no blocks available - grow the pool
102
- block = AllocateSlab ( ) ;
103
- block . Lease ( ) ;
104
- return block ;
105
- }
106
-
107
- /// <summary>
108
- /// Internal method called when a block is requested and the pool is empty. It allocates one additional slab, creates all of the
109
- /// block tracking objects, and adds them all to the pool.
110
- /// </summary>
111
- private MemoryPoolBlock AllocateSlab ( )
112
- {
113
- var slab = MemoryPoolSlab . Create ( _slabLength ) ;
114
- _slabs . Push ( slab ) ;
115
-
116
- // Get the address for alignment
117
- IntPtr basePtr = Marshal . UnsafeAddrOfPinnedArrayElement ( slab . PinnedArray ! , 0 ) ;
118
- // Page align the blocks
119
- var offset = ( int ) ( ( ( ( ulong ) basePtr + ( uint ) _blockSize - 1 ) & ~ ( ( uint ) _blockSize - 1 ) ) - ( ulong ) basePtr ) ;
120
- // Ensure page aligned
121
- Debug . Assert ( ( ( ulong ) basePtr + ( uint ) offset ) % _blockSize == 0 ) ;
122
-
123
- var blockCount = ( _slabLength - offset ) / _blockSize ;
124
- Interlocked . Add ( ref _totalAllocatedBlocks , blockCount ) ;
125
-
126
- MemoryPoolBlock ? block = null ;
127
-
128
- for ( int i = 0 ; i < blockCount ; i ++ )
129
- {
130
- block = new MemoryPoolBlock ( this , slab , offset , _blockSize ) ;
131
-
132
- if ( i != blockCount - 1 ) // last block
133
- {
134
- #if BLOCK_LEASE_TRACKING
135
- block . IsLeased = true ;
136
- #endif
137
- Return ( block ) ;
138
- }
139
-
140
- offset += _blockSize ;
141
- }
142
-
143
- return block ! ;
66
+ return new MemoryPoolBlock ( this , BlockSize ) ;
144
67
}
145
68
146
69
/// <summary>
@@ -163,25 +86,6 @@ internal void Return(MemoryPoolBlock block)
163
86
{
164
87
_blocks . Enqueue ( block ) ;
165
88
}
166
- else
167
- {
168
- GC . SuppressFinalize ( block ) ;
169
- }
170
- }
171
-
172
- // This method can ONLY be called from the finalizer of MemoryPoolBlock
173
- internal void RefreshBlock ( MemoryPoolSlab slab , int offset , int length )
174
- {
175
- lock ( _disposeSync )
176
- {
177
- if ( ! _isDisposed && slab != null && slab . IsActive )
178
- {
179
- // Need to make a new object because this one is being finalized
180
- // Note, this must be called within the _disposeSync lock because the block
181
- // could be disposed at the same time as the finalizer.
182
- Return ( new MemoryPoolBlock ( this , slab , offset , length ) ) ;
183
- }
184
- }
185
89
}
186
90
187
91
protected override void Dispose ( bool disposing )
@@ -197,17 +101,11 @@ protected override void Dispose(bool disposing)
197
101
198
102
if ( disposing )
199
103
{
200
- while ( _slabs . TryPop ( out var slab ) )
104
+ // Discard blocks in pool
105
+ while ( _blocks . TryDequeue ( out _ ) )
201
106
{
202
- // dispose managed state (managed objects).
203
- slab . Dispose ( ) ;
204
- }
205
- }
206
107
207
- // Discard blocks in pool
208
- while ( _blocks . TryDequeue ( out var block ) )
209
- {
210
- GC . SuppressFinalize ( block ) ;
108
+ }
211
109
}
212
110
}
213
111
}
0 commit comments