C#File.ReadAllBytes vs std::ifstream(Windows) 在网络文件的所有字节中,C和C++读取产生不同的结果。C++的长度是C<的三倍。
C# C++ <>使用C结构文件给出与C++ +/p>钻孔的相同结果,我们可以看到它是从KNAL32.DLL调用Read文件,C++中复制相同的代码给出了相同的性能。C#File.ReadAllBytes vs std::ifstream(Windows) 在网络文件的所有字节中,C和C++读取产生不同的结果。C++的长度是C<的三倍。,c#,c++,windows,C#,C++,Windows,C# C++ 使用C结构文件给出与C++ +/p>钻孔的相同结果,我们可以看到它是从KNAL32.DLL调用Read文件,C++中复制相同的代码给出了相同的性能。 HANDLE f_handle = CreateFile(fp, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); DWORD read=0; ReadFile(f_handle, buffer, fs_len, &a
HANDLE f_handle = CreateFile(fp, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD read=0;
ReadFile(f_handle, buffer, fs_len, &read, NULL);
CloseHandle(f_handle);
< P>如果你得到不同的时间,可能是因为.NET默认使用文件IO的4KB缓冲区,这是你C++代码使用的1KB缓冲区的4倍。 编辑:请记住,因为这是一个网络文件,所以每次读取缓冲区时,网络延迟也会增加。因此,缓冲区越小,读取越多,增加的延迟和其他开销就越多
编辑:我没有看到整行代码,也没有看到缓冲区大小上额外的*1024块。因此,缓冲区的大小实际上是1MB。为了公平地比较这两种情况,使用相同的缓冲区大小来实现C++和C++的实现。 < P>我做了一些进一步的测试,并给出了完整的代码/结果。 测试由以下人员设置:
C#呼叫代码
[DllImport(DLL_NAME, CharSet = CharSet.Unicode)]
public static extern int test(string data_in, int option, int block_size);
...
string fp_template = @"N:/foo/{0}/bar ({1}).csv";
int KB = 1024;
int MB = KB * 1024;
int block_id = 0;
foreach (var block_size in new int[] {KB*1,KB*4,KB*32,MB*1,MB*5 })
{
Console.WriteLine("BlockSize (KB): " +(block_size/1024));
for (int i = 0; i < 50; i++)
{
Stopwatch sw_loop = Stopwatch.StartNew();
ParseBlockNative.test(String.Format(fp_template,block_id, i), i % 2,block_size);
Console.WriteLine("Option: {0} Taken: {1}", i % 2 == 0 ? "0-SLT" : "1-WIN", sw_loop.ElapsedMilliseconds);
}
Console.WriteLine();
block_id++;
}
这些测试结果已被取代,请跳到下一节 从网络读取37MB文件的时间,平均每个数据点超过25个文件 拿1
+------------+------+----------+
| Block_Size | SLT | Kernel32 |
+------------+------+----------+
| 1KB | 957 | 1065 |
| 4KB | 965 | 953 |
| 32KB | 952 | 729 |
| 1MB | 1015 | 230 |
| 5MB | 993 | 231 |
+------------+------+----------+
进行2次(20分钟后重新进行相同测试)
评论: 更改读取大小不会改善STL结果。 内核32倍从4KB略微提高到32KB,大部分从32KB提高到1MB 目前我的直觉是,作为一个网络驱动器,延迟非常高,但带宽很大。许多小请求(~4KB)比较少的大请求(~1MB)慢得多。延迟比我们在常规SSD或HDD上看到的要大得多,因此对更多请求的惩罚更严厉。 即使我告诉STL以1MB块读取,结果表明它忽略了这一点,并请求了大量4KB的读取
更新-唯一数据 在上面一节中看到的Kernel32从32KB提高到1MB的速度对我来说有点难以置信。我对每个读取操作都使用一个唯一的文件,但内容是相同的。我担心基于数据内容会有某种程度的缓存。我重新进行了上述测试,但这次我为每个读取操作随机生成了唯一的文件 下面的每个数据点表示25个不同文件的平均值,其中包含随机生成的内容
+------------+---------+----------+
| Block_Size | SLT | Kernel32 |
+------------+---------+----------+
| 1KB | 976 | 1,101 |
| 4KB | 1,027 | 1,011 |
| 32KB | 969 | 768 |
| 1MB | 981 | 530 |
| 5MB | 1,008 | 541 |
+------------+---------+----------+
为了完整性,C#的File.ReadAllBytes完成所需的时间约为585ms,接近内核32 1MB的时间
我将上述测试的一个子集redid为Kernel32,将文件\u FLAG\u NO\u缓冲传递到Kernel32,1MB运行时增加到大约700ms,但仍然明显优于STL
评论:
在我看来,服务器端网络缓存的影响已经消除。
我看到的是C#\Kernel32的性能超过了SLT。在SLT中,通过增加读取大小而不增加性能。 C++缓冲区为1 MIB,不是1。KiB@CodesInChaos该死完整的代码和测试结果添加到另一个POSII中,希望C++代码只是一个简单的例子,它看起来像是缓冲区溢出到了ME。完整的代码和测试结果添加到另一个POST中,需要找到另一个理论,文件。您还需要反向运行测试,以便消除/检测文件系统缓存的影响。最有可能的原因是速度差异。我们的网络确实进行缓存,我可以在初始测试中看到它的效果。在上面的测试中,我通过为每次读取创建一个唯一的文件来纠正这个问题。ie我对SLT和Kerel32的5种不同块大小平均超过25个文件,因此网络上有25*5*2个不同(但相等)的文件。没有文件被读取两次,因此颠倒顺序不会起任何作用。我同意网络缓存是不同的,在我看来,SLT和Kerel32以不同的方式请求数据,后者导致网络缓存。缓存已在数据内容上找到,测试结果已更新,并显示与C#的File.ReadAllBytes一致
extern "C" int DllExport test(wchar_t* fp,int option,int block_size)
{
int fs_len = 38441760;
char* buffer = (char*)malloc(fs_len);
int data_rem = fs_len;
int data_read = 0;
if (option==0)
{
std::ifstream str_in(fp, std::ifstream::binary);
while (data_rem > 0)
{
str_in.read(buffer + data_read, min(block_size,data_rem));
data_rem -= str_in.gcount();
data_read += str_in.gcount();
}
}
else
{
HANDLE f_handle = CreateFile(fp, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
while (data_rem > 0)
{
DWORD read = 0;
ReadFile(f_handle, buffer + data_read, min(block_size, data_rem), &read, NULL);
data_rem -= read;
data_read += read;
}
CloseHandle(f_handle);
}
free(buffer);
return data_read;
}
+------------+------+----------+
| Block_Size | SLT | Kernel32 |
+------------+------+----------+
| 1KB | 957 | 1065 |
| 4KB | 965 | 953 |
| 32KB | 952 | 729 |
| 1MB | 1015 | 230 |
| 5MB | 993 | 231 |
+------------+------+----------+
+------------+------+----------+
| Block_Size | SLT | Kernel32 |
+------------+------+----------+
| 1KB | 1040 | 999 |
| 4KB | 1077 | 1102 |
| 32KB | 1079 | 784 |
| 1MB | 1028 | 231 |
| 5MB | 1035 | 201 |
+------------+------+----------+
+------------+---------+----------+
| Block_Size | SLT | Kernel32 |
+------------+---------+----------+
| 1KB | 976 | 1,101 |
| 4KB | 1,027 | 1,011 |
| 32KB | 969 | 768 |
| 1MB | 981 | 530 |
| 5MB | 1,008 | 541 |
+------------+---------+----------+