Frage

Nehmen wir an, Sie möchten eine Hochleistungsmethode schreiben, die einen großen Datensatz verarbeitet. Warum sollten Entwickler nicht die Möglichkeit haben, das manuelle Speichermanagement einzuschalten, anstatt gezwungen zu werden, zu C oder C ++ zu wechseln?

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

            // process

            delete buffer;
        } 
    }   
}
War es hilfreich?

Lösung

Denn so können Sie einen Speicherblock manuell löschen, während es möglicherweise noch Hinweise darauf gibt (und die Laufzeit kann nicht wissen, dass ohne einen GC -Zyklus baumelnde Zeiger hervorrufen kann und somit brechen kann Speichersicherheit. GC-Sprachen sind im Allgemeinen von Design-sicherem Gedächtnis.

In C#können Sie insbesondere das tun, was Sie wollen:

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

            // process

            Marshal.FreeHGlobal(buffer);
        } 
    }   
}

Beachten Sie, dass Sie wie in C/C ++ eine vollständige Zeigerarithmetik für Rohzeigertypen in C# - also haben buffer[i] oder buffer+i sind gültige Ausdrücke.

Andere Tipps

Wenn Sie eine hohe Leistung und eine detaillierte Kontrolle benötigen, sollten Sie vielleicht das schreiben, was Sie in C oder C ++ tun. Nicht alle Sprachen sind gut für alle Dinge.

Bearbeitet, um hinzuzufügen: Eine einzelne Sprache wird nicht für alle Dinge gut sein. Wenn Sie alle nützlichen Funktionen in allen guten Programmiersprachen addieren, werden Sie ein wirklich großes Chaos bekommen, weitaus schlechter als C ++, auch wenn Sie Inkonsistenz vermeiden können.

Funktionen sind nicht kostenlos. Wenn eine Sprache ein Merkmal hat, verwenden die Menschen sie wahrscheinlich. Sie werden nicht in der Lage sein, C# gut genug zu lernen, ohne die neuen Routinen des Manual Memory Management -Managements C# zu lernen. Compiler -Teams werden es auf Kosten anderer Compiler -Funktionen implementieren, die nützlich sind. Die Sprache wird wahrscheinlich schwer wie C oder C ++ zu analysieren, und dies führt zu einer langsamen Zusammenstellung. (Als C ++ - Mann bin ich immer erstaunt, wenn ich eines unserer C# -Projekte zusammenstelle. Die Zusammenstellung scheint fast augenblicklich.)

Funktionen in Konflikt zueinander, manchmal auf unerwartete Weise. C90 kann bei Matrix -Berechnungen nicht so gut abschneiden, da die Möglichkeit, dass C -Zeiger aliased sind, einige Optimierungen verhindert. Wenn Sie Zeigerarithmetik in einer Sprache zulassen, müssen Sie seine Konsequenzen akzeptieren.

Sie schlagen eine C# -Erweiterung vor, um das manuelle Speichermanagement zu ermöglichen, und in einigen Fällen wären dies nützlich. Das würde bedeuten, dass das Speicher auf getrennte Weise zugewiesen werden müsste, und es müsste eine Möglichkeit geben, einen manuell verwalteten Speicher aus automatisch verwaltetem Speicher zu erzählen. Plötzlich haben Sie eine komplizierte Speicherverwaltung, es besteht mehr Chance für einen Programmierer, sich zu vermasseln, und der Speichermanager selbst ist komplizierter. Sie erhalten eine kleine Leistung, die in einigen Fällen im Austausch für mehr Komplikationen und langsamere Speichermanagement in allen Fällen wichtig ist.

Es kann sein, dass wir irgendwann eine Programmiersprache haben werden, die für fast alle Zwecke gut ist, vom Scripting bis zum Zahlenknopf, aber es gibt nichts Populäres, das in der Nähe ist. In der Zwischenzeit müssen wir bereit sein, die Grenzen der Verwendung von nur einer Sprache oder der Herausforderung zu akzeptieren, mehrere zu lernen und zwischen ihnen zu wechseln.

Warum nicht einfach den Puffer löschen und wiederverwenden in dem Beispiel, das Sie gepostet haben?

Der Müllkollektor .NET ist sehr sehr gut darin, herauszufinden, auf welche Objekte nicht mehr verwiesen werden, und die zugehörige Speicher rechtzeitig zu befreien. Tatsächlich verfügt der Müllsammler über einen speziellen Haufen (das große Objekthaufen), in dem er große Objekte wie diese setzt, die optimiert werden, um mit ihnen umzugehen.

Darüber hinaus entfernt, wenn keine Referenzen explizit befreit werden, beseitigt einfach eine ganze Reihe von Fehler mit Speicherlecks und baumelnden Zeigern, was zu viel sichererem Code führt.

Die Befreiung jedes nicht verwendeten Blocks einzeln wie in einer Sprache mit explizitem Speichermanagement kann teurer sein als ein Müllsammler dies tun zu lassen, da die GC die Möglichkeit hat, Kopierschemata zu verwenden, um eine Zeit linear für die Anzahl der lebendigen Blöcke zu verbringen (oder Die Anzahl der neuesten Blöcke, die lebendig sind), anstatt jeden toten Block verarbeiten zu müssen.

Der gleiche Grund, warum die meisten Kerne nicht zulassen, dass Sie Ihre eigenen Threads planen. Denn 99,99+% der Zeit, die Sie nicht wirklich benötigen, und die Aufdeckung dieser Funktionalität für den Rest der Zeit wird Sie nur dazu verleiten, etwas potenziell Dummes/Gefährliches zu tun.

Wenn Sie wirklich eine feine Getreidespeicherregelung benötigen, schreiben Sie diesen Abschnitt des Codes in etwas anderes.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top