<i id='NyG2z'><tr id='NyG2z'><dt id='NyG2z'><q id='NyG2z'><span id='NyG2z'><b id='NyG2z'><form id='NyG2z'><ins id='NyG2z'></ins><ul id='NyG2z'></ul><sub id='NyG2z'></sub></form><legend id='NyG2z'></legend><bdo id='NyG2z'><pre id='NyG2z'><center id='NyG2z'></center></pre></bdo></b><th id='NyG2z'></th></span></q></dt></tr></i><div id='NyG2z'><tfoot id='NyG2z'></tfoot><dl id='NyG2z'><fieldset id='NyG2z'></fieldset></dl></div>

    <small id='NyG2z'></small><noframes id='NyG2z'>

    <legend id='NyG2z'><style id='NyG2z'><dir id='NyG2z'><q id='NyG2z'></q></dir></style></legend>
  1. <tfoot id='NyG2z'></tfoot>

      • <bdo id='NyG2z'></bdo><ul id='NyG2z'></ul>

      如何让 IOStream 性能更好?

      时间:2023-09-16
      • <i id='px0Rm'><tr id='px0Rm'><dt id='px0Rm'><q id='px0Rm'><span id='px0Rm'><b id='px0Rm'><form id='px0Rm'><ins id='px0Rm'></ins><ul id='px0Rm'></ul><sub id='px0Rm'></sub></form><legend id='px0Rm'></legend><bdo id='px0Rm'><pre id='px0Rm'><center id='px0Rm'></center></pre></bdo></b><th id='px0Rm'></th></span></q></dt></tr></i><div id='px0Rm'><tfoot id='px0Rm'></tfoot><dl id='px0Rm'><fieldset id='px0Rm'></fieldset></dl></div>
          <tbody id='px0Rm'></tbody>

        <small id='px0Rm'></small><noframes id='px0Rm'>

        • <bdo id='px0Rm'></bdo><ul id='px0Rm'></ul>
          <tfoot id='px0Rm'></tfoot>
          <legend id='px0Rm'><style id='px0Rm'><dir id='px0Rm'><q id='px0Rm'></q></dir></style></legend>
              1. 本文介绍了如何让 IOStream 性能更好?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                问题描述

                大多数学习 C 的 C++ 用户更喜欢使用 printf/scanf 系列函数,即使他们在使用 C++ 编码.

                虽然我承认我发现界面更好(尤其是类似 POSIX 的格式和本地化),但似乎压倒性的关注是性能.

                看看这个问题:

                <块引用>

                如何加快逐行读取文件的速度

                似乎最好的答案是使用 fscanf 并且 C++ ifstream 始终慢 2-3 倍.

                我认为如果我们可以编译一个技巧"存储库来提高 IOStreams 性能,哪些有效,哪些无效.

                要考虑的要点

                • 缓冲 (rdbuf()->pubsetbuf(buffer, size))
                • 同步(std::ios_base::sync_with_stdio)
                • 语言环境处理(我们可以使用精简的语言环境,还是完全删除它?)

                当然,欢迎使用其他方法.

                注意:提到了 Dietmar Kuhl 的新"实现,但我无法找到有关它的许多细节.以前的参考文献似乎是死链接.

                解决方案

                这是我目前收集到的:

                缓冲:

                如果默认缓冲区很小,增加缓冲区大小肯定可以提高性能:

                • 它减少了硬盘命中次数
                • 减少系统调用次数

                可以通过访问底层的streambuf实现来设置缓冲区.

                char Buffer[N];std::ifstream 文件("file.txt");file.rdbuf()->pubsetbuf(Buffer, N);//保证 rdbuf 的指针读取器//构造函数成功后非空

                @iavr 提供的警告:根据 cppreference最好在打开文件之前调用 pubsetbuf.否则,各种标准库实现具有不同的行为.

                区域设置处理:

                Locale 可以执行字符转换、过滤以及涉及数字或日期的更聪明的技巧.它们经历了一个复杂的动态调度和虚拟调用系统,因此删除它们有助于减少惩罚.

                默认的 C 语言环境旨在不执行任何转换以及跨机器统一.这是一个很好的默认使用.

                同步:

                我看不到使用此工具的任何性能改进.

                可以使用sync_with_stdio 静态函数访问全局 设置(std::ios_base 的静态成员).

                测量:

                玩这个,我玩弄了一个简单的程序,使用 gcc 3.4.2 在 SUSE 10p3 和 -O2 上编译.

                <块引用>

                C : 7.76532e+06
                C++:1.0874e+07

                对于默认代码,这代表了大约 20%... 的减速.实际上,篡改缓冲区(在 C 或 C++ 中)或同步参数 (C++) 并没有产生任何改进.

                其他人的结果:

                <块引用>

                @Irfy on g++ 4.7.2-2ubuntu1,-O3,虚拟化 Ubuntu 11.10,3.5.0-25-generic,x86_64,足够的 ram/cpu,196MB 的几个find/>> largefile.txt"运行

                C:634572C++:473222

                C++ 快 25%

                <块引用>

                @Matteo Italia 在 g++ 4.4.5、-O3、Ubuntu Linux 10.10 x86_64 上使用一个随机的 180 MB 文件

                电话:910390
                C++:776016

                C++ 快 17%

                <块引用>

                @Bogatyr on g++ i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1(Apple Inc. build 5664),mac mini,4GB 内存,空闲,除了这个测试有 168MB 数据文件

                C : 4.34151e+06
                C++:9.14476e+06

                C++ 慢 111%

                <块引用>

                @Asu on clang++ 3.8.0-2ubuntu4、Kubuntu 16.04 Linux 4.8-rc3、8GB ram、i5 Haswell、Crucial SSD、88MB 数据文件(tar.xz 存档)

                C : 270895C++:162799

                C++ 快 66%

                所以答案是:这是一个实施质量问题,实际上取决于平台:/

                对于那些对基准测试感兴趣的人,这里有完整的代码:

                #include #include #include #include <cmath>#include #include 模板 双基准(Func f,size_t 迭代){F();时间值 a, b;gettimeofday(&a, 0);for (; 迭代 --> 0;){F();}gettimeofday(&b, 0);返回 (b.tv_sec * (unsigned int)1e6 + b.tv_usec) -(a.tv_sec * (unsigned int)1e6 + a.tv_usec);}结构 CRead{CRead(char const* 文件名): _filename(filename) {}无效运算符()(){FILE* file = fopen(_filename, "r");整数计数 = 0;while ( fscanf(file,"%s", _buffer) == 1 ) { ++count;}fclose(文件);}字符常量* _文件名;字符_缓冲区[1024];};结构 CppRead{CppRead(char const* filename): _filename(filename), _buffer() {}枚举 { BufferSize = 16184 };无效运算符()(){std::ifstream 文件(_filename, std::ifstream::in);//删除扩展缓冲区的注释file.rdbuf()->pubsetbuf(_buffer, BufferSize);整数计数 = 0;std::string s;而(文件>> s){ ++计数;}}字符常量* _文件名;char _buffer[BufferSize];};int main(int argc, char* argv[]){size_t 迭代次数 = 1;if (argc > 1) { 迭代 = atoi(argv[1]);}char const* oldLocale = setlocale(LC_ALL,"C");如果(strcmp(oldLocale,C")!= 0){std::cout <<替换了旧的语言环境"<<oldLocale<<"' by 'C'
                ";}char const* 文件名 = "大文件.txt";CRead 读取(文件名);CppRead cppread(文件名);//注释以使用默认设置bool oldSyncSetting = std::ios_base::sync_with_stdio(false);双 ctime = 基准(创建,迭代);双 cpptime = 基准(cppread,迭代);//如果注释了 oldSyncSetting 的声明,则注释std::ios_base::sync_with_stdio(oldSyncSetting);std::cout <<C:"<<时间<<"
                "C++:"<<cpptime<<"
                ";返回0;}

                Most C++ users that learned C prefer to use the printf / scanf family of functions even when they're coding in C++.

                Although I admit that I find the interface way better (especially POSIX-like format and localization), it seems that an overwhelming concern is performance.

                Taking at look at this question:

                How can I speed up line by line reading of a file

                It seems that the best answer is to use fscanf and that the C++ ifstream is consistently 2-3 times slower.

                I thought it would be great if we could compile a repository of "tips" to improve IOStreams performance, what works, what does not.

                Points to consider

                • buffering (rdbuf()->pubsetbuf(buffer, size))
                • synchronization (std::ios_base::sync_with_stdio)
                • locale handling (Could we use a trimmed-down locale, or remove it altogether ?)

                Of course, other approaches are welcome.

                Note: a "new" implementation, by Dietmar Kuhl, was mentioned, but I was unable to locate many details about it. Previous references seem to be dead links.

                解决方案

                Here is what I have gathered so far:

                Buffering:

                If by default the buffer is very small, increasing the buffer size can definitely improve the performance:

                • it reduces the number of HDD hits
                • it reduces the number of system calls

                Buffer can be set by accessing the underlying streambuf implementation.

                char Buffer[N];
                
                std::ifstream file("file.txt");
                
                file.rdbuf()->pubsetbuf(Buffer, N);
                // the pointer reader by rdbuf is guaranteed
                // to be non-null after successful constructor
                

                Warning courtesy of @iavr: according to cppreference it is best to call pubsetbuf before opening the file. Various standard library implementations otherwise have different behaviors.

                Locale Handling:

                Locale can perform character conversion, filtering, and more clever tricks where numbers or dates are involved. They go through a complex system of dynamic dispatch and virtual calls, so removing them can help trimming down the penalty hit.

                The default C locale is meant not to perform any conversion as well as being uniform across machines. It's a good default to use.

                Synchronization:

                I could not see any performance improvement using this facility.

                One can access a global setting (static member of std::ios_base) using the sync_with_stdio static function.

                Measurements:

                Playing with this, I have toyed with a simple program, compiled using gcc 3.4.2 on SUSE 10p3 with -O2.

                C : 7.76532e+06
                C++: 1.0874e+07

                Which represents a slowdown of about 20%... for the default code. Indeed tampering with the buffer (in either C or C++) or the synchronization parameters (C++) did not yield any improvement.

                Results by others:

                @Irfy on g++ 4.7.2-2ubuntu1, -O3, virtualized Ubuntu 11.10, 3.5.0-25-generic, x86_64, enough ram/cpu, 196MB of several "find / >> largefile.txt" runs

                C : 634572 C++: 473222

                C++ 25% faster

                @Matteo Italia on g++ 4.4.5, -O3, Ubuntu Linux 10.10 x86_64 with a random 180 MB file

                C : 910390
                C++: 776016

                C++ 17% faster

                @Bogatyr on g++ i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664), mac mini, 4GB ram, idle except for this test with a 168MB datafile

                C : 4.34151e+06
                C++: 9.14476e+06

                C++ 111% slower

                @Asu on clang++ 3.8.0-2ubuntu4, Kubuntu 16.04 Linux 4.8-rc3, 8GB ram, i5 Haswell, Crucial SSD, 88MB datafile (tar.xz archive)

                C : 270895 C++: 162799

                C++ 66% faster

                So the answer is: it's a quality of implementation issue, and really depends on the platform :/

                The code in full here for those interested in benchmarking:

                #include <fstream>
                #include <iostream>
                #include <iomanip>
                
                #include <cmath>
                #include <cstdio>
                
                #include <sys/time.h>
                
                template <typename Func>
                double benchmark(Func f, size_t iterations)
                {
                  f();
                
                  timeval a, b;
                  gettimeofday(&a, 0);
                  for (; iterations --> 0;)
                  {
                    f();
                  }
                  gettimeofday(&b, 0);
                  return (b.tv_sec * (unsigned int)1e6 + b.tv_usec) -
                         (a.tv_sec * (unsigned int)1e6 + a.tv_usec);
                }
                
                
                struct CRead
                {
                  CRead(char const* filename): _filename(filename) {}
                
                  void operator()() {
                    FILE* file = fopen(_filename, "r");
                
                    int count = 0;
                    while ( fscanf(file,"%s", _buffer) == 1 ) { ++count; }
                
                    fclose(file);
                  }
                
                  char const* _filename;
                  char _buffer[1024];
                };
                
                struct CppRead
                {
                  CppRead(char const* filename): _filename(filename), _buffer() {}
                
                  enum { BufferSize = 16184 };
                
                  void operator()() {
                    std::ifstream file(_filename, std::ifstream::in);
                
                    // comment to remove extended buffer
                    file.rdbuf()->pubsetbuf(_buffer, BufferSize);
                
                    int count = 0;
                    std::string s;
                    while ( file >> s ) { ++count; }
                  }
                
                  char const* _filename;
                  char _buffer[BufferSize];
                };
                
                
                int main(int argc, char* argv[])
                {
                  size_t iterations = 1;
                  if (argc > 1) { iterations = atoi(argv[1]); }
                
                  char const* oldLocale = setlocale(LC_ALL,"C");
                  if (strcmp(oldLocale, "C") != 0) {
                    std::cout << "Replaced old locale '" << oldLocale << "' by 'C'
                ";
                  }
                
                  char const* filename = "largefile.txt";
                
                  CRead cread(filename);
                  CppRead cppread(filename);
                
                  // comment to use the default setting
                  bool oldSyncSetting = std::ios_base::sync_with_stdio(false);
                
                  double ctime = benchmark(cread, iterations);
                  double cpptime = benchmark(cppread, iterations);
                
                  // comment if oldSyncSetting's declaration is commented
                  std::ios_base::sync_with_stdio(oldSyncSetting);
                
                  std::cout << "C  : " << ctime << "
                "
                               "C++: " << cpptime << "
                ";
                
                  return 0;
                }
                

                这篇关于如何让 IOStream 性能更好?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                上一篇:为什么编译器可以比普通函数更好地优化 lambda 下一篇:什么更有效?使用 pow 平方或只是乘以它自己?

                相关文章

                最新文章

                <tfoot id='r7N2J'></tfoot>
              2. <i id='r7N2J'><tr id='r7N2J'><dt id='r7N2J'><q id='r7N2J'><span id='r7N2J'><b id='r7N2J'><form id='r7N2J'><ins id='r7N2J'></ins><ul id='r7N2J'></ul><sub id='r7N2J'></sub></form><legend id='r7N2J'></legend><bdo id='r7N2J'><pre id='r7N2J'><center id='r7N2J'></center></pre></bdo></b><th id='r7N2J'></th></span></q></dt></tr></i><div id='r7N2J'><tfoot id='r7N2J'></tfoot><dl id='r7N2J'><fieldset id='r7N2J'></fieldset></dl></div>

                <small id='r7N2J'></small><noframes id='r7N2J'>

                  <bdo id='r7N2J'></bdo><ul id='r7N2J'></ul>

                  1. <legend id='r7N2J'><style id='r7N2J'><dir id='r7N2J'><q id='r7N2J'></q></dir></style></legend>