En sx.el
, tenemos un caso en el que necesitamos verificar si hemos aprobado GET
o POST
como argumento.
Actualmente tenemos el argumento pasando como una cadena y lo estamos usando (string= "GET" url-method)
para compararlo "GET"
.
¿Hay alguna ventaja de compilación elisp / byte para cambiarlo a un símbolo (equal url-method 'GET)
?
elisp
byte-compilation
Jonathan Leech-Pepin
fuente
fuente
eq
para comparar contra un símbolo.eq
convertirá objetos de Emacsint
y los comparará. Compararint
s es mucho más rápido que compararstring
s.string=
funcionará como se espera, yaurl-method
sea un símbolo o una cadena. OTOH si usaeq
oequal
, debe asegurarse de que los argumentos sean del mismo tipo.Respuestas:
Los nuevos usuarios de Lisp que vienen de otros idiomas a veces usan cadenas para tales fines por costumbre.
Los símbolos se pueden comparar con en
eq
lugar de soloequal
.string=
usa un código similar aequal
, para probar cada carácter hasta que se encuentre una falta de coincidencia. Entonces sí, la comparación de símbolos puede ser un poco más rápida. Si está utilizando la comparación en un bucle, por ejemplo, la diferencia podría ser importante.Además, dependiendo del código particular, a menudo puede hacer que el código sea más simple o más legible para usar símbolos en lugar de cadenas. Y hay funciones (y macros, etc.) que esperan símbolos o que comparan cosas usando
eq
(oeql
) por defecto. Para usar aquellos con cadenas, de todos modos debe convertir a símbolos.fuente
Tenga en cuenta que el lector lisp practica símbolos, de modo que las referencias independientes a un símbolo dado le dan exactamente el mismo objeto lisp , y en consecuencia puede compararlos
eq
(que solo necesita comparar las direcciones de los objetos).Por el contrario, las cadenas independientes son siempre objetos lisp diferentes y, por lo tanto, debe comparar sus contenidos.
Por lo tanto, esperaría que la
eq
comparación gane por rendimiento.Curiosamente (ciertamente estoy muy sorprendido), algunas pruebas triviales
benchmark-run
están dandostring=
la victoria por bastante margen. Esto me parece muy extraño. YMMV?Editar: Así que acabo de notar esta respuesta (y su comentario) nuevamente, y me sentí inspirado para ver si podía recrear y explicar el resultado.
nb Nada se compila en bytes inicialmente.
La primera constatación fue que mis símbolos eran
quote
d y las cadenas no, e inmediatamente descubrí quequote
era el responsable de la mayor parte de la diferencia de velocidad:es, para cadenas más pequeñas, consistentemente más rápido que:
sin embargo, si también citamos la cadena:
eso casi iguala las cosas por completo.
Sin embargo, en promedio, a menos que la cuerda sea bastante grande, la comparación de la cuerda todavía parece ganar por un pelo.
Un enfoque alternativo es vincular los objetos a las variables:
Una vez más, estoy viendo la comparación de cuerdas más rápido por nariz, en promedio.
Después de la compilación de bytes, solo veo un resultado consistente para los casos variables de let-bound, donde
eq
es consistentemente más rápido questring=
(toma alrededor de 2/3 del tiempo).Para los otros ejemplos, obtengo resultados sin sentido (para mí) como que las cadenas entre comillas son más rápidas que las cadenas sin comillas, lo que solo puedo adivinar es efectivamente el ruido de otros aspectos de la ejecución y / o en
benchmark-run
sí mismo. Había suficiente variedad entre diferentes ejecuciones de la misma función para ocultar por completo cualquier diferencia entre ejecuciones de diferentes funciones.Mis conclusiones son:
(a) las
eq
comparaciones con un símbolo pueden (algo contraintuitivamente) ser más lentas que una comparación de cadenas, si se cita el símbolo.(b) A menos que las cadenas sean bastante grandes, las diferencias prácticas son completamente insignificantes, por lo que no me molestaría en convertir una a la otra por razones puramente de rendimiento.
fuente
intern
+eq
contrastring=
. O posiblemente por alguna razón completamente diferente: es imposible saberlo sin ver su código. Debe publicar su código de prueba como una pregunta en este sitio.benchmark-run-compiled
(con la idea de que eso eliminaría el costo deintern
), pero varias veces obtuve resultados negativos. Creo que ambas operaciones son demasiado rápidas para medir de manera confiable.