我发现将文件“加载”到文件中可能需要非常不同的时间 - 即使我的机器似乎没有做太多其他事情。我附上了一些代码来说明问题:
输出低于。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
LoadFileUnman();
LoadFileUnman();
LoadFileUnman();
LoadFileUnman();
LoadFileUnman();
Console.WriteLine("Done");
}
public unsafe bool LoadFileUnman()
{
string filename = @"C:\DataFile.BNF";
var fileStream = new FileStream(filename,
FileMode.Open,
FileAccess.Read,
FileShare.Read,
16 * 1024,
FileOptions.SequentialScan);
if (fileStream == null)
{
Console.WriteLine( "Could not open file");
return true;
}
Int64 length = fileStream.Length;
Console.WriteLine("File length: " + length.ToString("#,###"));
UnmanagedMemoryStream GlobalMS;
IntPtr GlobalBuffer;
try
{
IntPtr myp = new IntPtr(length);
GlobalBuffer = Marshal.AllocHGlobal(myp);
}
catch (Exception er)
{
Console.WriteLine("Could not allocate memory: " + er.Message);
return true;
}
unsafe
{
byte* pBytes = (byte*)GlobalBuffer.ToPointer();
GlobalMS = new UnmanagedMemoryStream(pBytes, (long)length, (long)length, FileAccess.ReadWrite);
DateTime befDT = DateTime.Now;
fileStream.CopyTo(GlobalMS);
Console.WriteLine("Load took: " + DateTime.Now.Subtract(befDT).TotalMilliseconds.ToString("#,###") + "ms");
GlobalMS.Seek(0, SeekOrigin.Begin);
}
GlobalMS.Close();
fileStream.Close();
return false;
}
}
}
这是输出,当我使用更大的文件(10G)时,时间差异更大。然后有时加载甚至一分钟都是几秒钟。
File length: 178,782,404
Load took: 5,125ms
File length: 178,782,404
Load took: 156ms
File length: 178,782,404
Load took: 172ms
File length: 178,782,404
Load took: 141ms
File length: 178,782,404
Load took: 1,891ms
任何人都可以告诉我它为何如此变数,如果有什么我可以做的。
EDIT 1
从我的评论中 - 对我来说似乎是一个好主意,强调我需要的是一种方法来修复负载的可变性而不是整体速度。我可以通过优化方式(我有)来提高速度,但这是问题的结果加载时间的差异。
EDIT 2
以下是我正在运行的服务。如果有人注意到任何可能导致我问题的人,我将不胜感激。
答案 0 :(得分:3)
这取决于很多因素,例如你当时PC正在做什么,磁盘碎片,内存是否(几乎)满等等。
除了优化您的环境之外,您无能为力:
如果您阅读的文件是副本,那么您可以从RAM磁盘中读取它们 - 因此您可能有一个后台进程将文件复制到RAM磁盘,然后您的程序可以从那里读取它们。这也比从磁盘读取速度快得多。
另请参阅http://www.softperfect.com/products/ramdisk/了解RAM磁盘软件。
编辑:从你的图片中我注意到以下内容,这可能会影响性能(注意这个列表并非详尽无遗,因此可能还有其他我没注意到的服务导致延迟):
答案 1 :(得分:1)
需要考虑的事项:
如果你跑了5次以上就会看到结果会很有趣。
其他一些信息:
等待磁盘的IO绑定进程将优先提升,以便能够立即处理数据。大多数操作系统都将其作为调度程序架构的一部分。这意味着通常一个中等繁忙的系统不应该对正在运行的进程产生很大影响......除非它们共享一些缓慢的设备。磁盘是一个很慢的设备,但很容易忘记内存也是一个相对较慢的设备,应该小心共享。
对于并列论(假设你正在编写服务器软件):我的MSSQL服务器有数据库/日志有效地分布在28个磁盘上,服务器包含几个带有多个CPU的卡,所有这些卡都有单独的总线访问单独的内存,还有一些交叉连接。 MSSQL利用它将部分DB分配给与最近的CPU对应的内存。搜索在所有CPU及其关闭内存上并行完成(请参阅NUMA。我的观点是有专门用于推动类似场景的硬件。
答案 2 :(得分:0)
第一次实例化缓冲区时,操作系统会搜索空闲内存。对于10G文件,很明显必须在磁盘上找到空间,因此存在巨大的延迟。再次重做任务后,内存在回收之前仍然可用。
您可以通过在按钮处理程序中的每个LoadFileUnman()之后放置一个GC.Collect()来验证这一点。
答案 3 :(得分:0)
Windows系统正在幕后做事,这使得“无法”控制或测试真正发生的事情。 Windows系统在其他所有内容上都有自己的缓冲层。文件流刷新不会将数据刷新到磁盘,而是刷新系统,它可以根据需要执行所需的操作。
请参阅可从任务管理器启动的资源监视器,然后您可能会看到系统进程正在读取和写入与您的应用程序相同的文件。
- 我想要的是大文件的最佳顺序读写速度,但是由于这样的智能系统以及“优秀的”ms文档,我真的被卡住了。猜猜我会像其他人一样做,无论做什么都有效......悲伤的事情