swift和Managed(c#)之间的压缩性能差异



我正在托管内存环境中实现LZF压缩,并从ios环境中解压缩。

所以这是我的代码实现lzf解压如下在c#中

private static int LZFDecompress(byte[] input, byte[] output)
{
int inputLength = input.Length;
int outputLength = output.Length;
uint iidx = 0;
uint oidx = 0;
do
{
uint ctrl = input[iidx++];
if (ctrl < (1 << 5)) /* literal run */
{
ctrl++;
if (oidx + ctrl > outputLength)
{
//SET_ERRNO (E2BIG);
return 0;
}
do
output[oidx++] = input[iidx++];
while ((--ctrl) != 0);
}
else /* back reference */
{
uint len = ctrl >> 5;
int reference = (int)(oidx - ((ctrl & 0x1f) << 8) - 1);
if (len == 7)
len += input[iidx++];
reference -= input[iidx++];
if (oidx + len + 2 > outputLength)
{
//SET_ERRNO (E2BIG);
return 0;
}
if (reference < 0)
{
//SET_ERRNO (EINVAL);
return 0;
}
output[oidx++] = output[reference++];
output[oidx++] = output[reference++];
do
output[oidx++] = output[reference++];
while ((--len) != 0);
}
}
while (iidx < inputLength);
return (int)oidx;
}

并像这个一样移植到swift

private static func LZFDecompress(input: [UInt8],
output: inout [UInt8])
-> Int
{
let inputLength = input.count
let outputLength = output.count

var iidx = 0
var oidx = 0

repeat
{
var ctrl = Int(input[iidx])
iidx += 1

if ctrl < (1 << 5)
{
ctrl += 1

if oidx + ctrl > outputLength
{
return 0
}

repeat
{
output[oidx] = input[iidx]
oidx += 1
iidx += 1
ctrl -= 1
}
while ctrl != 0
}
else
{
var len = ctrl >> 5
var reference = oidx - ((ctrl & 0x1f) << 8) - 1

if len == 7
{
len += Int(input[iidx])
iidx += 1
}

reference -= Int(input[iidx])
iidx += 1

if oidx + len + 2 > outputLength
{
return 0
}

if reference < 0
{
return 0
}

output[oidx] = output[reference]
oidx += 1
reference += 1
output[oidx] = output[reference]
oidx += 1
reference += 1

repeat
{
output[oidx] = output[reference]
oidx += 1
reference += 1
len -= 1
}
while len != 0
}
}
while iidx < inputLength

return oidx
}

但我有一个问题,这是一个性能差异。在c#中需要2-3秒,但在swift中需要9-10秒来解压缩相同的文件。。。我不能理解这种情况。

我在windows的控制台上测试了c#。我在操场或mac项目中测试了swift。

没有考虑SIMD和CPU,这不是一个高效的代码。所以我用的解压方法(lz4,zlib(是苹果提供的。它比以前快多了。解压缩200Mb文件的成本低于1秒。

但在托管环境(c#(中,它比非托管环境慢。如果您想要更高的性能,请实现本机。

我使用这些lzib管理的代码。

  • https://github.com/jstedfast/Ionic.Zlib
  • https://github.com/Kulestar/unity-zlib(统一版,dotnet mono(

在同一文件中解压缩需要6-7秒,压缩需要30秒。

然后你应该知道这个代码与苹果中的lzip兼容。它包括为压缩数据添加标头。

public static byte[] Compress(byte[] inputData)
{
var zlib = new ZlibCodec(CompressionMode.Compress);
zlib.CompressLevel = Zlib.CompressionLevel.AppleSupported; // Level5
zlib.InputBuffer = inputData;
zlib.OutputBuffer = new byte[inputData.Length];
zlib.NextIn = 0;
zlib.AvailableBytesIn = inputData.Length;
zlib.NextOut = 0;
zlib.AvailableBytesOut = inputData.Length;
zlib.InitializeDeflate(Zlib.CompressionLevel.AppleSupported, false); 
// 'false' means it's 1951(deflate) version not 1950(lzib) version
zlib.Deflate(FlushType.Finish);
var output = new byte[zlib.TotalBytesOut];
Array.Copy(zlib.OutputBuffer, output, (int)zlib.TotalBytesOut);
return output;
}
public static byte[] Decompress(byte[] inputData, int outputSize)
{
var zlib = new ZlibCodec(CompressionMode.Decompress);
zlib.CompressLevel = Zlib.CompressionLevel.AppleSupported;
zlib.InputBuffer = inputData;
zlib.OutputBuffer = new byte[outputSize];
zlib.NextIn = 0;
zlib.AvailableBytesIn = inputData.Length;
zlib.NextOut = 0;
zlib.AvailableBytesOut = outputSize;
zlib.InitializeInflate(false);
zlib.Inflate(FlushType.Finish);
var output = new byte[zlib.TotalBytesOut];
Array.Copy(zlib.OutputBuffer, output, (int)zlib.TotalBytesOut);
return output;
}

我希望能帮助像我这样实现多平台压缩的人。

最新更新