Necesito dividir el contenido de un búfer en una lista de cadenas. El carácter nulo se usa para separar los elementos.
Si los elementos estaban separados por caracteres de nueva línea, entonces podría usar el mismo enfoque que 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))
Supongo que forward-line
es eficiente, pero el uso de line-beginning-position
y line-end-position
es un poco sospechoso. Pero como se usa el carácter nulo, no puedo hacerlo de todos modos.
Una forma de hacerlo sería:
(split-string (buffer-string) "\0")
También estaba considerando esta variación:
(split-string (buffer-substring-no-properties (point-min)
(point-max))
"\0")
¿Es eso realmente más eficiente? El texto en el búfer no es propiedad, pero me imagino que buscar las propiedades inexistentes aún agregaría una sobrecarga.
En lugar de leer el búfer en una cadena y luego dividir la cadena, me gustaría trabajar directamente en el búfer, asumiendo nuevamente que eso es realmente más eficiente.
(let ((beg (point))
items)
(while (search-forward "\0" nil t)
(push (buffer-substring-no-properties beg (1- (point))) items)
(setq beg (point)))
(nreverse items))
¿Existe algo así search-forward-char
y sería eso más eficiente que search-forward
?
Supongo que podría usar:
(while (not (= (char-after) ?\0)) (forward-char))
Pero esperaría que estuviera disponible como una función si fuera más eficiente que search-forward
.
fuente
(skip-chars-forward "^\0")
Debería hacer el trabajo.(search-forward "\0" nil t)
en mi máquina.(split-string (buffer-substring-no-properties) "\0")
variante gane. Además, el rendimiento puede depender de la estructura del texto. (¿Hay muchas fichas cortas terminadas por caracteres nulos o hay fichas grandes con solo unos pocos caracteres nulos?)char-after
puede volvernil
.0
el cuello de botella de tu aplicación es realmente antes de cavar tan profundo?Respuestas:
He ejecutado los siguientes puntos de referencia en
sin personalizaciones, es decir, iniciando Emacs con la
-Q
bandera.Como @Tobias señala correctamente en un comentario , es una alternativa más rápida a la
search-forward
búsqueda de un solo personajeskip-chars-forward
. Algunos puntos de referencia siguen.Carácter nulo al final del búfer
da
Largas líneas terminadas en nulo
da
Líneas cortas terminadas en nulo
da
Tenga en cuenta que la menor diferencia de tiempo con líneas cortas probablemente se deba a la mayor complejidad del bucle de la prueba (b). Además, la inversión de la dirección de la búsqueda (es decir, utilizando
point-max
,skip-chars-backward
,bobp
, ybackward-char
) no hace ninguna diferencia notable.Veamos:
da
así que no hay diferencia en un búfer sin propiedad Tenga en cuenta que tuve que colocar la llamada
buffer-string
en una función separada de compilación de bytes, de lo contrario, se habría optimizado a una constante debajobenchmark-run-compiled
.Vamos a revisar. Las siguientes tres funciones deberían dar el mismo resultado:
Carácter nulo al final del búfer
da
Largas líneas terminadas en nulo
da
Líneas cortas terminadas en nulo
da
Entonces, probablemente pueda obtener una aceleración de ~ 2x usando
skip-chars-{forward,backward}
, pero como señala @Tobias , ¿vale la pena la complejidad adicional?fuente