Created
January 14, 2019 17:16
-
-
Save dsyme/cbeb525e7c7d16ee0ad2965bf747fb4a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ResizeArray = | |
/// Split a ResizeArray into an array of smaller chunks. | |
/// This requires `items/chunkSize` Array copies of length `chunkSize` if `items/chunkSize % 0 = 0`, | |
/// otherwise `items/chunkSize + 1` Array copies. | |
let chunkBySize f chunkSize (items: ResizeArray<'t>) = | |
// we could use Seq.chunkBySize here, but that would involve many enumerator.MoveNext() calls that we can sidestep with a bit of math | |
let itemCount = items.Count | |
if itemCount = 0 | |
then [||] | |
else | |
let chunksCount = | |
match itemCount / chunkSize with | |
| n when itemCount % chunkSize = 0 -> n | |
| n -> n + 1 // any remainder means we need an additional chunk to store it | |
[| for index in 0..chunksCount-1 do | |
let startIndex = index * chunkSize | |
let takeCount = min (itemCount - startIndex) chunkSize | |
// pre-creating the array and doing a single copy is slightly better than | |
// two copies via ResizeArray<'t>.GetRange(start, count).ToArray(). | |
let holder = Array.zeroCreate takeCount | |
for i in 0 .. takeCount - 1 do | |
holder.[i] <- f items.[startIndex + i] | |
yield holder |] | |
/// Split a large ResizeArray into a series of array chunks that are each under the | |
/// Large Object Heap limit, in order to prevent the entire array from not being garbage-collected. | |
let mapToSmallArrayChunks f (inp: ResizeArray<'t>) = | |
let itemSizeBytes = sizeof<'t> | |
let lohSizeThresholdBytes = 85_000 | |
// rounding down here is good because it ensures we don't go over | |
let maxArrayItemCount = lohSizeThresholdBytes / itemSizeBytes | |
/// chunk the provided input into arrays that are smaller than the LOH limit | |
/// in order to prevent long-term storage of those values | |
chunkBySize f maxArrayItemCount inp |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment