gpt4 book ai didi

c++ - 性能比较 - pcap 文件读取 : C+ +'s ifstream VS C' s fread

转载 作者:太空宇宙 更新时间:2023-11-04 01:52:32 50 4
gpt4 key购买 nike

我正在研究哪个是更快的二进制文件读取器:C++ 的 ifstream::read 或 C 的 fread。

根据网上的资料,包括类似的问题,差别不大,所以决定挖北斗。

我使用了一个 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(&eth, 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*)&eth, 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++ 读取文件的更快方法。

最佳答案

ifstream::read()将数据从内部缓冲区复制到您的缓冲区。它导致性能的主要差异。您可以尝试克服它并通过 pubsetbuf 将内部缓冲区替换为您自己的缓冲区。 :

std::ifstream file;
char buf[1024];
file.rdbuf()->pubsetbuf(buf, sizeof buf);

问题是这个函数是实现定义的,在大多数情况下你仍然需要使用额外的数据拷贝。

在您的情况下,您不需要 ifstream 的所有功能, 所以为了性能和简单我建议使用 <cstdio> .

关于c++ - 性能比较 - pcap 文件读取 : C+ +'s ifstream VS C' s fread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40674693/

50 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com