【发布时间】:2016-11-18 10:28:04
【问题描述】:
我正在研究哪个是更快的二进制文件阅读器:C++ 的 ifstream::read 或 C 的 fread。
根据网上的说法,包括类似的问题,并没有太大的区别,所以我决定去挖dipper。
我使用了一个 1.22gb 的 pcap 文件,其中包含大约 1,377,000 个数据包。 两个程序都使用 mingw32-g++ 编译,没有优化。
头结构是根据wireshark的wiki-libpcap文件结构定义的: https://wiki.wireshark.org/Development/LibpcapFileFormat
这是 C 代码:
#include <stdio.h>
#include <stdlib.h>
#include <Winsock2.h>
/* definition of structs: pcap_global_header, pcap_packet_header, ethernet_header, ipv4_header, tcp_header */
int main()
{
int count = 0, bytes_read;
/* open file */
FILE * file = fopen("test.pcap", "rb");
/* read file header */
struct pcap_global_header gheader;
fread(&gheader, sizeof(char), sizeof(struct pcap_global_header), file);
// if not ethernet type
if(gheader.network != 1)
{
printf("not ethernet !\n");
return 1;
}
/* read packets */
char *buffer = (char*)malloc(gheader.snaplen);
struct pcap_packet_header pheader;
struct ether_header eth;
struct ipv4_header ip;
struct tcp_header tcp;
fread(&pheader, sizeof(char), sizeof(struct pcap_packet_header), file);
while(!feof(file))
{
++count;
bytes_read = fread(ð, sizeof(char), sizeof(struct ether_header), file);
// ip
if(eth.type == 0x08)
{
bytes_read += fread(&ip, sizeof(char), sizeof(struct ipv4_header), file);
//tcp
if( ip.protocol == 0x06 )
{
bytes_read += fread(&tcp, sizeof(char), sizeof(struct tcp_header), file);
}
}
//read rest of the packet
fread(buffer, sizeof(char), pheader.incl_len - bytes_read, file);
// read next packet's header
fread(&pheader, sizeof(char), sizeof(struct pcap_packet_header), file);
}
printf("(C) total packets: %d\n", count);
return 0;
}
这是 C++ 代码:
#include <iostream>
#include <fstream>
#include <memory>
#include <Winsock2.h>
/* definition of structs: pcap_global_header, pcap_packet_header, ethernet_header, ipv4_header, tcp_header */
int main()
{
int count_packets = 0, bytes_read;
/* open file */
std::ifstream file("test.pcap", std::fstream::binary | std::fstream::in);
/* read file header */
struct pcap_global_header gheader;
file.read((char*)&gheader, sizeof(struct pcap_global_header));
// if not ethernet type
if(gheader.network != 1)
{
printf("not ethernet !\n");
return 1;
}
/* read packets */
char *buffer = std::allocator<char>().allocate(gheader.snaplen);
struct pcap_packet_header pheader;
struct ether_header eth;
struct ipv4_header ip;
struct tcp_header tcp;
file.read((char*)&pheader, sizeof(pcap_packet_header));
while(!file.eof())
{
++count_packets;
file.read((char*)ð, sizeof(struct ether_header));
bytes_read = sizeof(struct ether_header);
// ip
if(eth.type == 0x08)
{
file.read((char*)&ip, sizeof(struct ipv4_header));
bytes_read += sizeof(struct ipv4_header);
//tcp
if( ip.protocol == 0x06 )
{
file.read((char*)&tcp, sizeof(struct tcp_header));
bytes_read += sizeof(struct tcp_header);
}
}
// read rest of the packet
file.read(buffer, pheader.incl_len - bytes_read);
// read next packet's header
file.read((char*)&pheader, sizeof(pcap_packet_header));
}
std::cout << "(C++) total packets :" << count_packets << std::endl;
return 0;
}
结果非常令人失望:
C代码结果:
(C) total packets: 1377065
Process returned 0 (0x0) execution time : 1.031 s
Press any key to continue.
C++代码结果:
(C++) total packets :1377065
Process returned 0 (0x0) execution time : 3.172 s
Press any key to continue.
显然,我对每个版本都运行了几次,因此,我正在寻找一种使用 C++ 读取文件的更快方法。
【问题讨论】:
-
我正在寻找一种使用 C++ 读取文件的更快方法。您找到了 - 使用
::fread()。另见Why is “while ( !feof (file) )” always wrong? -
没有优化?为什么要在没有优化的情况下进行基准测试?
-
@AndrewHenle 我用错了 feof() 吗?
-
@J.Doe 我用错了 feof() 吗? 是的。阅读链接的问题和答案。
feof()直到在尝试读取文件末尾之后才为真。 -
@AndrewHenle 我在调用 feof() 之前读取了第一个数据包的标头,这里没有任何问题
标签: c++ c performance pcap