Skip to content

Instantly share code, notes, and snippets.

@dsyme
Created January 14, 2019 17:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dsyme/cbeb525e7c7d16ee0ad2965bf747fb4a to your computer and use it in GitHub Desktop.
Save dsyme/cbeb525e7c7d16ee0ad2965bf747fb4a to your computer and use it in GitHub Desktop.
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