C++ 真的很慢
所以我试着为自己编写一个linux管道的命令。把它想象成gnu“cat”或“sed”的复制品,它从标准输入获取输入,进行一些处理并写入标准输出 <>我最初写了一个AWK脚本,但是想要更多的性能,所以我使用了下面的C++代码:C++ 真的很慢,c++,pipeline,cout,cin,C++,Pipeline,Cout,Cin,所以我试着为自己编写一个linux管道的命令。把它想象成gnu“cat”或“sed”的复制品,它从标准输入获取输入,进行一些处理并写入标准输出 我最初写了一个AWK脚本,但是想要更多的性能,所以我使用了下面的C++代码: std::string crtLine; crtLine.reserve(1000); while (true) { std::getline(std::cin, crtLine); if (!std::cin) // failbit (EOF immediat
std::string crtLine;
crtLine.reserve(1000);
while (true)
{
std::getline(std::cin, crtLine);
if (!std::cin) // failbit (EOF immediately found) or badbit (I/O error)
break;
std::cout << crtLine << "\n";
}
我尝试了cin.getline(buffer,size)而不是getline(istream,string),但没有改进。这很尴尬,是缓冲问题吗?我还尝试一次获取100KB,而不是一行,没有帮助!有什么想法吗
编辑:
你们说的有道理,但罪魁祸首不是字符串生成/复制,也不是扫描换行符。(缓冲区的大小也是如此)。请看以下两个程序:
char buf[200];
while (fgets(buf, 200, stdin))
std::cout << buf;
$time cat 'file' | ./FilterRange > /dev/null
real 0m3.276s
char buf[200];
while (std::cin.getline(buf, 200))
std::cout << buf << "\n";
$time cat 'file' | ./FilterRange > /dev/null
real 0m55.031s
charbuf[200];
而(fgets(buf、200、stdin))
std::cout/dev/null
实际0m3.276s
char-buf[200];
而(标准::cin.getline(buf,200))
标准::cout
这正是cat(无任何参数)所做的
不是真的。这与/bin/cat的效果完全相同,但使用的方法不同
/bin/cat
看起来更像这样:
while( (readSize = read(inFd, buffer, sizeof buffer)) > 0)
write(outFd, buffer, readSize);
请注意,/bin/cat
不对其输入进行处理。它不会从中构建std::string
,也不会扫描\n
,它只是一个接一个地执行系统调用
另一方面,您的程序构建字符串
s,复制它们,扫描\n
等
这个小而完整的程序运行速度比/bin/cat慢2-3个数量级:
#include <string>
#include <iostream>
int main (int ac, char **av) {
std::string crtLine;
crtLine.reserve(1000);
while(std::getline(std::cin, crtLine)) {
std::cout << crtLine << "\n";
}
}
#include <string>
#include <iostream>
#include <vector>
int main (int ac, char **av) {
std::vector<char> v(4096);
do {
std::cin.read(&v[0], v.size());
std::cout.write(&v[0], std::cin.gcount());
} while(std::cin);
}
#包括
#包括
内部主(内部ac,字符**av){
std::字符串crtLine;
储备量(1000);
while(std::getline(std::cin,crtLine)){
std::cout/dev/null
编辑
该程序的性能在/bin/cat的50%以内:
#include <string>
#include <iostream>
int main (int ac, char **av) {
std::string crtLine;
crtLine.reserve(1000);
while(std::getline(std::cin, crtLine)) {
std::cout << crtLine << "\n";
}
}
#include <string>
#include <iostream>
#include <vector>
int main (int ac, char **av) {
std::vector<char> v(4096);
do {
std::cin.read(&v[0], v.size());
std::cout.write(&v[0], std::cin.gcount());
} while(std::cin);
}
#包括
#包括
#包括
内部主(内部ac,字符**av){
std::向量v(4096);
做{
标准::cin.read(&v[0],v.size());
std::cout.write(&v[0],std::cin.gcount());
}while(std::cin);
}
简言之,如果您的需求是逐行分析输入,那么您将不得不为使用格式化输入付出一些代价。另一方面,如果您需要执行逐字节分析,那么您可以使用非格式化输入并加快速度。要使sta获得良好性能,您首先要做的事情是标准I/O流对象它关闭与标准C流对象的同步:
std::ios_base::sync_with_stdio(false);
一旦你做到了这一点,你应该会有更好的表现。不过,你是否表现良好是另一个问题
由于一些人声称猫在里面会做些有趣的事情,下面是将一个流复制到另一个流的最快方法:
std::cout << std::cin.rdbuf();
我希望我最终能做到最好…如果你真的想在stdin上有更好的性能,你应该尝试使用纯C
vector<char> line(0x1000);
while(!feof(stdin))
fgets(&line.front(), line.size(), stdin);
矢量线(0x1000);
而(!feof(stdin))
fgets(&line.front(),line.size(),stdin);
<代码> > P>我认为更快的解决方案将基于 > <代码>筛选器范围。SH < /Cord>?为什么不直接调用C++程序?也就是说,该循环的典型模式是“代码>”(STD::GETLIN(STD:CIN,CRTLIN))。{std::cout如果你在寻找性能,你应该尝试C风格的I/O函数,而不是cin/cout;)你用优化编译了吗?-O2或-O3?这可能不会减少44秒,但如果你担心时间问题,那么肯定应该这样做。Rob:是的,你的版本是等效的,更漂亮。我用了它,调用了直接使用脚本,不做任何更改,我的程序不做任何其他事情。我使用的是g++-O3-Wall-c-fmessage length=0-MMD-mpd。您会惊讶地发现,您的通用命令比专门设计用于快速执行操作的专用工具慢。如果您编写的命令是beet cat,那么它将是新的cat。因为您正在执行行处理,所以期望您获得(在您进行大量优化之后)与任何基于行的unix筛选器的速度大致相同。我将此标记为答案,但也阅读了原始问题中的编辑。事实上,sync_with_stdio似乎非常有帮助。它将速度提高了7倍。实际上,这是一款黄金级的产品,因为它使cin的速度仅为fgets的2倍,另外一个好处是您不需要知道最大行长。…还有像这样的“优化”吗?:)没有,没有这么简单的了。我在某处有自己的IOStreams实现,它做了很多有趣的优化,但它的不完整状态现在对你没有帮助。不过,我仍然希望在某个时候得到它…;)
vector<char> line(0x1000);
while(!feof(stdin))
fgets(&line.front(), line.size(), stdin);