2016-10-07 8 views
0

Bin ich richtig anzunehmen, dass, wenn ein Prozess malloc aufruft, möglicherweise E/A involviert ist (Auslagern von Caches usw.), um Speicher verfügbar zu machen, was wiederum impliziert, dass er beträchtliche Zeit blockieren kann? Also, sollten wir nicht zwei Versionen von malloc in Linux haben, sagen wir "fast_malloc", das zum Erhalten kleinerer Blöcke & garantiert nicht blockieren (aber natürlich immer noch mit OUT_OF_MEMORY) und einem anderen async_malloc geeignet ist, wo wir nach Belieben fragen könnten -size Speicherplatz, aber einen Rückruf erfordern?Sollte malloc nicht asynchron sein?

Beispiel: Wenn ich einen kleineren Speicherblock benötige, um Platz für ein Element in der verknüpften Liste zu schaffen, bevorzuge ich das traditionelle Inline-malloc, das es in 99.999% der Fälle erfüllen sollte oder einfach fehlschlägt . Ein anderes Beispiel: Wenn ich ein DB-Server bin, der versucht, einen beträchtlichen Chunk zuzuteilen, um Indizes darin zu setzen, kann ich mich für das async_malloc entscheiden und mit der "Callback-Komplexität" umgehen.

Der Grund, warum ich das heraufgebracht habe, ist, dass ich versuche, hoch gleichzeitige Server zu schaffen, die Hunderttausende von Webanfragen pro Sekunde handhaben und generell Threads für die Bearbeitung der Anfragen vermeiden. Anders ausgedrückt: Wenn I/O auftritt, möchte ich, dass es asynchron ist (sagen wir auf Basis von Libevent). Leider habe ich festgestellt, dass die meisten C-APIs keine Unterstützung für die gleichzeitige Verwendung bieten. Zum Beispiel blockiert die allgegenwärtige MySQL C-Bibliothek vollständig, und das ist nur eine Bibliothek, die meine Server ausgiebig nutzen. Auch hier kann ich die Nichtblockierung immer simulieren, indem ich sie auf einen anderen Thread verschiebe, aber das ist bei weitem nicht so billig wie das Warten auf ein Ergebnis über den Completion-Callback.

+5

Der Aufruf von 'malloc' verursacht nicht automatisch mehr IO. Vielleicht verwirren Sie die Verwendung des zurückgegebenen Speichers im Gegensatz zur Zuweisung des Speichers an Sie. Nur weil Sie nach 100MB fragen, heißt das nicht, dass 'malloc' sofort 100MB Swapping auslöst. Das passiert nur, wenn Sie auf den Speicher zugreifen. – kaylum

+0

C gibt nicht die zeitliche Leistung von 'malloc()' an. Sicherlich ist dies nicht die erste Anwendung, die Timing-Bedenken hat. Ein typisches "malloc()", das in einem Major-OS verwendet wird, vermeidet Blockierungen für lange Zeit und verteilt sie nur bei Verwendung. http://stackoverflow.com/q/19991623/2410359. – chux

Antwort

3

Wie kaylum sagte in einem Kommentar:

malloc Sprech wird nicht von Natur aus mehr IO verursachen. Vielleicht verwirren Sie die Verwendung des zurückgegebenen Speichers im Gegensatz zur Zuweisung des Speichers an Sie. Nur weil Sie nach 100 MB fragen, heißt das nicht, dass malloc sofort 100 MB Swapping auslöst. Das passiert nur, wenn Sie auf den Speicher zugreifen.

Wenn Sie gegen lange Verzögerungen schützen wollen für den Austausch usw. während späteren Zugriff an den zugewiesenen Speicher, können Sie mlock auf sie in einem separaten Thread nennen (so wird Ihr Prozess nicht ins Stocken geraten Warte für mlock zu vervollständigen). Sobald mlock erfolgreich ausgeführt wurde, wird der Speicher physisch instanziiert und kann erst nach munlock ausgelagert werden.

2

Denken Sie daran, dass ein Aufruf von malloc() nicht notwendigerweise dazu führt, dass Ihr Programm das Betriebssystem nach mehr Speicher fragt. Es liegt an der Implementierung von malloc() durch die C-Laufzeitumgebung.

Für Glibc malloc() lediglich (je nachdem, wie viel Sie fragen) gibt einen Zeiger auf den Speicher zurück, den die Laufzeit bereits vom Betriebssystem hat. In ähnlicher Weise gibt free() nicht notwendigerweise Speicher an das Betriebssystem zurück. Es ist viel schneller so. Ich denke glibcs ​​malloc() ist auch threadsicher.

Interessanterweise gibt dies C, C++ (und alles, was darauf aufgebaut ist) die gleichen Eigenschaften, die normalerweise mit Sprachen wie Java und C# verbunden sind. Eine Runtime wie Java oder C# auf einer Runtime wie glibc aufzubauen, bedeutet, dass es tatsächlich mehr Arbeit als nötig gibt, Speicher zu verwalten ... Es sei denn, sie verwenden gar nicht malloc() oder new.

Es gibt verschiedene Allokatoren, und Sie können, was auch immer Sie möchten, in Ihr Programm einbinden, unabhängig davon, was Ihre normale C-Laufzeit bietet. Selbst auf Plattformen wie * BSD (die in ihrem Speicherzuweisungs-Ansatz normalerweise viel traditioneller sind und das Betriebssystem immer dann fragen, wenn Sie malloc() oder new aufrufen) können Sie denselben Trick ausführen.

+0

* Ich denke, glibc malloc() ist thread sicher auch. * Das stimmt. Tatsächlich verwaltet die 'malloc'-Implementierung von glibc eine Thread-lokale (private) Arena für jeden Thread, so dass es fast keine Kollisionen gibt, wenn mehrere Threads gleichzeitig 'malloc' aufrufen. –

1

Anders ausgedrückt, zu jeder Zeit, wenn I/O auftritt, möchte ich, dass es asynchron ist (sagen wir auf Basis von Libevent).

Ich habe schlechte Nachrichten für Sie. Jedes Mal, wenn Sie auf Speicher zugreifen, besteht die Gefahr, dass Sie für E/A blockieren.

malloc selbst ist ziemlich unwahrscheinlich zu blockieren, weil das System ruft es nur einen Eintrag in einer Datenstruktur, die den Kernel "Karte in einigen Speicher hier, wenn es zugegriffen wird" sagt erstellen verwendet. Dies bedeutet, dass malloc nur blockiert, wenn es erforderlich ist, zum Kernel zu gehen, um mehr Speicher zuzuordnen, und entweder der Kernel nicht mehr genügend Arbeitsspeicher hat, so dass er selbst auf die Zuweisung seiner internen Datenstruktur warten muss (Sie können dann eine Weile warten)) oder Sie verwenden mlockall. Das tatsächliche Zuweisen von Speicher, der zu dem Tauschen führen kann, geschieht nicht, bis Sie Speicher berühren. Und Ihr eigener Speicher kann jederzeit ausgelagert werden (oder Ihr Programmtext kann ausgelagert werden) und Sie haben praktisch keine Kontrolle darüber.

Verwandte Themen