Ich habe festgestellt, dass das Anrufen zu viele Male nicht so intelligent sein wird.
Wie haben Sie es herausgefunden? Denn der einzige Weg, um wirklich zu wissen, ist die Leistung zu messen.
Ihre Strategie muss möglicherweise davon abweichen, wie Sie die Daten vom Benutzer lesen. Wenn Sie getchar()
verwenden, möchten Sie wahrscheinlich realloc()
nicht verwenden, um die Puffergröße bei jedem Lesen eines Zeichens um ein Zeichen zu erhöhen. Eine gute realloc()
wird jedoch viel weniger ineffizient sein als Sie selbst unter diesen Umständen denken. Die minimale Blockgröße, die glibc Ihnen als Antwort auf eine malloc()
tatsächlich geben wird, ist, glaube ich, 16 Bytes. Wenn Sie also von 0 bis 16 Zeichen wechseln und jedes Mal neu zuweisen, müssen Sie nicht kopieren. In ähnlicher Weise muss für größere Umverteilungen möglicherweise kein neuer Block zugewiesen werden, es kann möglich sein, den vorhandenen Block größer zu machen. Vergessen Sie nicht, dass realloc()
sogar bei seiner langsamsten Geschwindigkeit schneller ist, als eine Person eingeben kann.
Die meisten Leute gehen nicht für diese Strategie. Was eingegeben werden kann, kann piped werden, so dass das Argument, dass Leute nicht sehr schnell tippen, nicht unbedingt funktioniert. Normalerweise führen Sie das Konzept der Kapazität ein. Sie ordnen einen Puffer mit einer bestimmten Kapazität zu und wenn er voll ist, erhöhen Sie seine Kapazität (mit), indem Sie einen neuen Block einer bestimmten Größe hinzufügen. Die Anfangsgröße und die Neuzuordnungsgröße können auf verschiedene Arten abgestimmt werden. Wenn Sie Benutzereingaben lesen, können Sie sich für kleine Werte entscheiden, z. 256 Byte, wenn Sie Dateien von der Festplatte oder über das Netzwerk lesen, könnten Sie nach größeren Werten suchen, z. 4 KB oder größer.
Die Inkrementgröße muss nicht einmal konstant sein. Sie können die Größe für jede erforderliche Neuzuweisung verdoppeln. Dies ist die Strategie einiger Programmierbibliotheken. Zum Beispiel verwendet die Java-Implementierung einer Hash-Tabelle, glaube ich, und so möglicherweise die Cocoa-Implementierung eines Arrays.
Es ist unmöglich vorher zu wissen, was die beste Strategie in einer bestimmten Situation ist. Ich würde etwas auswählen, das sich richtig anfühlt, und dann, wenn die Anwendung Leistungsprobleme hat, würde ich testen, um es abzustimmen. Ihr Code muss nicht so schnell wie möglich sein, aber nur schnell genug.
Jedoch eine Sache, die ich absolut nicht tun würde, überlagert einen Home Rolled Memory-Algorithmus über den integrierten Zuordner. Wenn Sie feststellen, dass Sie eine Liste der Blöcke verwalten, die Sie nicht verwenden, anstatt sie zu befreien, tun Sie es falsch. Das hat OpenSSL in Schwierigkeiten gebracht.
Ja, dies wird Speicherpool genannt, und im Allgemeinen ist es eine gute Idee. – arrowd
Möglicherweise kann es besser sein, die Größe Ihres Puffers zu verdoppeln, anstatt ihn um einen festgelegten Betrag zu vergrößern. – silel
Was optimieren Sie, Geschwindigkeit oder Speicherverbrauch? Wenn Sie 100MB im Voraus reservieren, müssen Sie fast nie 'realloc' aufrufen. Könnte der Schnellste sein. –