Discussion:
manejo de cadenas vb.net
(demasiado antiguo para responder)
jorge
2008-02-07 14:51:30 UTC
Permalink
cual es mas eficiente?
dim str as string = "line 1"
str += "line 2"
str += "line 3"
str += "line 4"
str += "line 5"
o
dim str as string = "line 1" + _
"line 2" + _
"line 3" + _
"line 4" + _
"line 5"

o
dim sb as new stringbuilder("line 1")
sb.Append("line 2")
sb.Append("line 3")
sb.Append("line 4")
sb.Append("line 5")

la pregunta viene pq nosotros utilizamos la construccion de sentencias
Select del SQL en los programas y me he dado cuenta que al momento de
depurar existe mucho consumo de variables de tipo string.

gracias de antemano.
Jorge
Jhonny Vargas P.
2008-02-07 14:58:14 UTC
Permalink
Depende... si son muchas concatenaciones sin duda usa StringBuilder.... si
son pocas como las de 5 líneas que tienes... usa un simple string.
--
Saludos,
Jhonny Vargas P.
http://msmvps.com/jvargas
Santiago de Chile
Post by jorge
cual es mas eficiente?
dim str as string = "line 1"
str += "line 2"
str += "line 3"
str += "line 4"
str += "line 5"
o
dim str as string = "line 1" + _
"line 2" + _
"line 3" + _
"line 4" + _
"line 5"
o
dim sb as new stringbuilder("line 1")
sb.Append("line 2")
sb.Append("line 3")
sb.Append("line 4")
sb.Append("line 5")
la pregunta viene pq nosotros utilizamos la construccion de sentencias
Select del SQL en los programas y me he dado cuenta que al momento de
depurar existe mucho consumo de variables de tipo string.
gracias de antemano.
Jorge
Mickel Kurtis
2008-02-19 16:12:27 UTC
Permalink
Sin Dudas la segunda. Siempre que hagas un llamado a una funcion vas a
necesitar mas recursos, pese a que en el ejemplo, serian muy escasos. Y en
el caso que asignes un valor a una variables y luego volver a asignarle un
nuevo valor actualizado, tambien desperdiciarias recursos. Habira que
investigar como queda el codigo compliado para identificar diferencias MSIL.
Saludos
Marcos Beccar Varela
Post by jorge
cual es mas eficiente?
dim str as string = "line 1"
str += "line 2"
str += "line 3"
str += "line 4"
str += "line 5"
o
dim str as string = "line 1" + _
"line 2" + _
"line 3" + _
"line 4" + _
"line 5"
o
dim sb as new stringbuilder("line 1")
sb.Append("line 2")
sb.Append("line 3")
sb.Append("line 4")
sb.Append("line 5")
la pregunta viene pq nosotros utilizamos la construccion de sentencias
Select del SQL en los programas y me he dado cuenta que al momento de
depurar existe mucho consumo de variables de tipo string.
gracias de antemano.
Jorge
Leonardo Azpurua
2008-02-19 20:51:14 UTC
Permalink
Post by Mickel Kurtis
Sin Dudas la segunda. Siempre que hagas un llamado a una funcion vas a
necesitar mas recursos, pese a que en el ejemplo, serian muy escasos. Y en
el caso que asignes un valor a una variables y luego volver a asignarle un
nuevo valor actualizado, tambien desperdiciarias recursos. Habira que
investigar como queda el codigo compliado para identificar diferencias MSIL.
Saludos
Marcos Beccar Varela
Hola, Marcos:

Si todos los valores son constantes, la mejor opcion es sin duda la segunda.
El compilador detecta la concatenación de una serie de constantes y arma una
sola cadena.

La instrucción
s = "T1" & "T2" & "T3" & "T4" & "T5"
es traducida a IL como
IL_0001: ldstr "T1T2T3T4T5"
IL_0006: stloc.0

La primera opción es la peor de todas en cualquier caso, pero apenas un poco
peor que la segunda cuando hay variables en la expresion. Si cambiamos la
original por

s = "T1" & t & "T3" & "T4" & "T5"

IL_0001: ldstr "T2"
IL_0006: stloc.2
IL_0007: ldstr "T1"
IL_000c: ldloc.2
IL_000d: call string [mscorlib]System.String::Concat(string,
string)
IL_0012: ldstr "T3T4T5"
IL_0017: call string [mscorlib]System.String::Concat(string,
string)

resultando casi equivalente a la primera.

En estos casos, lo mejor es siempre usar StringBuilder, que usa un búfer de
caracteres donde realiza la concatenación mediante simple adición al final,
y sólo cuando se llama a la propiedad ToString ensambla la cadena.

Las cadenas en VB y en .NET son áreas dinámicas de memoria que se asignan
según resulta necesario. En la medida en que la serie de concatenaciones
utiliza referencias variables, se producen llamadas a funciones que generan
nuevas cadenas, queluego deben ser manejadas por el colector de basura y
producen perdidas de eficiencia en la llamada y posteriormente demoran los
procesos de recolección.

Como criterio general, cuando se va a realizar una serie de concatenaciones
numerosas (por ejemplo, al armar una sentencia SQL dinámica, o combinar un
patrón de texto con elementos variables para producir algun tipo de
documento) siempre es mejor usar un StringBuilder que cualquier otra cosa.

Salud!
Jhonny Vargas P.
2008-02-20 13:20:35 UTC
Permalink
Que tal Leonardo, suelo chequear de otras maneras algunas instrucciones y
estreso para ver cual es la mejor opción...

Pero me puedes comentar como obtuviste esos valores?... disculpa mi
ignorancia, pero me parece bastante bueno...
--
Saludos,
Jhonny Vargas P.
http://msmvps.com/jvargas
Santiago de Chile

"Leonardo Azpurua" <l e o n a r d o [arroba] m v p s [punto] o r g> escribió
Post by Leonardo Azpurua
Post by Mickel Kurtis
Sin Dudas la segunda. Siempre que hagas un llamado a una funcion vas a
necesitar mas recursos, pese a que en el ejemplo, serian muy escasos. Y
en el caso que asignes un valor a una variables y luego volver a
asignarle un nuevo valor actualizado, tambien desperdiciarias recursos.
Habira que investigar como queda el codigo compliado para identificar
diferencias MSIL.
Saludos
Marcos Beccar Varela
Si todos los valores son constantes, la mejor opcion es sin duda la
segunda. El compilador detecta la concatenación de una serie de constantes
y arma una sola cadena.
La instrucción
s = "T1" & "T2" & "T3" & "T4" & "T5"
es traducida a IL como
IL_0001: ldstr "T1T2T3T4T5"
IL_0006: stloc.0
La primera opción es la peor de todas en cualquier caso, pero apenas un
poco peor que la segunda cuando hay variables en la expresion. Si
cambiamos la original por
s = "T1" & t & "T3" & "T4" & "T5"
IL_0001: ldstr "T2"
IL_0006: stloc.2
IL_0007: ldstr "T1"
IL_000c: ldloc.2
IL_000d: call string [mscorlib]System.String::Concat(string,
string)
IL_0012: ldstr "T3T4T5"
IL_0017: call string [mscorlib]System.String::Concat(string,
string)
resultando casi equivalente a la primera.
En estos casos, lo mejor es siempre usar StringBuilder, que usa un búfer
de caracteres donde realiza la concatenación mediante simple adición al
final, y sólo cuando se llama a la propiedad ToString ensambla la cadena.
Las cadenas en VB y en .NET son áreas dinámicas de memoria que se asignan
según resulta necesario. En la medida en que la serie de concatenaciones
utiliza referencias variables, se producen llamadas a funciones que
generan nuevas cadenas, queluego deben ser manejadas por el colector de
basura y producen perdidas de eficiencia en la llamada y posteriormente
demoran los procesos de recolección.
Como criterio general, cuando se va a realizar una serie de
concatenaciones numerosas (por ejemplo, al armar una sentencia SQL
dinámica, o combinar un patrón de texto con elementos variables para
producir algun tipo de documento) siempre es mejor usar un StringBuilder
que cualquier otra cosa.
Salud!
Leonardo Azpurua
2008-02-20 14:33:19 UTC
Permalink
Post by Jhonny Vargas P.
Que tal Leonardo, suelo chequear de otras maneras algunas instrucciones y
estreso para ver cual es la mejor opción...
Pero me puedes comentar como obtuviste esos valores?... disculpa mi
ignorancia, pero me parece bastante bueno...
Hola, Johnny:

Hice un programita de prueba y abrí el ejecutable con ILDASM.EXE.

Lo de comparar las operaciones de concatención contra el uso de
StringBuilder lo hice hace mucho tiempo con un programa parecido a esto:

Sub Main
Dim s as String = "", t as Single, i as Integer
t = Timer()
For i = 1 to 30000
s = s & Chr(65 + i MOD 26)
Next
WL("30000 concantenaciones tardaron {0} segundos", Timer() - t)
s = ""
t = Timer()
Dim b As New System.Text.StringBuilder()
For i = 1 to 30000
b.Append(Chr(65 + i MOD 26))
Next
s = b.ToString
WL("30000 Appends tardaron {0} segundos", Timer() - t)
RL()
End Sub

WL y RL son dos "atajos" que implementa SnippetCompiler en el esqueleto de
código, equivalen a Console.WriteLine y Console.ReadLine.

Los resultados fueron estos:

30000 concantenaciones tardaron 0,390625 segundos
30000 Appends tardaron 0 segundos

y al subir la cantidad de operaciones a 100000, la diferencia es aun más
dramática:

100000 concantenaciones tardaron 12,875 segundos
100000 Appends tardaron 0 segundos

La perdida de eficiencia en las concatenaciones tiende a ser exponencial,
10K tardan 0.046875 seg., 30K no tardan el triple, sino 0,390625, es decir 8
veces más. Y 100K tarda no 3,3 veces más que 30K, sino 32,96.

La diferencia está dada por que cada vez que ejecutamos una concatenación
hay que crear una nueva cadena, una operación relativamente exigente. Lo
peor del uso excesivo de concatenaciones es que va "embasurando" la memoria,
haciendo necesarias intervenciones más frecuentes del colector de basura.

La conclusión evidente es que habría que usar StringBuilder en vez del
operador de concatenación, salvo en los casos más triviales.

Salud!
Jhonny Vargas P.
2008-02-20 21:00:23 UTC
Permalink
"Leonardo Azpurua" <l e o n a r d o [arroba] m v p s [punto] o r g> escribió
Post by Leonardo Azpurua
Post by Jhonny Vargas P.
Que tal Leonardo, suelo chequear de otras maneras algunas instrucciones y
estreso para ver cual es la mejor opción...
Pero me puedes comentar como obtuviste esos valores?... disculpa mi
ignorancia, pero me parece bastante bueno...
Hice un programita de prueba y abrí el ejecutable con ILDASM.EXE.
Excelente... gracias
Post by Leonardo Azpurua
Lo de comparar las operaciones de concatención contra el uso de
Sub Main
Dim s as String = "", t as Single, i as Integer
t = Timer()
For i = 1 to 30000
s = s & Chr(65 + i MOD 26)
Next
WL("30000 concantenaciones tardaron {0} segundos", Timer() - t)
s = ""
t = Timer()
Dim b As New System.Text.StringBuilder()
For i = 1 to 30000
b.Append(Chr(65 + i MOD 26))
Next
s = b.ToString
WL("30000 Appends tardaron {0} segundos", Timer() - t)
RL()
End Sub
WL y RL son dos "atajos" que implementa SnippetCompiler en el esqueleto de
código, equivalen a Console.WriteLine y Console.ReadLine.
30000 concantenaciones tardaron 0,390625 segundos
30000 Appends tardaron 0 segundos
y al subir la cantidad de operaciones a 100000, la diferencia es aun más
100000 concantenaciones tardaron 12,875 segundos
100000 Appends tardaron 0 segundos
La perdida de eficiencia en las concatenaciones tiende a ser exponencial,
10K tardan 0.046875 seg., 30K no tardan el triple, sino 0,390625, es decir
8 veces más. Y 100K tarda no 3,3 veces más que 30K, sino 32,96.
La diferencia está dada por que cada vez que ejecutamos una concatenación
hay que crear una nueva cadena, una operación relativamente exigente. Lo
peor del uso excesivo de concatenaciones es que va "embasurando" la
memoria, haciendo necesarias intervenciones más frecuentes del colector de
basura.
La conclusión evidente es que habría que usar StringBuilder en vez del
operador de concatenación, salvo en los casos más triviales.
Efectivamente también había realizado algo similar hace algún tiempo...
mientras sean pocas concatenaciones es más rapido un simple "&"... pero
cuando haces cantidad de operaciones gigantescas la curva comienza a
inclinarse a favor del stringbuilder.. por eso concuerdo contigo y mientras
más operaciones la diferencia es notable..

Gracias!

Saludos,
Jhonny Vargas P.

Continúe leyendo en narkive:
Loading...