zstandard support standard seven rar5 programa plugin para mac help gratis descomprimir descompresor descargar como archivos archivo abrir 7zs c# performance compression 7zip lzma

c# - support - ¿Por qué el LZMA SDK(7-zip) es tan lento?



seven zip para mac (6)

Acabo de echar un vistazo a la implementación de LZMA CS, y todo se realiza en código administrado. Habiendo realizado recientemente una investigación sobre esto para un requisito de compresión en mi proyecto actual, la mayoría de las implementaciones de compresión en código administrado parecen tener un rendimiento menos eficiente que en nativo.

Solo puedo suponer que esta es la causa del problema aquí. Si observa la tabla de rendimiento para otra herramienta de compresión, QuickLZ, puede ver la diferencia en el rendimiento entre el código nativo y el administrado (ya sea C # o Java).

Se me ocurren dos opciones: usar las instalaciones de interoperabilidad de .NET para llamar a un método de compresión nativo, o si puede permitirse sacrificar el tamaño de compresión, visite http://www.quicklz.com/ .

Encontré 7-zip genial y me gustaría usarlo en aplicaciones .net. Tengo un archivo de 10MB (a.001) y toma:

2 segundos para codificar .

Ahora será bueno si pudiera hacer lo mismo en c #. He descargado http://www.7-zip.org/sdk.html LZMA SDK c # código fuente. Básicamente copié el directorio CS en una aplicación de consola en Visual Studio:

Luego compilé y todo fue compilado sin problemas. Así que en el directorio de salida coloqué el archivo a.001 que tiene un tamaño de 10 MB. En el método principal que vino en el código fuente que coloqué:

[STAThread] static int Main(string[] args) { // e stands for encode args = "e a.001 output.7z".Split('' ''); // added this line for debug try { return Main2(args); } catch (Exception e) { Console.WriteLine("{0} Caught exception #1.", e); // throw e; return 1; } }

cuando ejecuto la aplicación de la consola, la aplicación funciona muy bien y obtengo la salida a.7z en el directorio de trabajo. El problema es que lleva tanto tiempo. ¡Se tarda unos 15 segundos en ejecutarse! También he intentado https://stackoverflow.com/a/8775927/637142 enfoque y también toma mucho tiempo. ¿Por qué es 10 veces más lento que el programa real?

también

Incluso si me puse a utilizar un solo hilo:

Todavía toma mucho menos tiempo (3 segundos vs 15):

(Editar) Otra Posibilidad

¿Podría ser porque C # es más lento que el ensamblaje o C? Me doy cuenta de que el algoritmo hace muchas operaciones pesadas. Por ejemplo, compara estos dos bloques de código. Ambos hacen la misma cosa:

do

#include <time.h> #include<stdio.h> void main() { time_t now; int i,j,k,x; long counter ; counter = 0; now = time(NULL); /* LOOP */ for(x=0; x<10; x++) { counter = -1234567890 + x+2; for (j = 0; j < 10000; j++) for(i = 0; i< 1000; i++) for(k =0; k<1000; k++) { if(counter > 10000) counter = counter - 9999; else counter= counter +1; } printf (" %d /n", time(NULL) - now); // display elapsed time } printf("counter = %d/n/n",counter); // display result of counter printf ("Elapsed time = %d seconds ", time(NULL) - now); gets("Wait"); }

salida

do#

static void Main(string[] args) { DateTime now; int i, j, k, x; long counter; counter = 0; now = DateTime.Now; /* LOOP */ for (x = 0; x < 10; x++) { counter = -1234567890 + x + 2; for (j = 0; j < 10000; j++) for (i = 0; i < 1000; i++) for (k = 0; k < 1000; k++) { if (counter > 10000) counter = counter - 9999; else counter = counter + 1; } Console.WriteLine((DateTime.Now - now).Seconds.ToString()); } Console.Write("counter = {0} /n", counter.ToString()); Console.Write("Elapsed time = {0} seconds", DateTime.Now - now); Console.Read(); }

Salida

Note cuánto más lento fue c #. Ambos programas se ejecutan desde el exterior visual studio en modo de lanzamiento. Tal vez esa es la razón por la que tarda tanto más tiempo en .net que en c ++.

También obtuve los mismos resultados. ¡C # fue 3 veces más lento como en el ejemplo que acabo de mostrar!

Conclusión

Parece que no puedo saber qué está causando el problema. Supongo que usaré 7z.dll e invocaré los métodos necesarios de c #. Una biblioteca que hace eso está en: http://sevenzipsharp.codeplex.com/ y de esa manera estoy usando la misma biblioteca que 7zip está usando como:

// dont forget to add reference to SevenZipSharp located on the link I provided static void Main(string[] args) { // load the dll SevenZip.SevenZipCompressor.SetLibraryPath(@"C:/Program Files (x86)/7-Zip/7z.dll"); SevenZip.SevenZipCompressor compress = new SevenZip.SevenZipCompressor(); compress.CompressDirectory("MyFolderToArchive", "output.7z"); }


Ejecuté un generador de perfiles en el código, y la operación más costosa parece estar en la búsqueda de coincidencias. En C #, está buscando un solo byte a la vez. Hay dos funciones (GetMatches y Skip) en LzBinTree.cs que contienen el siguiente fragmento de código, y gasta alrededor del 40-60% de su tiempo en este código:

if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) { while (++len != lenLimit) if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) break;

Básicamente, se trata de encontrar la longitud de coincidencia de un solo byte a la vez. Lo extraje en su propio método:

if (GetMatchLength(lenLimit, cur, pby1, ref len)) {

Y si usa un código inseguro y convierte el byte * a un ulong * y compara 8 bytes a la vez en lugar de 1, la velocidad casi se duplicó para mis datos de prueba (en un proceso de 64 bits):

private bool GetMatchLength(UInt32 lenLimit, UInt32 cur, UInt32 pby1, ref UInt32 len) { if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) return false; len++; // This method works with or without the following line, but with it, // it runs much much faster: GetMatchLengthUnsafe(lenLimit, cur, pby1, ref len); while (len != lenLimit && _bufferBase[pby1 + len] == _bufferBase[cur + len]) { len++; } return true; } private unsafe void GetMatchLengthUnsafe(UInt32 lenLimit, UInt32 cur, UInt32 pby1, ref UInt32 len) { const int size = sizeof(ulong); if (lenLimit < size) return; lenLimit -= size - 1; fixed (byte* p1 = &_bufferBase[cur]) fixed (byte* p2 = &_bufferBase[pby1]) { while (len < lenLimit) { if (*((ulong*)(p1 + len)) == *((ulong*)(p2 + len))) { len += size; } else return; } } }


El tiempo de ejecución de .net es más lento que las instrucciones nativas. Si algo sale mal en c, normalmente tenemos un bloqueo de la aplicación con la pantalla azul de la muerte. Pero en c # no lo hace, porque los cheques que no hacemos en c, en realidad se agregan en c #. Sin poner una comprobación adicional de nulo, el tiempo de ejecución nunca puede capturar la excepción de puntero nulo. Sin verificar el índice y la longitud, el tiempo de ejecución nunca puede capturar la excepción fuera de límites.

Estas son instrucciones implícitas antes de cada instrucción que hace lento el tiempo de ejecución de .net. En las aplicaciones empresariales típicas, no nos importa el rendimiento, donde la complejidad de los negocios y la lógica de la interfaz de usuario son más importantes, es por eso que .net runtime protege cada instrucción con un cuidado especial que nos permite depurar y resolver problemas rápidamente.

Los programas nativos de c siempre serán más rápidos que el tiempo de ejecución de .net, pero son difíciles de depurar y necesitan un conocimiento profundo de c para escribir el código correcto. Porque c ejecutará todo, pero no te dará ninguna excepción o pista de lo que salió mal.


Este tipo de código binario-aritmético y bifurcado es lo que aman los compiladores C y lo que odia el JIT .NET. El .NET JIT no es un compilador muy inteligente. Está optimizado para una rápida compilación. Si Microsoft quisiera ajustarlo para obtener el máximo rendimiento, ellos conectarán el backend de VC ++, pero luego no lo harán.

También, puedo decir por la velocidad que está obteniendo con 7z.exe (6MB / s) que está usando múltiples núcleos, probablemente usando LZMA2. Mi núcleo rápido i7 puede ofrecer 2MB / s por núcleo, por lo que supongo que 7z.exe está ejecutando múltiples subprocesos para usted. Intenta activar el subprocesamiento en la biblioteca 7zip si es posible.

Recomiendo que en lugar de usar el algoritmo LZMA de código administrado, use una biblioteca compilada de forma nativa o llame a 7z.exe usando Process.Start . Este último debe comenzar rápidamente con buenos resultados.


No he usado el SDK de LZMA, pero estoy bastante seguro de que, por defecto, 7-zip ejecuta la mayoría de las operaciones en muchos subprocesos. Como no lo he hecho, lo único que puedo sugerir es que compruebe si es posible forzarlo a usar muchos subprocesos (si no se utiliza de forma predeterminada).

Editar:

Como parece que los subprocesos pueden no ser (el único) problema relacionado con el rendimiento, hay otros en los que podría pensar:
  1. ¿Ha comprobado que ha configurado las mismas opciones que está configurando cuando usa la interfaz de usuario 7-zip? ¿Es el archivo de salida del mismo tamaño? Si no, puede suceder que un método de compresión sea mucho más rápido que el otro.

  2. ¿Está ejecutando su aplicación desde dentro o no? Si es así, esto también podría agregar algo de sobrecarga (pero supongo que no debería resultar en una aplicación que se ejecuta 5 veces más lenta).

  3. ¿Se están realizando otras operaciones antes de comprimir el archivo?

Otra alternativa es usar SevenZipSharp (disponible en NuGet) y apuntarlo a su 7z.dll. Entonces tus velocidades deberían ser aproximadamente las mismas:

var libPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "7-zip", "7z.dll"); SevenZip.SevenZipCompressor.SetLibraryPath(libPath); SevenZip.SevenZipCompressor compressor = new SevenZipCompressor(); compressor.CompressFiles(compressedFile, new string[] { sourceFile });