Reduce temporary string allocations
authorStefanos A <stapostol@gmail.com>
Thu, 5 Dec 2013 10:20:58 +0000 (11:20 +0100)
committerStefanos A <stapostol@gmail.com>
Thu, 5 Dec 2013 10:20:58 +0000 (11:20 +0100)
Instead of modifying the name of an OpenGL symbol on the managed side,
before copying it to the unmanaged side, we perform the modification
directly on the unmanaged side. This reduces the total amount of
allocations in OpenTK by ~30% (673496 bytes in 10750 objects compared
to 930272 bytes in 15243 objects before this modification.)

Source/OpenTK/Platform/MacOS/AglContext.cs

index 867c5dc..65bdd0a 100644 (file)
@@ -479,15 +479,35 @@ namespace OpenTK.Platform.MacOS
 
         public override IntPtr GetAddress(string function)
         {
-            string fname = "_" + function;
-            if (!NSIsSymbolNameDefined(fname))
-                return IntPtr.Zero;
-            
-            IntPtr symbol = NSLookupAndBindSymbol(fname);
-            if (symbol != IntPtr.Zero)
-                symbol = NSAddressOfSymbol(symbol);
-            
-            return symbol;
+            // Instead of allocating and combining strings in managed memory
+            // we do that directly in unmanaged memory. This way, we avoid
+            // 2 string allocations every time this function is called.
+
+            // must add a '_' prefix and null-terminate the function name,
+            // hence we allocate +2 bytes
+            IntPtr ptr = Marshal.AllocHGlobal(function.Length + 2);
+            try
+            {
+                Marshal.WriteByte(ptr, (byte)'_');
+                for (int i = 0; i < function.Length; i++)
+                {
+                    Marshal.WriteByte(ptr, i + 1, (byte)function[i]);
+                }
+                Marshal.WriteByte(ptr, function.Length + 1, 0); // null-terminate
+
+                IntPtr symbol = IntPtr.Zero;
+                if (NSIsSymbolNameDefined(ptr))
+                {
+                    symbol = NSLookupAndBindSymbol(ptr);
+                    if (symbol != IntPtr.Zero)
+                        symbol = NSAddressOfSymbol(symbol);
+                }
+                return symbol;
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(ptr);
+            }
         }
 
         public override IntPtr GetAddress(IntPtr function)