saber para miner minar minando minado esta equipo eliminar criptomonedas con computadoras como coin bitcoins c# .net stringbuilder

c# - para - eliminar virus bitcoin miner



¿Estoy minando la eficiencia de StringBuilder? (10)

Aparte de un poco de sobrecarga, personalmente no veo ningún problema con él. Definitivamente más legible. Mientras vea un número razonable de parámetros, no veo el problema.

Empecé a usar StringBuilder con preferencia a la concatenación directa, pero parece que falta un método crucial. Entonces, lo implementé yo mismo, como una extensión:

public void Append(this StringBuilder stringBuilder, params string[] args) { foreach (string arg in args) stringBuilder.Append(arg); }

Esto convierte el siguiente lío:

StringBuilder sb = new StringBuilder(); ... sb.Append(SettingNode); sb.Append(KeyAttribute); sb.Append(setting.Name);

Dentro de esto:

sb.Append(SettingNode, KeyAttribute, setting.Name);

Podría usar sb.AppendFormat("{0}{1}{2}",... , pero esto parece incluso menos preferido, y aún más difícil de leer. ¿Es mi extensión un buen método, o de alguna manera socava los beneficios? de StringBuilder ? No estoy tratando de optimizar nada de forma prematura, ya que mi método tiene más que ver con la legibilidad que con la velocidad, pero también me gustaría saber que no me estoy disparando en el pie.


Chris

Inspirado por esta respuesta de Jon Skeet (segunda respuesta), reescribí un poco su código. Básicamente, agregué el método TestRunner que ejecuta la función pasada e informa el tiempo transcurrido, eliminando un poco de código redundante. No para ser presumido, sino más bien como un ejercicio de programación para mí. Espero que sea de ayuda.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; namespace SBTest { class Program { private static void Main(string[] args) { // JIT everything AppendTest(1); AppendFormatTest(1); int iterations = 1000000; // Run Tests TestRunner(AppendTest, iterations); TestRunner(AppendFormatTest, iterations); Console.ReadLine(); } private static void TestRunner(Func<int, long> action, int iterations) { GC.Collect(); var sw = Stopwatch.StartNew(); long length = action(iterations); sw.Stop(); Console.WriteLine("--------------------- {0} -----------------------", action.Method.Name); Console.WriteLine("iterations: {0:n0}", iterations); Console.WriteLine("milliseconds: {0:n0}", sw.ElapsedMilliseconds); Console.WriteLine("output length: {0:n0}", length); Console.WriteLine(""); } private static long AppendTest(int iterations) { var sb = new StringBuilder(); for (var i = 0; i < iterations; i++) { sb.Append("TEST" + i.ToString("00000"), "TEST" + (i + 1).ToString("00000"), "TEST" + (i + 2).ToString("00000")); } return sb.Length; } private static long AppendFormatTest(int iterations) { var sb = new StringBuilder(); for (var i = 0; i < iterations; i++) { sb.AppendFormat("{0}{1}{2}", "TEST" + i.ToString("00000"), "TEST" + (i + 1).ToString("00000"), "TEST" + (i + 2).ToString("00000")); } return sb.Length; } } public static class SBExtentions { public static void Append(this StringBuilder sb, params string[] args) { foreach (var arg in args) sb.Append(arg); } } }

Aquí está la salida:

--------------------- AppendTest ----------------------- iterations: 1,000,000 milliseconds: 1,274 output length: 29,700,006 --------------------- AppendFormatTest ----------------------- iterations: 1,000,000 milliseconds: 1,381 output length: 29,700,006


Desde una perspectiva de claridad, su extensión está bien.

Probablemente sería mejor utilizar el formato .append (x) .append (y) .append (z) si nunca tiene más de aproximadamente 5 o 6 elementos.

El mismo StringBuilder solo le reportaría una ganancia de rendimiento si estuviera procesando muchos miles de elementos. Además, estará creando la matriz cada vez que llame al método.

Así que si lo haces por claridad, está bien. Si lo está haciendo por eficiencia, probablemente esté en el camino equivocado.


En última instancia, todo se reduce a lo que se traduce en menos creación de cadenas. Tengo la sensación de que la extensión resultará en un mayor conteo de cadenas que utilizando el formato de cadena. Pero el rendimiento probablemente no será tan diferente.


Es un poco de sobrecarga crear la matriz extra, pero dudo que sea mucho. Usted debe medir

Si resulta que la sobrecarga de crear matrices de cadenas es significativa, puede mitigarlo con varias sobrecargas, una para dos parámetros, una para tres, una para cuatro, etc. ... de modo que solo cuando llegue a un número mayor de los parámetros (por ejemplo, seis o siete) necesitarán crear la matriz. Las sobrecargas serían así:

public void Append(this builder, string item1, string item2) { builder.Append(item1); builder.Append(item2); } public void Append(this builder, string item1, string item2, string item3) { builder.Append(item1); builder.Append(item2); builder.Append(item3); } public void Append(this builder, string item1, string item2, string item3, string item4) { builder.Append(item1); builder.Append(item2); builder.Append(item3); builder.Append(item4); } // etc

Y luego una sobrecarga final usando params , por ejemplo

public void Append(this builder, string item1, string item2, string item3, string item4, params string[] otherItems) { builder.Append(item1); builder.Append(item2); builder.Append(item3); builder.Append(item4); foreach (string item in otherItems) { builder.Append(item); } }

Sin duda, espero que estos (o simplemente su método de extensión original) sean más rápidos que usar AppendFormat , que necesita analizar la cadena de formato, después de todo.

Tenga en cuenta que no hice que estas sobrecargas se llamaran entre sí de forma pseudo-recursiva; sospecho que estarían en línea, pero si no fueran la sobrecarga de configurar un nuevo marco de pila, etc. podría terminar siendo significativo. (Asumimos que la sobrecarga de la matriz es significativa, si llegamos hasta aquí).


No diría que está socavando su eficiencia, pero es posible que esté haciendo algo ineficiente cuando se dispone de un método más eficiente. AppendFormat es lo que creo que quieres aquí. Si la cadena {0} {1} {2} que se usa constantemente es demasiado fea, tiendo a poner mis cadenas de formato en consts anteriores, por lo que el aspecto sería más o menos el mismo que su extensión.

sb.AppendFormat(SETTING_FORMAT, var1, var2, var3);


No he probado recientemente, pero en el pasado, StringBuilder era en realidad más lento que la concatenación de cuerdas de vainilla simple ("este" + "ese") hasta que llegas a unas 7 concatenaciones.

Si se trata de una concatenación de cadenas que no está ocurriendo en un bucle, es posible que desee considerar si debería utilizar StringBuilder. (En un bucle, empiezo a preocuparme por las asignaciones con concatenación de cadenas de vainilla simple, ya que las cadenas son inmutables).


No veo ningún problema con su extensión. Si funciona para ti, todo está bien.

Yo prefiero

sb.Append(SettingNode) .Append(KeyAttribute) .Append(setting.Name);


Potencialmente incluso más rápido, ya que realiza en la mayoría de un paso de reasignación / copia, para muchos apéndices.

public void Append(this StringBuilder stringBuilder, params string[] args) { int required = stringBuilder.Length; foreach (string arg in args) required += arg.Length; if (stringBuilder.Capacity < required) stringBuilder.Capacity = required; foreach (string arg in args) stringBuilder.Append(arg); }


Preguntas como esta siempre pueden ser respondidas con un caso de prueba simple.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; namespace SBTest { class Program { private const int ITERATIONS = 1000000; private static void Main(string[] args) { Test1(); Test2(); Test3(); } private static void Test1() { var sw = Stopwatch.StartNew(); var sb = new StringBuilder(); for (var i = 0; i < ITERATIONS; i++) { sb.Append("TEST" + i.ToString("00000"), "TEST" + (i + 1).ToString("00000"), "TEST" + (i + 2).ToString("00000")); } sw.Stop(); Console.WriteLine("Testing Append() extension method..."); Console.WriteLine("--------------------------------------------"); Console.WriteLine("Test 1 iterations: {0:n0}", ITERATIONS); Console.WriteLine("Test 1 milliseconds: {0:n0}", sw.ElapsedMilliseconds); Console.WriteLine("Test 1 output length: {0:n0}", sb.Length); Console.WriteLine(""); } private static void Test2() { var sw = Stopwatch.StartNew(); var sb = new StringBuilder(); for (var i = 0; i < ITERATIONS; i++) { sb.Append("TEST" + i.ToString("00000")); sb.Append("TEST" + (i+1).ToString("00000")); sb.Append("TEST" + (i+2).ToString("00000")); } sw.Stop(); Console.WriteLine("Testing multiple calls to Append() built-in method..."); Console.WriteLine("--------------------------------------------"); Console.WriteLine("Test 2 iterations: {0:n0}", ITERATIONS); Console.WriteLine("Test 2 milliseconds: {0:n0}", sw.ElapsedMilliseconds); Console.WriteLine("Test 2 output length: {0:n0}", sb.Length); Console.WriteLine(""); } private static void Test3() { var sw = Stopwatch.StartNew(); var sb = new StringBuilder(); for (var i = 0; i < ITERATIONS; i++) { sb.AppendFormat("{0}{1}{2}", "TEST" + i.ToString("00000"), "TEST" + (i + 1).ToString("00000"), "TEST" + (i + 2).ToString("00000")); } sw.Stop(); Console.WriteLine("Testing AppendFormat() built-in method..."); Console.WriteLine("--------------------------------------------"); Console.WriteLine("Test 3 iterations: {0:n0}", ITERATIONS); Console.WriteLine("Test 3 milliseconds: {0:n0}", sw.ElapsedMilliseconds); Console.WriteLine("Test 3 output length: {0:n0}", sb.Length); Console.WriteLine(""); } } public static class SBExtentions { public static void Append(this StringBuilder sb, params string[] args) { foreach (var arg in args) sb.Append(arg); } } }

En mi PC, la salida es:

Testing Append() extension method... -------------------------------------------- Test 1 iterations: 1,000,000 Test 1 milliseconds: 1,080 Test 1 output length: 29,700,006 Testing multiple calls to Append() built-in method... -------------------------------------------- Test 2 iterations: 1,000,000 Test 2 milliseconds: 1,001 Test 2 output length: 29,700,006 Testing AppendFormat() built-in method... -------------------------------------------- Test 3 iterations: 1,000,000 Test 3 milliseconds: 1,124 Test 3 output length: 29,700,006

Por lo tanto, su método de extensión es solo un poco más lento que el método Append () y un poco más rápido que el método AppendFormat (), pero en los 3 casos, la diferencia es completamente trivial para preocuparse. Por lo tanto, si su método de extensión mejora la legibilidad de su código, ¡úselo!