views:

159

answers:

6

Lets say you want to write a high performance method which processes a large data set. Why shouldn't developers have the ability to turn on manual memory management instead of being forced to move to C or C++?

void Process()
{
    unmanaged
    {
        Byte[] buffer;
        while (true)
        {
            buffer = new Byte[1024000000];

            // process

            delete buffer;
        } 
    }   
}
+2  A: 

If you need high performance and detailed control, maybe you should write what you're doing in C or C++. Not all languages are good for all things.

Edited to add: A single language is not going to be good for all things. If you add up all the useful features in all the good programming languages, you're going to get a really big mess, far worse than C++, even if you can avoid inconsistency.

Features aren't free. If a language has a feature, people are likely to use it. You won't be able to learn C# well enough without learning the new C# manual memory management routines. Compiler teams are going to implement it, at the cost of other compiler features that are useful. The language is likely to become difficult to parse like C or C++, and that leads to slow compilation. (As a C++ guy, I'm always amazed when I compile one of our C# projects. Compilation seems almost instantaneous.)

Features conflict with each other, sometimes in unexpected ways. C90 can't do as well as Fortran at matrix calculations, since the possibility that C pointers are aliased prevents some optimizations. If you allow pointer arithmetic in a language, you have to accept its consequences.

You're suggesting a C# extension to allow manual memory management, and in a few cases that would be useful. That would mean that memory would have to be allocated in separate ways, and there would have to be a way to tell manually managed memory from automatically managed memory. Suddenly, you've complicated memory management, there's more chance for a programmer to screw up, and the memory manager itself is more complicated. You're gaining a little performance that matters in a few cases in exchange for more complication and slower memory management in all cases.

It may be that at some time we'll have a programming language that's good for almost all purposes, from scripting to number crunching, but there's nothing popular that's anywhere near that. In the meantime, we have to be willing to accept the limitations of using only one language, or the challenge of learning several and switching between them.

David Thornley
This is more of a comment than an answer.
ChaosPandion
Okay, that should be better.
David Thornley
@David: Great comment!
CesarGon
I am not suggesting, I am wondering why it has not been done. Besides putting words in my mouth you do make some great points.
ChaosPandion
A: 

In the example you posted, why not just erase the buffer and re-use it?

Anon.
Well the example is about as contrived as you can get. I was hoping people would use their imagination.
ChaosPandion
+13  A: 

Because allowing you to manually delete a memory block while there may still be references to it (and the runtime has no way of knowing that without doing a GC cycle) can produce dangling pointers, and thus break memory safety. GC languages are generally memory-safe by design.

That said, in C#, in particular, you can do what you want already:

void Process()
{
    unsafe
    {
        byte* buffer;
        while (true)
        {
            buffer = Marshal.AllocHGlobal(1024000000);

            // process

            Marshal.FreeHGlobal(buffer);
        } 
    }   
}

Note that, as in C/C++, you have full pointer arithmetic for raw pointer types in C# - so buffer[i] or buffer+i are valid expressions.

Pavel Minaev
Is there a way to inform the GC to not collect until you finish doing this high performance piece?
ChaosPandion
No, but you can tell it that there's a large block of unmanaged memory around using http://msdn.microsoft.com/en-us/library/system.gc.addmemorypressure.aspx and http://msdn.microsoft.com/en-us/library/system.gc.removememorypressure.aspx - this'll allow it to make a better decision about when and what to collect
thecoop
There isn't any documented way to disable .NET GC, so far as I know - not even with hosting APIs. However, if you do a full GC prior to the "critical" code block, don't do any managed memory allocation within the block, and don't run (or suspend) any background threads that do it, then I think the GC won't run. No guarantees, though. In general, if you want hard real-time, you should definitely stay away from any kind of GC.
Pavel Minaev
This example will definitely get close to high performance. I would rather use this than write one function in a C++ dll.
ChaosPandion
Writing native functions is an option, but it's worth keeping in mind that calls from managed to native (and vice versa) are also more expensive than calling managed/managed or native/native.
Pavel Minaev
A: 

The .NET garbage collector is very very good at working out which objects aren't referenced anymore and freeing the associated memory in a timely manner. In fact, the garbage collector has a special heap (the large object heap) in which it puts large objects like this, that is optimized to deal with them.

On top of this, not allowing references to be explicitly freed simply removes a whole host of bugs with memory leaks and dangling pointers, that leads to much safer code.

thecoop
A: 

Freeing each unused block individually as done in a language with explicit memory management can be more expensive than letting a Garbage Collector do it, because the GC has the possibility to use copying schemes to spend a time linear to the number of blocks left alive (or the number of recent blocks left alive) instead of having to handle each dead block.

Pascal Cuoq
A: 

The same reason most kernels won't let you schedule your own threads. Because 99.99+% of time you don't really need to, and exposing that functionality the rest of the time will only tempt you to do something potentially stupid/dangerous.

If you really need fine grain memory control, write that section of code in something else.

patros