Language agnostic 为什么不';托管语言是否提供手动删除对象的功能?

Language agnostic 为什么不';托管语言是否提供手动删除对象的功能?,language-agnostic,memory-management,garbage-collection,managed-code,Language Agnostic,Memory Management,Garbage Collection,Managed Code,假设您想编写一个处理大型数据集的高性能方法。 为什么开发者不应该有能力打开手动内存管理而不是被迫移动到C或C++?p> void Process() { unmanaged { Byte[] buffer; while (true) { buffer = new Byte[1024000000]; // process delete buffer;

假设您想编写一个处理大型数据集的高性能方法。 为什么开发者不应该有能力打开手动内存管理而不是被迫移动到C或C++?p>
void Process()
{
    unmanaged
    {
        Byte[] buffer;
        while (true)
        {
            buffer = new Byte[1024000000];

            // process

            delete buffer;
        } 
    }   
}

<>如果你需要高性能和详细的控制,也许你应该写下你在C或C++中所做的事情。并非所有的语言都适用于所有的事物

编辑后添加:单一语言并不是万能的。如果你把所有好的编程语言中所有有用的特性加起来,你会得到一个非常严重的混乱,甚至比C++更糟糕,即使你可以避免不一致。 功能不是免费的。如果一种语言有一个特点,人们很可能会使用它。如果不学习新的C#手动内存管理例程,您将无法学好C#。编译器团队将以其他有用的编译器特性为代价来实现它。语言很难像C或C++那样解析,这导致编译速度慢。(作为C++的人,当我编译我们的一个C项目时,我总是感到惊讶。编译几乎是瞬间的。) 特征之间相互冲突,有时以意想不到的方式。C90在矩阵计算方面不如Fortran,因为C指针有别名的可能性会阻止某些优化。如果允许在语言中使用指针算术,则必须接受其结果

您建议使用C#扩展来允许手动内存管理,在某些情况下这会很有用。这意味着必须以不同的方式分配内存,并且必须有一种方法来区分手动管理的内存和自动管理的内存。突然之间,你的内存管理变得复杂了,程序员有更多的机会搞砸了,内存管理器本身也变得更复杂了。在某些情况下,您会获得一些重要的性能,但在所有情况下,这会导致更复杂和更慢的内存管理


也许有一天,我们会有一种编程语言,它几乎适用于所有的用途,从脚本到数字运算,但没有一种流行的语言能做到这一点。同时,我们必须愿意接受仅使用一种语言的限制,或者学习几种语言并在它们之间切换的挑战。

在您发布的示例中,为什么不删除缓冲区并重新使用它?

因为允许您在仍有引用的情况下手动删除内存块(而且运行时无法知道,如果不进行GC循环的话)会产生悬空指针,因此会中断。GC语言在设计上通常是内存安全的

也就是说,特别是在C#中,你已经可以做你想做的事情了:

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

            // process

            Marshal.FreeHGlobal(buffer);
        } 
    }   
}

注意,与在C/C++中一样,在C#so
buffer[i]中,对于原始指针类型有完整的指针算法
buffer+i
是有效的表达式。

NET垃圾收集器非常擅长找出哪些对象不再被引用,并及时释放相关内存。事实上,垃圾收集器有一个特殊堆(大对象堆)它将这样的大型对象放入其中,并对其进行了优化处理


最重要的是,不允许显式释放引用只会删除大量带有内存泄漏和悬空指针的错误,这会导致更安全的代码。

像在具有显式内存管理的语言中那样单独释放每个未使用的块可能比让垃圾收集器这样做更昂贵,因为GC可以使用复制方案花费与剩余活动块数(或最近剩余活动块数)成线性关系的时间而不是必须处理每个死区。

这与大多数内核不允许您安排自己的线程的原因相同。因为99.99%的时间您实际上不需要这样做,而在其余时间暴露该功能只会诱使您做一些可能愚蠢/危险的事情


如果您真的需要细粒度的内存控制,请用其他方式编写该部分代码。

好的,这个示例是尽可能精心设计的。我希望人们能发挥他们的想象力。这更多的是一个评论,而不是一个答案。我不是在建议,我想知道为什么没有这样做。除了把话放在我嘴里,你还可以一些要点。有没有一种方法可以通知GC在完成这项高性能工作之前不要收集?没有,但您可以告诉它,在使用和-这将使它能够更好地决定何时和收集什么。据我所知,没有任何文档化的方法来禁用.NET GC-即使使用宿主API也不行。但是,如果在“关键”代码块之前执行完整GC,则不要在该块内执行任何托管内存分配,也不要运行(或挂起)任何背景线程都会这样做,那么我认为GC不会运行。虽然没有保证。一般来说,如果你想要硬实时,你应该绝对远离任何GC。这个例子肯定会接近高性能。我宁愿使用这个,而不在C++ DLL中写一个函数。编写本机函数是一个选项,但是它。值得记住的是,从托管到本机(反之亦然)的调用也比调用托管/托管或本机/本机更昂贵。