¿Sabías que en los procesadores x86 es más eficiente hacer x ^= x
donde x es un entero de 32 bits, que hacer x = 0
? Es cierto, y por supuesto tiene el mismo resultado. Por lo tanto, cada vez que se puede ver x = 0
en el código, uno puede reemplazarlo por x ^= x
y ganar eficiencia.
¿Alguna vez ha visto x ^= x
en muchos códigos?
La razón por la que no lo ha hecho no es solo porque la ganancia de eficiencia es leve, sino porque este es precisamente el tipo de cambio que un compilador (si compila a código nativo) o jitter (si compila IL o similar) hará . Desmontar algunos códigos x86 y no es inusual ver el ensamblaje equivalente a x ^= x
, aunque el código que se compiló para hacer esto casi seguro tenía x = 0
o quizás algo mucho más complicado como x = 4 >> 6
o x = 32 - y
donde el análisis del código muestra que y
siempre contendrá 32
en este punto, y así sucesivamente.
Por esta razón, a pesar de que x ^= x
se sabe que es más eficiente, la única efecto de que en la gran mayoría de los casos, sería hacer que el código menos legible (la única excepción sería donde no hacer x ^= y
estaba implicado en un algoritmo que se usaba y estábamos haciendo un caso donde x
y y
eran lo mismo aquí, en este caso x ^= x
haría más claro el uso de ese algoritmo, mientras que x = 0
lo ocultaría).
En 99.999999 por ciento de casos, lo mismo se aplicará a su ejemplo. En el 0 restante.000001% de casos que debería, pero existe una diferencia de eficiencia entre algún tipo extraño de operador que reemplaza y, el compilador no puede resolver el uno al otro. De hecho, 0.000001% exagera el caso, y solo lo menciono porque estoy bastante seguro de que si lo hubiera intentado lo suficiente podría escribir algo donde uno sea menos eficiente que el otro. Normalmente las personas no se esfuerzan por hacerlo.
Si alguna vez mira su propio código en reflector, probablemente encontrará algunos casos en los que se ve muy diferente al código que escribió. La razón de esto es que es la ingeniería inversa de la IL de su código, en lugar de su código en sí, y de hecho una cosa que a menudo encontrará es if(var == true)
o if(var != false)
convirtiéndose en if(var)
o incluso en if(!var)
con if
y else
bloques invertidos.
Mire más profundo y verá que aún se realizan más cambios ya que hay más de una manera de desollar al mismo gato. En particular, es interesante observar cómo se convierten las declaraciones switch
a IL; a veces se convierte en el equivalente a un montón de declaraciones if-else if
, y a veces se convierte en una búsqueda en una tabla de saltos que podrían realizarse, dependiendo de lo que parezca más eficiente en el caso en cuestión.
Mire más profundamente y se realizan otros cambios cuando se compila en código nativo.
No voy a estar de acuerdo con aquellos que hablan de "optimización prematura" solo porque pregunta sobre la diferencia de rendimiento entre dos enfoques diferentes, porque el conocimiento de tales diferencias es algo bueno, solo usa ese conocimiento prematuramente es prematuro (por definición). Pero un cambio que se compilará no es ni prematuro ni una optimización, es solo un cambio nulo.
"eventualmente usará suficientes declaraciones if para que importe". bastante seguro de que no lo harás –
"la optimización prematura es la raíz de todo mal" –
La optimización prematura es la raíz de todos los males –