基于可用物理内存的阵列大小
本文关键字:阵列 于可用 物理内存 | 更新日期: 2023-09-27 18:27:27
我正在尝试制作一个加密算法。我可以毫无问题地读取文件并将其转换为字节,并将字节保存在byteArray中。
问题是我目前正在创建这样的数组大小:
byte[] FileArray =new byte[10000000];
FileStream TheFileStream = new FileStream(FilePath.Text, FileMode.Open);
BinaryReader TheFileBinary = new BinaryReader(TheFileStream);
for (int i = 0; i < TheFileStream.Length; i++) {
FileArray = TheFileBinary.ReadBytes(10000000);
// I call a function here
if (TheFileStream.Position == TheFileStream.Length)
break;
}
然而,我不希望数组大小是固定的,因为如果我将其设置为1000000(例如),其他内存大小较小的机器可能会面临问题。我需要为每台机器找到内存大小的空闲大小,我如何根据空闲的未分配内存空间动态设置数组大小,以便在我可以将其放入byteArray的地方使用?
我注意到Arraysize越大,读取速度就越快,所以我也不想让它太小。我真的很感激你的帮助。
FileStream
跟踪文件中的字节数。只需使用Length
属性。
FileStream TheFileStream = new FileStream(FilePath.Text, FileMode.Open);
BinaryReader TheFileBinary = new BinaryReader(TheFileStream);
byte[] FileArray = TheFileBinary.ReadBytes(TheFileStream.Length);
好吧,重读这个问题,finnaly发现其中有一部分是问题,"我怎么知道空闲的未分配内存空间,这样我就可以把它放在字节数组中"。无论如何,我建议你看看这个问题以及它的最高评价。
如果你真的担心空间,那么使用一个简单的List,一次读取流的块(比如1024),并调用列表上的AddRange
方法。完成后,在List上调用ToArray
,现在就有了一个大小合适的字节数组。
List<byte> byteArr = new List<byte>();
byte[] buffer = new byte[1024];
int bytesRead = 0;
using(FileStream TheFileStream = new FileStream(FilePath.Text, FileMode.Open))
{
while((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
byteArr.AddRange(buffer);
}
buffer = byteArr.ToArray();
// call your method here.
编辑:对于较大的文件,最好还是分块读取。当然,您可以随心所欲地使用缓冲区大小,但1024通常是一个不错的起点。读取整个文件最终会使内存翻倍,因为您还必须处理与流大小相同的内部读取缓冲区(位于您自己的缓冲区之上)。将读取分解为块只占用FileStream.Length + <buffer size>
内存,而不是FileStream.Length * 2
内存。只是需要记住的。。。
byte[] buffer = null;
using(FileStream TheFileStream = new FileStream(FilePath.Text, FileMode.Open))
{
buffer = new byte[TheFileStream.Length];
int offset = 0;
while((bytesRead = stream.Read(buffer, offset, 1024)) > 0)
offset += bytesRead;
// Or just TheFileStream.Read(buffer, 0, buffer.Length) if it's small enough.
}
您可以使用WMI检索Win32_OperatingSystem
类的实例,并根据FreePhysicalMemory
或TotalVisibleMemorySize
属性进行内存计算:
static ulong GetAvailableMemoryKilobytes()
{
const string memoryPropertyName = "FreePhysicalMemory";
using (ManagementObject operatingSystem = new ManagementObject("Win32_OperatingSystem=@"))
return (ulong) operatingSystem[memoryPropertyName];
}
static ulong GetTotalMemoryKilobytes()
{
const string memoryPropertyName = "TotalVisibleMemorySize";
using (ManagementObject operatingSystem = new ManagementObject("Win32_OperatingSystem=@"))
return (ulong) operatingSystem[memoryPropertyName];
}
然后将任一方法的结果传递给这样的方法,以将读取缓冲区的大小缩放到本地机器的内存:
static int GetBufferSize(ulong memoryKilobytes)
{
const int bufferStepSize = 256; // 256 kilobytes of buffer...
const int memoryStepSize = 128 * 1024;// ...for every 128 megabytes of memory...
const int minBufferSize = 512; // ...no less than 512 kilobytes...
const int maxBufferSize = 10 * 1024; // ...no more than 10 megabytes
int bufferSize = bufferStepSize * ((int) memoryKilobytes / memoryStepSize);
bufferSize = Math.Max(bufferSize, minBufferSize);
bufferSize = Math.Min(bufferSize, maxBufferSize);
return bufferSize;
}
显然,每128 MB的RAM增加256 KB的缓冲区大小似乎有点傻,但如果你真的想这样做,这些数字只是如何扩展缓冲区大小的例子。除非你同时读取很多文件,否则担心几百千字节或几兆字节的缓冲区可能会带来更大的麻烦。您最好只进行基准测试,看看哪个大小的缓冲区能提供最佳性能(它可能不需要像您想象的那么大)并使用它。
现在你可以简单地更新你的代码如下:
ulong memoryKilobytes =
GetAvailableMemoryKilobytes();
// ...or GetTotalMemoryKilobytes();
int bufferSize = GetBufferSize(memoryKilobytes);
using (FileStream TheFileStream = new FileStream(FilePath.Text, FileMode.Open))
{
byte[] FileArray = new byte[bufferSize];
int readCount;
while ((readCount = TheFileBinary.Read(FileArray, 0, bufferSize)) > 0)
{
// Call a method here, passing FileArray as a parameter
}
}