Ich muss den Inhalt eines Puffers in eine Liste von Zeichenfolgen aufteilen. Das Nullzeichen wird verwendet, um die Elemente zu trennen.
Wenn die Elemente durch Zeilenumbrüche getrennt wurden, konnte ich den gleichen Ansatz verwenden wie process-lines
:
(let (lines)
(while (not (eobp))
(setq lines (cons (buffer-substring-no-properties
(line-beginning-position)
(line-end-position))
lines))
(forward-line 1))
(nreverse lines))
Ich gehe davon aus, dass forward-line
es effizient ist, aber die Verwendung von line-beginning-position
und line-end-position
ist ein bisschen verdächtig. Aber da das Nullzeichen verwendet wird, kann ich das sowieso nicht tun.
Eine Möglichkeit wäre:
(split-string (buffer-string) "\0")
Ich habe auch über diese Variante nachgedacht:
(split-string (buffer-substring-no-properties (point-min)
(point-max))
"\0")
Ist das eigentlich effizienter? Der Text im Puffer ist nicht geeignet, aber ich würde mir vorstellen, dass das Suchen nach nicht vorhandenen Eigenschaften immer noch einen Overhead verursachen würde.
Anstatt den Puffer in eine Zeichenfolge einzulesen und dann die Zeichenfolge aufzuteilen, möchte ich stattdessen direkt am Puffer arbeiten - wiederum unter der Annahme, dass dies tatsächlich effizienter ist.
(let ((beg (point))
items)
(while (search-forward "\0" nil t)
(push (buffer-substring-no-properties beg (1- (point))) items)
(setq beg (point)))
(nreverse items))
Gibt es so etwas search-forward-char
und wäre das effizienter als search-forward
?
Ich nehme an, ich könnte verwenden:
(while (not (= (char-after) ?\0)) (forward-char))
Aber ich würde erwarten, dass das als Funktion verfügbar ist, wenn es effizienter wäre als search-forward
.
quelle
(skip-chars-forward "^\0")
sollte den Job machen.(search-forward "\0" nil t)
auf meiner Maschine.(split-string (buffer-substring-no-properties) "\0")
gewinnt also die Variante. Darüber hinaus kann die Leistung von der Struktur des Textes abhängen. (Gibt es viele kurze Token, die mit Nullzeichen abgeschlossen sind, oder gibt es große Token mit nur wenigen Nullzeichen?)char-after
kannnil
.0
wirklich der Engpass Ihrer Anwendung ist, bevor Sie so tief gegraben haben?Antworten:
Ich habe die folgenden Benchmarks durchgeführt
ohne Anpassungen, dh indem Emacs mit der
-Q
Flagge gestartet wird .Wie @Tobias in einem Kommentar richtig hervorhebt , ist eine schnellere Alternative zur
search-forward
Suche nach einem einzelnen Zeichenskip-chars-forward
. Einige Benchmarks folgen.Nullzeichen am Pufferende
gibt
Lange nullterminierte Zeilen
gibt
Kurze nullterminierte Zeilen
gibt
Es ist zu beachten, dass der geringere Zeitunterschied bei kurzen Leitungen wahrscheinlich auf die höhere Schleifenkomplexität von Test (b) zurückzuführen ist. Darüber hinaus die Richtung der Suche Umkehren (dh mit
point-max
,skip-chars-backward
,bobp
, undbackward-char
) macht keinen spürbaren Unterschied.Wir werden sehen:
gibt
also kein Unterschied in einem nicht propertisierten Puffer. Beachten Sie, dass ich den Aufruf von
buffer-string
in eine separate bytekompilierte Funktion stellen musste, sonst wäre er auf eine Konstante unter optimiert wordenbenchmark-run-compiled
.Lass uns nachsehen. Die folgenden drei Funktionen sollten das gleiche Ergebnis liefern:
Nullzeichen am Pufferende
gibt
Lange nullterminierte Zeilen
gibt
Kurze nullterminierte Zeilen
gibt
Sie können also wahrscheinlich eine ~ 2-fache
skip-chars-{forward,backward}
Beschleunigung erzielen, wenn Sie verwenden , aber wie @Tobias hervorhebt , ist es die zusätzliche Komplexität wert?quelle