????1????????????????С?????????С?????СС??85?? 000????????????????LOH???

????2??????“????”?????????????????????????

????3?????????????????3???

??????????????????????????????饗List<float>?????????Щ?????????????Щ??????С??????????85?? 000????????????????????????????LOH?????????????????????????????????????????????????????????????????1????????????????????C++??deque??????????????????????洢?????????????????С??С??85?? 000?????????????????

?????????????????????64λ?????п????????????????64λ???????и?????????????????????????.NET?е?LOH???????Χ?????????????????????????????????????????OutOfMemoryException???????????????潻??????????????????????????е?????????

????????????????????б??????IList<T>????????????List<T>??????????????????????????????????

    public class BlockList<T> : IList<T> 
     { 
         private static int maxAllocSize; 
         private static int initAllocSize; 
         private T[][] blocks; 
         private int blockCount; 
         private int[] blockSizes; 
         private int version; 
         private int countCache; 
         private int countCacheVersion; 
      
         static BlockList() 
         { 
             var type = typeof(T); 
             var size = type.IsValueType ? Marshal.SizeOf(default(T)) : IntPtr.Size; 
             maxAllocSize = 80000 / size; 
             initAllocSize = 8; 
         } 
      
         public BlockList() 
         { 
             blocks = new T[8][]; 
             blockSizes = new int[8]; 
             blockCount = 0; 
         } 
      
         public void Add(T item) 
         { 
             int blockId = 0?? blockSize = 0; 
             if (blockCount == 0) 
             { 
                 UseNewBlock(); 
             } 
             else
             { 
                 blockId = blockCount - 1; 
                 blockSize = blockSizes[blockId]; 
                 if (blockSize == blocks[blockId].Length) 
                 { 
                     if (!ExpandBlock(blockId)) 
                     { 
                         UseNewBlock(); 
                         ++blockId; 
                         blockSize = 0; 
                     } 
                 } 
             } 
      
             blocks[blockId][blockSize] = item; 
             ++blockSizes[blockId]; 
             ++version; 
         } 
      
         public void Insert(int index?? T item) 
         { 
             if (index > Count) 
             { 
                 throw new ArgumentOutOfRangeException("index"); 
             } 
      
             if (blockCount == 0) 
             { 
                 UseNewBlock(); 
                 blocks[0][0] = item; 
                 blockSizes[0] = 1; 
                 ++version; 
                 return; 
             } 
      
             for (int i = 0; i < blockCount; ++i) 
             { 
                 if (index >= blockSizes[i]) 
                 { 
                     index -= blockSizes[i]; 
                     continue; 
                 } 
      
                 if (blockSizes[i] < blocks[i].Length || ExpandBlock(i)) 
                 { 
                     for (var j = blockSizes[i]; j > index; --j) 
                     { 
                         blocks[i][j] = blocks[i][j - 1]; 
                     } 
      
                     blocks[i][index] = item; 
                     ++blockSizes[i]; 
                     break; 
                 } 
      
                 if (i == blockCount - 1) 
                 { 
                     UseNewBlock(); 
                 } 
      
                 if (blockSizes[i + 1] == blocks[i + 1].Length 
                     && !ExpandBlock(i + 1)) 
                 { 
                     UseNewBlock(); 
                     var newBlock = blocks[blockCount - 1]; 
                     for (int j = blockCount - 1; j > i + 1; --j) 
                     { 
                         blocks[j] = blocks[j - 1]; 
                         blockSizes[j] = blockSizes[j - 1]; 
                     } 
      
                     blocks[i + 1] = newBlock; 
                     blockSizes[i + 1] = 0; 
                 } 
      
                 var nextBlock = blocks[i + 1]; 
                 var nextBlockSize = blockSizes[i + 1]; 
                 for (var j = nextBlockSize; j > 0; --j) 
                 { 
                     nextBlock[j] = nextBlock[j - 1]; 
                 } 
      
                 nextBlock[0] = blocks[i][blockSizes[i] - 1]; 
                 ++blockSizes[i + 1]; 
      
                 for (var j = blockSizes[i] - 1; j > index; --j) 
                 { 
                     blocks[i][j] = blocks[i][j - 1]; 
                 } 
      
                 blocks[i][index] = item; 
                 break; 
             } 
      
             ++version; 
         } 
      
         public void RemoveAt(int index) 
         { 
             if (index < 0 || index >= Count) 
             { 
                 throw new ArgumentOutOfRangeException("index"); 
             } 
      
             for (int i = 0; i < blockCount; ++i) 
             { 
                 if (index >= blockSizes[i]) 
                 { 
                     index -= blockSizes[i]; 
                     continue; 
                 } 
      
                 if (blockSizes[i] == 1) 
                 { 
                     for (int j = i + 1; j < blockCount; ++j) 
                     { 
                         blocks[j - 1] = blocks[j]; 
                         blockSizes[j - 1] = blockSizes[j]; 
                     } 
      
                     blocks[blockCount - 1] = null; 
                     blockSizes[blockCount - 1] = 0; 
                     --blockCount; 
                 } 
                 else
                 { 
                     for (int j = index + 1; j < blockSizes[i]; ++j) 
                     { 
                         blocks[i][j - 1] = blocks[i][j]; 
                     } 
      
                     blocks[i][blockSizes[i] - 1] = default(T); 
                     --blockSizes[i]; 
                 } 
      
                 break; 
             } 
      
             ++version; 
         } 
      
         private bool ExpandBlock(int blockId) 
         { 
             var length = blocks[blockId].Length; 
             if (length == maxAllocSize) 
             { 
                 return false; 
             } 
      
             length = Math.Min(length * 2?? maxAllocSize); 
             Array.Resize(ref blocks[blockId]?? length); 
             return true; 
         } 
      
         private void UseNewBlock() 
         { 
             if (blockCount == blocks.Length) 
             { 
                 Array.Resize(ref blocks?? blockCount * 2); 
                 Array.Resize(ref blockSizes?? blockCount * 2); 
             } 
      
             blocks[blockCount] = new T[initAllocSize]; 
             blockSizes[blockCount] = 0; 
             ++blockCount; 
         } 
     }