[Mono-dev] Large object size limits

Neale Ferguson NealeFerguson at verizon.net
Thu Jun 12 20:38:26 UTC 2014


The following program runs fine on .NET -

using System;
using System.Collections.Generic;
using System.Runtime;
using System.Text;

namespace LargeObjectTest
{
        class Program
        {
                static void Main(string[] args)
                {

                        IList<double> myList = new List<double>();


                        long index = 1024*1024*1024;

                        Console.WriteLine("index:" + index);

                        double[] array = null;

                        Console.WriteLine("UInt32.MaxValue: "+UInt32.MaxValue);
                        try
                        {
                                array = new double[index];

                                Console.WriteLine("doubleArray:LongLength " + array.Length * sizeof(double) + " bytes");
                                Console.WriteLine("sizeof(double) " + sizeof(double) + " bytes");
                                Console.WriteLine("index " + index);
                                Console.WriteLine("doubleArray:LongLength " + array.LongLength);
                                Console.WriteLine("doubleArray:Size " + array.LongLength * sizeof(double) * 1.0 + " Bytes");
                        }
                        catch (Exception e)
                        {
                                Console.WriteLine("Exception:" + e);
                                Console.WriteLine("Exception:" + e.Message + " allocating :" + index);
                                Console.WriteLine("Exception:" + e.Message + " allocating :" + index * sizeof(double));
                        }
                }
        }
}

However, on mono on Linux it results in:

index:1073741824
UInt32.MaxValue: 4294967295
Exception:System.OutOfMemoryException: Out of memory
  at (wrapper managed-to-native) object:__icall_wrapper_mono_array_new_specific (intptr,int)
  at LargeObjectTest.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0 
Exception:Out of memory allocating :1073741824
Exception:Out of memory allocating :8589934592

If I make the following change to override the SIZE_MAX value from /usr/include/stdint.h:

--- a/mono/metadata/sgen-los.c
+++ b/mono/metadata/sgen-los.c
@@ -342,8 +342,12 @@ sgen_los_alloc_large_inner (MonoVTable *vtable, size_t size)
         *
         * size <= SIZE_MAX - (mono_pagesize () - 1) - sizeof (LOSObject)
         */
+#undef SIZE_MAX
+#define SIZE_MAX (17179869184U)
        if (size > SIZE_MAX - (mono_pagesize () - 1) - sizeof (LOSObject))
                return NULL;
+#undef SIZE_MAX
+#define SIZE_MAX (4294967295U)
 
 #ifdef LOS_DUMMY
        if (!los_segment)

Then the program works as it does under .NET:

index:1073741824
UInt32.MaxValue: 4294967295
doubleArray:LongLength 0 bytes
sizeof(double) 8 bytes
index 1073741824
doubleArray:LongLength 1073741824
doubleArray:Size 8589934592 Bytes

The question is, what is the correct value for the comparison in lieu of SIZE_MAX? I can't determine what the max is on .NET. Another question is what type of compacting happens with large objects like this?

Neale



More information about the Mono-devel-list mailing list