大字节[]的优化
本文关键字:优化 字节 | 更新日期: 2023-09-27 18:11:52
我有5MB字节[],我以2k的块写入磁盘。要获取2k (c_writeSizeInBytes)的内存,我可以这样做:
int numberOfIterations = bytes.Length / c_writeSizeInBytes;
for (int i = 0; i < numberOfIterations; i++)
{
bool nearEnd = bytes.Length - i == c_writeSizeInBytes;
byte[] buffer = nearEnd ? bytes.Skip(i * c_writeSizeInBytes).ToArray() : bytes.Skip(i * c_writeSizeInBytes).Take(c_writeSizeInBytes).ToArray();
binaryWriter.Write(buffer, 0, c_writeSizeInBytes);
}
2mb文件后5MB文件的性能非常慢。有什么方法可以优化它吗?
谢谢
您在这里使用Skip
/Take
/ToArray
是非常低效的。如果有写入块,那么您应该将偏移量传递给Write
,即
binaryWriter.Write(buffer, i * CHUNK_SIZE, CHUNK_SIZE);
(可能在最后一个块中使用一些Math.Min
来获取剩余的计数,以防它不是完整的块数)
但是,如果您已经将数据作为byte[]
,则不需要这样做-只需对Write
进行一次调用。
binaryWriter.Write(buffer, 0, buffer.Length);
如果您正在编写整个文件(即此数据替换旧数据,如果有的话),则只需使用File.WriteAllBytes
。
我会这样写:
byte[] input;
using(var inStream = new MemoryStream(input))
using(var outStream = File.OpenWrite("c:''file.dat"))
{
inStream.CopyTo(outStream, 2048);
}
啊,这里出现了Schlemiel the Painter的情况。for循环涉及一次查找字节数组中的一个元素(通过. skip()),并且每次迭代都会在数组中走得更远一些,因此,完成每次for循环迭代所花费的时间越来越长,迭代次数越多。
既然已经有了字节数组,为什么还需要缓冲区呢?您可以直接从现有数组写入二进制流:
int offset = 0, lastFullWriteIndex = bytes.Length - c_writeSizeInBytes;
while (offset < lastFullWriteIndex)
{
binaryWriter.Write(bytes, offset, c_writeSizeInBytes);
offset += c_writeSizeInBytes;
}
binaryWriter.Write(bytes, offset, bytes.Length - offset);
这不仅消除了连续遍历越来越多的数组所带来的减速效应,而且还消除了将字节复制到缓冲区的额外工作。
不知道你有什么约束迫使你只写2k块大小但如果你一定要这样做,那就试试这个方法
public void Write(Byte[] bytes,System.IO.Stream stream)
{
int chunkSize = 2 * 1024; //2k
int offset = 0;
do
{
var count = offset + chunkSize > bytes.Length ? bytes.Length - offset : chunkSize;
stream.Write(bytes, offset, count);
offset += count;
} while (offset < bytes.Length);
}
好的,如果你想自己滚动(没有必要),这是一种方法。
const int BufferSize = 2000
for (int left = bytes.Length; left > 0; left -= BufferSize)
{
if (left < BufferSize)
{
binaryWriter.Write(byte, bytes.length - left, left);
break;
}
binaryWriter.Write(byte, bytes.length - left, BufferSize);
}