c# - example - path combine asp net
¿Por qué System.IO.Path.Combine tiene 4 sobrecargas? (6)
¿Qué pasa con shugar sintáctico para idiomas que no admiten algo similar a la palabra clave c # - "params"
Actualizar
Se eliminó el problema de rendimiento ya que solo medí la versión de 4 parámetros, pero no la versión de 3 y 2 parámetros que son realmente más rápidas
El rendimiento no es la razón. (Ver mi punto de referencia a continuación)
Punto de referencia
Medí el rendimiento. Para mi sorpresa, la versión array fue ligeramente mejor.
[TestMethod]
public void MeasurePathPerfomance()
{
// repeat several times to avoid jit-issues
for (int j = 0; j < 10; j++)
{
{
DateTime start = DateTime.Now;
string result;
for (int i = 0; i < 30000; i++)
{
result = System.IO.Path.Combine("a", "b", "c", "d"); // use 4 parameter version
}
TimeSpan spend = DateTime.Now - start;
System.Console.WriteLine("4 param : {0}", spend.TotalMilliseconds);
}
{
DateTime start = DateTime.Now;
string result;
for (int i = 0; i < 30000; i++)
{
result = System.IO.Path.Combine(new string[] { "a", "b", "c", "d" });
}
TimeSpan spend = DateTime.Now - start;
System.Console.WriteLine("array[4] param : {0}", spend.TotalMilliseconds);
}
}
}
resultado
4 param : 10.001
array[4] param : 9.0009
4 param : 12.0012
array[4] param : 8.0008
4 param : 12.0012
array[4] param : 10.001
4 param : 11.0011
array[4] param : 9.0009
4 param : 11.0011
array[4] param : 11.0011
4 param : 11.0011
array[4] param : 9.0009
4 param : 10.001
array[4] param : 8.0008
4 param : 10.001
array[4] param : 9.0009
4 param : 11.0011
array[4] param : 9.0009
4 param : 11.0011
array[4] param : 9.0009
En .NET 4, System.IO.Path tiene las siguientes sobrecargas para el método Combine
:
public static string Combine(params string[] paths)
public static string Combine(string path1, string path2)
public static string Combine(string path1, string path2, string path3)
public static string Combine(string path1, string path2, string path3, string path4)
El primero se agregó en .NET 4 para admitir cualquier número de argumentos de ruta. El segundo ya estaba allí en versiones anteriores, así que supongo que se mantiene por compatibilidad con versiones anteriores.
Pero tengo curiosidad por saber cuál es el uso de las otras sobrecargas. ¿Estos casos de uso ya no están cubiertos por la primera firma de método con params
?
edición: ahora creo que la respuesta es "porque no todos los idiomas tienen soporte de params
(y no es conveniente pasar una matriz sin el soporte de parámetros)". Sin embargo, la mente de la colmena de stackoverflow parece estar en desacuerdo. Por lo tanto, como compromiso, no estoy aceptando ninguna respuesta.
Creo que la razón es que la mayoría de los programadores usan uno, dos, tres o cuatro valores para combinar y más que eso, usted desea pensar que es mejor implementar una matriz en lugar de usar más valores.
Ejemplo
Sum(a , b); //fine
Sum(a , b , c);//fine
Sum(a , b , c , d);//fine
Sum(a , b , c , d ,....); //now I think you think everyone think even Microsoft also thinks, its better to implement array here
// something like this
Sum(params var[] n);
Así que encontrarás que la mayor parte del método contiene 1,2,3,4 argumentos y luego params
Es solo por el rendimiento, el rendimiento de los últimos 3 es mayor que el primer método.
Si desea conocer la implementación, simplemente mscorlib con reflector, verá que el rendimiento será mejor en las últimas 3 funciones
La compatibilidad hacia atrás es la mejor razón que se me ocurre. Las sobrecargas probablemente están llamando al primer método.
Sospecharía de rendimiento, ya que tiene que crear una matriz intermedia con parámetros, más la sobrecarga de atravesar la matriz, etc. Probablemente hay algunos casos internos, etc., en los que existe un buen caso para usar las versiones de parámetros numerados fijos.
Actualizar
Ahora he realizado pruebas de rendimiento para verificar mis suposiciones. Esto es algo que debería haber hecho en primer lugar: rompí mi propio mantra de desempeño:
No pienses - mide.
Mis suposiciones no son del todo correctas, pero no del todo equivocadas. La versión de 4 parámetros fijos es ligeramente más lenta que la versión de 4 parámetros, pero las variaciones fijas de 3 y 2 funcionan significativamente mejor.
Hay una serie de problemas con el arnés de prueba de rendimiento para la respuesta aceptada actual que indica que el rendimiento va totalmente a favor de la versión params. Esto es incorrecto:
- Utiliza DateTime. Ahora para el cronometraje. Siempre use un Cronómetro para realizar micro evaluaciones comparativas como DatTime. Ahora solo es preciso entre ~ 10ms-> 15ms. Hay un sinfín de artículos sobre esto .
- La prueba solo cubre el caso de la versión de 4 parámetros. ¿Qué pasa con las versiones de 3 y 2 parámetros?
- La generación y recolección de basura no son tomadas en consideración. Un método puede ser más rápido en una línea recta entre A-> B, pero también puede generar una gran cantidad de basura que tendrá que limpiarse en algún momento. Esta es una penalización de rendimiento diferida, pero sigue siendo un impacto en el rendimiento, por lo que debe tenerse en cuenta.
- Asegúrese de que los argumentos tengan valores realistas: ¿es realista combinar rutas de un solo carácter?
Tengo los siguientes resultados de desempeño, los cuales incluí variaciones de 2, 3 y 4 argumentos donde se puede ver que el desempeño es significativamente mejor para 2 y 3 variaciones, y marginalmente peor para las 4 variaciones. Sin embargo, las versiones de argumento de número fijo son más rápidas en general, siendo 3 la más significativa en términos de esta pregunta (la variación de 2 argumentos existió desde .Net 1.1).
***2 Args***
params2:3018.44ms
params2:3007.61ms
params2:2988.52ms
params2:2992.33ms
params2:2995.89ms
args2 :1724.83ms
args2 :1723.97ms
args2 :1727.76ms
args2 :1720.42ms
args2 :1718.24ms
***3 Args***
params3:4168.37ms
params3:4169.61ms
params3:4165.63ms
params3:4161.51ms
params3:4153.61ms
args3 :3476.96ms
args3 :3483.40ms
args3 :3482.49ms
args3 :3595.15ms
args3 :3561.11ms
***4 Args***
params4:4992.71ms
params4:4985.51ms
params4:4995.63ms
params4:5002.47ms
params4:4993.99ms
args4 :4993.02ms
args4 :4992.93ms
args4 :4991.07ms
args4 :4993.04ms
args4 :4995.14ms
Prueba:
public void MeasurePathPerformance()
{
const int TestIterations = 5;
const string Root = "C://xxxxxxxxxx";
string seg = new string(''x'', 10);
string path = null;
Action<string, Func<double>> test = (name, action) =>
{
for (int i = 0; i < TestIterations; i++)
{
Console.WriteLine("{0}:{1:F2}ms", name, action());
}
};
Console.WriteLine("***2 Args***");
Action p2 = () => path = Path.Combine(new[] { Root, seg });
test("params2", () => TimeTest(p2));
Action a2 = () => path = Path.Combine(Root, seg);
test("args2 ", () => TimeTest(a2));
Console.WriteLine("***3 Args***");
Action p3 = () => path = Path.Combine(new[] { Root, seg, seg });
test("params3", () => TimeTest(p3));
Action a3 = () => path = Path.Combine(Root, seg, seg);
test("args3 ", () => TimeTest(a3));
Console.WriteLine("***4 Args***");
Action p4 = () => path = Path.Combine(new[] { Root, seg, seg, seg });
test("params4", () => TimeTest(p4));
Action a4 = () => path = Path.Combine(Root, seg, seg, seg);
test("args4 ", () => TimeTest(a4));
Console.WriteLine(path);
}
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.GC.Collect")]
private static double TimeTest(Action action)
{
const int Iterations = 10 * 1000 * 1000;
Action gc = () =>
{
GC.Collect();
GC.WaitForFullGCComplete();
};
Action empty = () => { };
Stopwatch stopwatch1 = Stopwatch.StartNew();
for (int j = 0; j < Iterations; j++)
{
empty();
}
double loopElapsed = stopwatch1.Elapsed.TotalMilliseconds;
gc();
action(); //JIT
action(); //Optimize
Stopwatch stopwatch2 = Stopwatch.StartNew();
for (int j = 0; j < Iterations; j++)
{
action();
}
gc();
double testElapsed = stopwatch2.Elapsed.TotalMilliseconds;
return (testElapsed - loopElapsed);
}
Una posible razón también puede ser reducir la presión sobre el recolector de basura. La sobrecarga params-array crea una nueva matriz cada vez que se llama al método. Si el método se llama a menudo, se crean muchos objetos de matriz temporales, lo que aumenta la presión sobre el recolector de basura.