gpt4 book ai didi

c# - 为什么 LZMA SDK (7-zip) 这么慢

转载 作者:IT王子 更新时间:2023-10-29 04:30:46 26 4
gpt4 key购买 nike

我发现 7-zip 很棒,我想在 .net 应用程序上使用它。我有一个 10MB 的文件 (a.001),它需要:

enter image description here

2 秒编码

现在,如果我能在 C# 上做同样的事情就好了。我已经下载了 http://www.7-zip.org/sdk.html LZMA SDK c# 源代码。我基本上将 CS 目录复制到 visual studio 中的控制台应用程序中: enter image description here

然后我编译了,一切都顺利编译了。因此,在输出目录中,我放置了大小为 10MB 的文件 a.001。在我放置的源代码中的主要方法上:

[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;
}
}

当我执行控制台应用程序时,该应用程序运行良好,我在工作目录中得到了输出 a.7z问题是它需要很长时间。执行大约需要 15 秒! 我也尝试过 https://stackoverflow.com/a/8775927/637142 方法,它也需要很长时间。为什么比实际程序慢 10 倍?

还有

即使我设置为只使用一个线程: enter image description here

它仍然需要更少的时间(3 秒对 15 秒):


(编辑)另一种可能性

可能是因为 C# 比汇编或 C 慢?我注意到该算法做了很多繁重的操作。例如比较这两个代码块。他们都做同样的事情:

C

#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");
}

输出

enter image description here

c#

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();
}

输出

enter image description here

注意 c# 有多慢。这两个程序都在 Release模式下从 visual studio 外部运行。 也许这就是为什么在 .net 中比在 c++ 中花费更长的时间的原因。

我也得到了同样的结果。就像我刚刚展示的示例一样,C# 慢了 3 倍!


结论

我似乎不知道是什么导致了这个问题。我想我会使用 7z.dll 并从 c# 调用必要的方法。这样做的图书馆位于:http://sevenzipsharp.codeplex.com/这样我就可以使用与 7zip 相同的库:

    // 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");


}

最佳答案

我对代码运行了一个探查器,最昂贵的操作似乎是搜索匹配项。在 C# 中,它一次搜索一个字节。 LzBinTree.cs 中有两个函数(GetMatches 和 Skip),其中包含以下代码片段,它在这段代码上花费了大约 40-60% 的时间:

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

它基本上是试图一次找到一个字节的匹配长度。我将其提取到自己的方法中:

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

如果您使用不安全代码并将 byte* 转换为 ulong* 并一次比较 8 个字节而不是 1 个字节,我的测试数据的速度几乎翻了一番(在 64 位进程中):

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;
}
}
}

关于c# - 为什么 LZMA SDK (7-zip) 这么慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12292593/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com