Giter Site home page Giter Site logo

测试不完整/不公正 about fast_io HOT 87 CLOSED

cppfastio avatar cppfastio commented on June 27, 2024
测试不完整/不公正

from fast_io.

Comments (87)

trcrsired avatar trcrsired commented on June 27, 2024 5

14岁的oj小朋友没事就回去学习,不要在这浪费时间上网打游戏。

何况现在不进国家队也没有保送了,你在这吹个毛B呢。

from fast_io.

24bit-xjkp avatar 24bit-xjkp commented on June 27, 2024 4

先来看看从fast_io中学习经验的MyStd在整数转字符串上的性能
clang -std=c++2b -flto=thin -fuse-ld=lld -Ofast -march=native .\ItoaSpeedTest.cpp -Xlinker /subsystem:console
结果:

MyStd::itoa costed 0.017900ms
::itoa costed 0.346200ms
::_itoa_s costed 0.247000ms
::sprintf costed 0.957400ms
::sprintf_s costed 1.165300ms
std::to_string costed 0.132000ms
std::ostringstream::str costed 4.821200ms
std::ostringstream::operator>> costed 8.194000ms
ItoaSpeedTest is successful.

ItoaSpeedTest.txt
测试源代码在这了。。。
能测出stdio比fast_io快,好好反思一下测试怎么写的。

from fast_io.

AbrasiveBoar902 avatar AbrasiveBoar902 commented on June 27, 2024 3

你封装了你这一堆再测,我只希望看到一行print之类的调用
封装不了还有什么可比的

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024 2
#include<fast_io.h>
#include<fast_io_legacy.h>
int main() {
  fast_io::timer tm(u8"fast_io");
  fast_io::filebuf_file fbf(u8"fastio.txt",fast_io::open_mode::out);
  for(std::size_t i{};i!=10000000;++i)
    print(fbf,"Hello World");
}

这么测的小朋友。你测流的性能搞毛呢???

同时要加-O2
你也可以尝试-flto -march=native -Ofast -s

之后甚至可以-fprofile-generate
-fprofile-use

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024 2

好好好,下面上你要的 stdio 测试结果。事情越来越迷惑了。
以下是使用 stdio 进行写文件的情况。为了防止长度优化,我执行了一次 strlen。
编译参数和之前的差不多。
stdio.cpp:

#include <cstring>
#include <cstdio>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"stdio");
  char buf[10240 * 10 + 1];
  const char* w = "Hello World";
  size_t ptr = 0;
  FILE* fout = fopen("stdio.txt", "w");
  for(size_t i = 0;i != 10000000; ++i) {
    size_t len = strlen(w);
    if (ptr + len >= sizeof(buf) / sizeof(char)) {
      fwrite(buf, sizeof(char), ptr, fout);
      ptr = 0;
    }
    memcpy(buf + ptr, w, len);
    ptr += len;
  }
  if (ptr) {
    fwrite(buf, sizeof(char), ptr, fout);
  }
  fclose(fout);
}

编译参数:

clang++ -std=c++2b -I../include -O2 fast_io.cc -o fast_io --save-temps && clang++ -std=c++2b -I../include -O2 stdio.cpp -o stdio --save-temps

测试结果(为方便计算我就不上图片了):

# rm -rf *.txt && ./fast_io && ./stdio && du fastio.txt stdio.txt && diff fastio.txt stdio.txt -s
fast_io:0.200083769s
stdio (mixed):0.19944s
107424  fastio.txt
107424  stdio.txt
文件 fastio.txt 和 stdio.txt 相同
# rm -rf *.txt && \time -v ./fast_io && \time -v ./stdio && du fastio.txt stdio.txt && diff fastio.txt stdio.txt -s
fast_io:0.248277461s
        Command being timed: "./fast_io"
        User time (seconds): 0.08
        System time (seconds): 0.16
        Percent of CPU this job got: 97%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.25
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 2772
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 153
        Voluntary context switches: 21
        Involuntary context switches: 25
        Swaps: 0
        File system inputs: 0
        File system outputs: 214848
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
stdio (mixed):0.188824692s
        Command being timed: "./stdio"
        User time (seconds): 0.02
        System time (seconds): 0.12
        Percent of CPU this job got: 76%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.19
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 2528
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 138
        Voluntary context switches: 12
        Involuntary context switches: 10
        Swaps: 0
        File system inputs: 0
        File system outputs: 214848
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
107424  fastio.txt
107424  stdio.txt
文件 fastio.txt 和 stdio.txt 相同

至于为什么 fast_io 的优化突然不翼而飞了,我百思不得其解。
追记:stdio 变为 stdio (mixed) 的原因是我在源文件上还测试了动态 std::string 初始化(性能拉跨),更正代码为最新源文件时忘记把名字改回来了。

你这个strlen早就被编译器优化成常数了。fwrite这么写与write就没区别。

strlen 不是 constexpr,std::size 是,而 std::size 不适用于此情况。

你要测就直接测流fout<<"Hello World" 对比print(fbf,"Hello World");的性能。我都没看到你从哪里有这个代码。之前测的故意不展示了。拿你自己直接手工艹还能控制字符串长度。

strlen是编译器后门,编译器知道多长。和常量表达式没有任何关系

from fast_io.

havedifficultyinfindingnames avatar havedifficultyinfindingnames commented on June 27, 2024 2

去查看库中以下概念:reserve_printabledynamic_reserve_printablescatter_printable,以及相关数据结构。你如果库本身都不会用,何来资格去评判他?

from fast_io.

YexuanXiao avatar YexuanXiao commented on June 27, 2024 1

腾讯阿里百度华为都有使用C++20的项目,企业不代表老旧代码。等你在C++的学习上的更进一步,就可能会理解iostream的问题所在(或者和少部分人一样永远不能理解,甚至和大部分人一样放弃C++),fastio无疑是目前在安全性,效率和易用性得到了最好的平衡的IO库(好于fmt和iostream)。此外OI的代码不能产生任何价值,OI的代码也不具备任何参考价值。希望你能尽快的度过中二时期,重新审视自身的水平(尤其是C++),以学习为中心,而不是进行这种幼稚而且没营养的讨论,因此关闭该issue。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024 1

你脑子有病就回家吃药。

未将 Intel C++ 加入比较(C++ 11 比 C++ 20 可能不妥,但是性能第一位)。

首先Intel早就换clang了,intel oneapi compiler早就是clang套壳,有那个时间折腾前端,还不如向llvm贡献代码。
事实就算用icc根本不可能对性能有任何的改变和影响。因为所有标准库的实现iostream是已经编译好的二进制,通常编译器都是实现成动态链接库,你用这个库不过是链接上去。用任何编译器,只要调用规范一样,生成的指令都完全一样。如果你连编译和链接的区别都搞不清还是回家吃药去吧。

未将其余同属 Windows GCC 实现的编译器加入对比列表,而却挑中表现最一般的 MinGW-w64。

mingw-w64就是windows gcc的libc,这个项目除了自己为了msvcrt补了一部分东西(例如stdio的C99支持以外)其他的东西都是微软提供的,特别是ucrt.
与微软编译器的不同主要还是C++标准库的运行时。微软用的是MSVC STL,GCC用的是和linux一样的libstdc++
你要是分不清binutils-gdb libc, linux内核头文件,gcc的区别还是建议一边玩去。

未能提供(尽量)统一的编译参数。

不论什么编译参数,性能都远远快于iostream 不服你自己测去,我们拿数据你自己也不信那就自己测去。

在提及 Rust 编程语言的速度时,未提及使用 Debug 还是使用 Release 编译。

搞笑了。我怎么可能用debug给你测性能?

iostream 包含后暴增 800 K

以 gcc 为例,请在编译参数加入 -s(或更为激进的-Os -s),然后再试一次。支持 Release 版的,请用 Release 版。您要是禁用了优化或者只开了 -O1、带了符号表和调试信息,我无话可说。

我当然加了-s,不仅-s还-flto -Ofast

gcc根本没有release一说。对你不懂的东西就闭嘴。

我猜你测这玩意连-static-libstdc++选项都不知道加,在这满地打滚。iostream大量的亡虚函数,等于说整个标准库全家桶,全死在编译好的libstdc++.a或是libstdc++-6.dll里了。很多平台根本不能动态链接(例如wasm,各类嵌入式,安卓等)libstdc++,怎么可能不大?

#include<fast_io.h>

int main()
{
        print("Hello World\n");
}
#include<iostream>

int main()
{
        std::cout<<"Hello World\n";
}
g++ -o iostream iostream.cc -Oz -std=c++23 -static-libstdc++ -s -flto
g++ -o fast_io helloworld.cc -Oz -std=c++23 -static-libstdc++ -s -flto
-rwxrwxr-x 1 cqwrteur cqwrteur  23112 Jan 27 13:06 fast_io
-rwxrwxr-x 1 cqwrteur cqwrteur 843296 Jan 27 13:05 iostream

你告诉我这不是800kb是什么?你眼瞎了?

您的行为等同于 Typescript + class 已经过时,建议使用 JavaScript function + Type description / interface。

此外,您几乎抛弃了兼容性,而这正是企业代码需要的。想必,您不会轻易在公司的老旧环境上使用 C++ 20 吧。

你的意思是C++标准委员会更新标准叫“抛弃兼容性”。
我又不在乎不用C++20的项目,就像你怎么还用rust呢?

当个人和企业都不(愿意)广泛使用 fast_io 时,您是卢瑟。

没有人强迫你用。你不尊重别人的劳动,在这骂人。你不是卢瑟谁是卢瑟。

是的,论数值计算模板元被 constexpr 可读性完爆,但是请您用 constexpr 函数,不用 template 关键字来遍历元组。

搞笑了。std::tuple本身就是个笑话。性能都不如直接写个struct.没事找事吧你。

您搞错了此选项的意思。请确认自己包含的头文件/用到的特性是否含在这些已提供的头文件中。

我还提到了特性,也就是说您可能需要添加额外的禁用参数来避免这些特性被默认打开,这样才能正常编译。

更多的偏见由于时间问题不再叙述。

你在这说什么你完全不懂的东西呢?

--disable-hosted-libstdcxx是编译构建独立C++,和异常不异常就没毛关系。还有你扯iostream向前兼容,iostream都不独立。你说你连个本地,交叉,加拿大编译都搞不出来,在这扯--disable-hosted-libstdcxx

https://en.cppreference.com/w/cpp/freestanding

相反fast_io是独立库,不需要任何宿主功能就能运行。

不懂就拿这个工具链你去看下,看看有没有什么iostream
https://github.com/trcrsired/windows-hosted-x86_64-elf-toolchains

链表淘汰了

您要是可以把数组(一定确保是连续内存)的插入时间复杂度变成 O(1),可能学 OI 的人都要跪下来叫您爷爷。

第一。链表的插入时间是不是O(1)根本没有意义。因为链表虽然按随机访问这种抽象机下插入时间为Θ(1),然而往往遍历到插入的点位本身的时间却是Θ(N)。一个典型的例子就是约瑟夫环,虽然插入是Θ(1)但遍历N次到下一个节点。实际的时间复杂度却是Θ(N+1)=Θ(N).
而数组,虽然插入的时间是Θ(N),但遍历的时间却是Θ(1)。总时间复杂度仍然是Θ(N+1)=Θ(N)。而数组的缓存命中率更高,加之省空间,甚至可以硬件simd指令加速复制,实际的性能远远高于链表。

第二。谁告诉你访问随机地址叫Θ(1)的,没有抽象机有意义?在现代处理器上有多级缓存加页表一类的。访问随机地址的开销实际就不可能是Θ(1) 。有人说是O(sqrt(N))。不管怎样,Θ(1)就不可能严格意义上正确

第三。链表还有其他很多额外的开销。堆分配的开销。内存碎片的开销。本身链表多的指针域也会浪费大量内存空间。这些开销都是巨大的。

您的 fast_io 固然比流式 I/O 快,但无可否认地后者文档和实例多得数不胜数,并且提供了很棒的前向兼容性。在这一点上,您的 fast_io 毫无疑问地完败给了您看不起的流式 I/O。

搞笑了。fast_io本身就是流式I/O. iostream不过是一种具体的实现。就像标准库list实现了双向链表,你自己写个双向链表就不是双向链表了?
前向兼容性?搞笑了。你让iostream运行在pdp11, avr, linux内核,windows内核一类的再来哗好吧。
fast_io什么时候不支持对iostream加速了?你确定你用过这个库?没用过你扯毛。

而现在提出的 I/O 提速虽然性能高但却不能贸然使用。因为换用 fast_io 的成本过高,且不是每个人都使用 C++ 20。

又是I/O性能不重要论。脑残言论不值得一驳。你不用C++23就去更新编译器,不要在我这浪费时间谢谢。

还是这话,没人强迫你用,不服性能就自己测。不服功能就自己写。别浪费别人时间。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024 1

测完了,跑分结果确实有问题。

以下使用默认优化参数/动态链接,测定两次 fast_io 和 std::fstream 完成 1M 数据写入的速度。

后台所有无关进程和网络连接(包括本地)已被挂起,以减小测量误差。

以下是 fast_io 的测试代码:

#include<fast_io.h>                                               #include<fast_io_device.h>
#include<fast_io_legacy.h>                                        #include<fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"fast_io");
  fast_io::filebuf_file fbf(u8"fastio.txt",fast_io::open_mode::out);
  std::ostream fout(fbf.fb);
  for(std::size_t i{};i!=10000000;++i)
    fout<<"Hello World";
}

以下是 std::fstream 的测试代码:

#include <fstream>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"fstream");
  std::ofstream fout("fstream.txt");
  for(std::size_t i{};i!=10000000;++i)
    fout<<"Hello World";
}

Screenshot_1

如图,使用如上参数编译后分别进行测试,fast_io 和 std::fstream 区别不明显(fast_io 比 std::fstream 慢 0.009496769s,可算作误差)。

Screenshot_2

如图,使用 time 工具进行速度对比,此时 fast_io 与 std::fstream 速度差异较为明显(fast_io 比 std::fstream 慢 0.066591615s)。

此外,我们还关注到上下文切换的次数。在此次测试中,fast_io 的上下文切换次数是 std::fstream 的 3 2⁄3 倍,这意味着 fast_io 的成本在 ARM/ARM64 Linux 上更高昂,且吃力不讨好。

我使用了 chroot 容器,以下是它们两个的 uname 数据。

chroot 容器:

Linux kali 4.14.186-perf-gf74b69998c5c #1 SMP PREEMPT Tue Jul 12 20:48:38 CST 2022 aarch64 GNU/Linux

宿主:

Linux kali 4.14.186-perf-gf74b69998c5c #1 SMP PREEMPT Tue Jul 12 20:48:38 CST 2022 aarch64 Android

你不开优化扯毛蛋呢

iostream本身已经是-O2优化的了。

from fast_io.

24bit-xjkp avatar 24bit-xjkp commented on June 27, 2024 1

别的不说,部分ostream的operator<<会调用sprintf,sprintf可是自己写个循环都能超过的存在。即使没用sprintf,用的也是循环再逆序的实现。而jeaiii/itoa在此方面可以带来巨大的提升。

如图,使用如上参数编译后分别进行测试,fast_io 和 std::fstream 区别不明显(fast_io 比 std::fstream 慢 0.009496769s,可算作误差)。

测出这种离谱的结果先反思自己测试程序有没有写对。用的operator<<明明是ostream的。。。流都没玩明白就别说了。

iostream 包含后暴增 800 K

以 gcc 为例,请在编译参数加入 -s(或更为激进的-Os -s),然后再试一次。支持 Release 版的,请用 Release 版。您要是禁用了优化或者只开了 -O1、带了符号表和调试信息,我无话可说。

加-Oz都没用,libstdc++-v6.a的体积一点少不了。

您的 fast_io 固然比流式 I/O 快,但无可否认地后者文档和实例多得数不胜数,并且提供了很棒的前向兼容性。在这一点上,您的 fast_io 毫无疑问地完败给了您看不起的流式 I/O。

搞笑了,这话就不存在。微软都不敢说它向前兼容怎么样。建议试试win10上跑一个需要msvc++2005的vocaloid3,不装旧版库能跑得起来算我输。你觉得兼容只是装了很多版本的库。实际上自带fast_io/在系统里安装fast_io同样可以兼容。

from fast_io.

24bit-xjkp avatar 24bit-xjkp commented on June 27, 2024 1

链表淘汰了

您要是可以把数组(一定确保是连续内存)的插入时间复杂度变成 O(1),可能学 OI 的人都要跪下来叫您爷爷。

链表在内核中是有广泛的应用(但也不是io),但在用户的io这种场合下是淘汰的,不应该把要io的数据放链表里。

此外,我们还关注到上下文切换的次数。在此次测试中,fast_io 的上下文切换次数是 std::fstream 的 3 2⁄3 倍,这意味着 fast_io 的成本在 ARM/ARM64 Linux 上更高昂,且吃力不讨好。

有没有可能,就是输出到默认设置的流并不能体现fast_io::obuf_file大缓冲区的优势。

我年龄较小,本 issue 也未经过高人指点,若有任何事实错误或表意不清的位置,请不吝赐教。

那就学习去,工程和OI不是一个东西。OI的东西没用实际意义。

面向对象 C with Classes 过时,使用 C with Concepts

您的行为等同于 Typescript + class 已经过时,建议使用 JavaScript function + Type description / interface。

"JavaScript function + Type description / interface"可不是什么值得推广的东西,而且,该淘汰的是JavaScript,给JavaScript加点特性并不能影响它应该被淘汰。而C with Concepts是值得推广的,这解决了模板编程可读性差的问题。可惜C with Classes并不能解决可读性的问题,意大利面条代码很大程度上是滥用oop导致的。关于这一结论,可以在讨论编程范式的文章里找到。可以说,是很多人提倡oop,但反对继承的人依然很多。即使你能严格遵循里氏替换规则,也不意味着继承等oop特性就能带来更多的可读性。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024 1

fast_io的六级文件

wine_file 对应wine层的文件。非缓冲流,进程安全。
nt_file 对应nt层的文件。非缓冲流,进程安全。
win32_file 对应win32层的文件。非缓冲流,进程安全。
posix_file 对应posix层的文件。非缓冲流,进程安全。
c_file 对应c层的文件。缓冲上锁流,线程安全,进程不安全。
filebuf_file 对应C++标准库流缓冲层的文件。缓冲流,线程进程都不安全。

从下级到上级移动(例如用nt句柄构造C++标准库文件流),上级到下级强制转换(例如得到fstream里的FILE*,或是fd或是HANDLE或是wine的平台fd)。

native_file在windows为win32_file,其他平台(包括cygwin)都是posix_file。

basic_obuf是给文件类型加缓冲的。

例如obuf_file是basic_obuf<native_file>等于只是在native_file上加了层缓冲而已。不考虑与stdio和fstream共用的情况的时,根本就没有理由用filebuf_file

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024 1

你这种带模板的定长串的输出方式本身就是问题,C++模板一个长度就会生成一个函数。把数组放模板里本来就是问题。你见过哪个库这么干的?字符串长度的可能性是无穷多种的,你每个都生成一份,代码不能合并导致体积炸妈,进而性能炸妈,就不是性能问题了??你这个api设计就有问题,因而基于这样的测的方式都有问题。

其次,终于承认输出整数“明显慢于fast_io”了?当性能慢于fast_io的时候你连数据都不列出了。说是摆烂。fast_io::concat是你这样用的?亲,初中生回去学习吧,不要在这浪费时间。

什么狗屁“内联”,C++里的内联指的是防ODR违反。函数都展开就比不展开快了,多出来的指令二进制体积被你吃了?间接造成上层函数体积增加,开销比你想的大的多的多。

安卓不是libc++就出鬼了。除非你是静态链接。libstdc++根本就不支持bionic

from fast_io.

YexuanXiao avatar YexuanXiao commented on June 27, 2024 1

你这种带模板的定长串的输出方式本身就是问题,C++模板一个长度就会生成一个函数。把数组放模板里本来就是问题。你见过哪个库这么干的?字符串长度的可能性是无穷多种的,你每个都生成一份,代码不能合并导致体积炸妈,进而性能炸妈,就不是性能问题了??你这个api设计就有问题,因而基于这样的测的方式都有问题。
其次,终于承认输出整数“明显慢于fast_io”了?当性能慢于fast_io的时候你连数据都不列出了。说是摆烂。fast_io::concat是你这样用的?亲,初中生回去学习吧,不要在这浪费时间。
什么狗屁“内联”,C++里的内联指的是防ODR违反。函数都展开就比不展开快了,多出来的指令二进制体积被你吃了?间接造成上层函数体积增加,开销比你想的大的多的多。
安卓不是libc++就出鬼了。除非你是静态链接。libstdc++根本就不支持bionic

# ldd stdio
          linux-vdso.so.1 (0x0000007764bcd000)
          libstdc++.so.6 => /lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000007764940000)
          libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x00000077648a0000)
          libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000007764860000)                  libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x00000077646b0000)
          /lib/ld-linux-aarch64.so.1 (0x0000007764b90000)

请不要陷入无意义的争论。fast_io所有的benchmark测试代码都在benchmark目录下。请提交你的代码以及你的测试结果。在提交代码前请注意:fast_io目标是建立一个通用的输入输出库,我认为如果fast_io/stdio/iostream可以在10行内解决的代码,人们是不会愿意手写20行来实现相同的功能。

你这讲的,好比格式化日期。

如果我是商业应用,我不会傻到去用格式化库。

如果我是个人应用,我也不会为了这点性能就加上一个第三方库。

你要是整个 LD_PRELOAD 库,劫持 sprintf 等 glibc 操作并将其换成更为优化的实现,这样只要一加上 LD_PRELOAD 甚至能给 C 语言和非 C/C++ 语言程序提速,那肯定没人骂你。

但是你搞个基于 C++ 20 不说(ABI 不兼容),还和旧范式完全不兼容(能兼容,能提速吗?),那就跟个鸡肋一样食之无味弃之可惜,作者还个个跟贴吧老哥一样,那就肯定被骂了。

加上各位的测试建立在开优化的基础上,可惜很多工程不开 -O2,也没有测试时那么激进的编译参数。

不要学了几个词就在这乱说,ABI兼不兼容就是个狗屁问题,gcc从2003年到现在就用的一个ABI,clang从2005年出生就用的一个ABI。微软的MSVC自从能编译amd64程序开始就是一个ABI,在网上听风就是雨扯毛呢,符号名的重整方法在这些年里从来没改过,网上那些说C++ABI不兼容的弱智根本就不知道这是C++类型安全的表现,放C里瞎jb链接运行时再报错有意思?你给我解释解释为什么Linux内核和glibc不能随便升级?

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024 1

你这种带模板的定长串的输出方式本身就是问题,C++模板一个长度就会生成一个函数。把数组放模板里本来就是问题。你见过哪个库这么干的?字符串长度的可能性是无穷多种的,你每个都生成一份,代码不能合并导致体积炸妈,进而性能炸妈,就不是性能问题了??你这个api设计就有问题,因而基于这样的测的方式都有问题。
其次,终于承认输出整数“明显慢于fast_io”了?当性能慢于fast_io的时候你连数据都不列出了。说是摆烂。fast_io::concat是你这样用的?亲,初中生回去学习吧,不要在这浪费时间。
什么狗屁“内联”,C++里的内联指的是防ODR违反。函数都展开就比不展开快了,多出来的指令二进制体积被你吃了?间接造成上层函数体积增加,开销比你想的大的多的多。
安卓不是libc++就出鬼了。除非你是静态链接。libstdc++根本就不支持bionic

# ldd stdio
          linux-vdso.so.1 (0x0000007764bcd000)
          libstdc++.so.6 => /lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000007764940000)
          libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x00000077648a0000)
          libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000007764860000)                  libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x00000077646b0000)
          /lib/ld-linux-aarch64.so.1 (0x0000007764b90000)

请不要陷入无意义的争论。fast_io所有的benchmark测试代码都在benchmark目录下。请提交你的代码以及你的测试结果。在提交代码前请注意:fast_io目标是建立一个通用的输入输出库,我认为如果fast_io/stdio/iostream可以在10行内解决的代码,人们是不会愿意手写20行来实现相同的功能。

你这讲的,好比格式化日期。
如果我是商业应用,我不会傻到去用格式化库。
如果我是个人应用,我也不会为了这点性能就加上一个第三方库。
你要是整个 LD_PRELOAD 库,劫持 sprintf 等 glibc 操作并将其换成更为优化的实现,这样只要一加上 LD_PRELOAD 甚至能给 C 语言和非 C/C++ 语言程序提速,那肯定没人骂你。
但是你搞个基于 C++ 20 不说(ABI 不兼容),还和旧范式完全不兼容(能兼容,能提速吗?),那就跟个鸡肋一样食之无味弃之可惜,作者还个个跟贴吧老哥一样,那就肯定被骂了。
加上各位的测试建立在开优化的基础上,可惜很多工程不开 -O2,也没有测试时那么激进的编译参数。

不要学了几个词就在这乱说,ABI兼不兼容就是个狗屁问题,gcc从2003年到现在就用的一个ABI,clang从2005年出生就用的一个ABI。微软的MSVC自从能编译amd64程序开始就是一个ABI,在网上听风就是雨扯毛呢,符号名的重整方法在这些年里从来没改过,网上那些说C++ABI不兼容的弱智根本就不知道这是C++类型安全的表现,放C里瞎jb链接运行时再报错有意思?你给我解释解释为什么Linux内核和glibc不能随便升级?

加我qq811452018,我把你加回来吧。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

人没了。我就看到一部分。

我不是大厨就不能评价厨师炒的菜烂了?另外,在 GitHub 发表 issue 不违法,因为不涉政。

你都没吃过这个菜,说人家厨师炒的烂。何况人家请你吃了?爱用用不用滚。

不违法也不代表你有权利在github上发issue。使用github是特权不是你的权利。根据github的规定,到别的项目刷屏完全可以举报你封了。

既然我说的是链表,您就不能拿无法扩容的栈上数组跟其作比较。

想必在空间不够导致触发重新分配的时候,您也能站出来说性能远高于链表。

谁说数组就是在“栈上了”。向量不是一种数组?重新分配又怎样?重新分配以后扩容2倍了。插入平摊后时间复杂度仍然是Θ(1) 就算是重分配,平摊以后单次操作开销仍然远远小于链表。
更何况就OI约瑟夫环一类的问题,一直在删除元素根本不存在重分配问题。
我又不是没测试性能。不懂就去读算法导论平摊分析那章的动态表(就是向量的数据结构,算法导论叫动态表)。

同样存图邻接表就应该用二维向量,而不是第一维向量第二维链表。因为cache不友好,除非图极度稀疏,一个节点就0条或一条边那种情况(我也就见过一次),只要节点平均至少有2个元素链表就不如向量。根本上链表就扯蛋的。事实上所有用链表的情况都能用向量换掉。

shared_ptr 的引用计数开销巨大,建议您脑内维护静态生命周期,非常省成本。

不理解怎么扯到shared_ptr了?事实上双向链表还就不能用shared_ptr,因为会绕环导致整个链表都没被释放。
就fast_io本身而言,智能指针,new/delete,虚函数一类的都是禁止使用的。因为不独立,无法移植。整个库就没shared_ptr,unique_ptr,tuple,string_view,span等等破烂,你在说什么完全无关的东西呢。

你给我找出来这个库什么时候用到shared_ptr, unique_ptr等非独立特性了?搞清楚std::array都不能用。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024
您口无遮拦了。您能举出来很多平台,唯独忘了桌面环境。事实上,C++ 也可以用来开发应用程序,而通常这些应用程序是不需要静态链接的。

这是完全错误的。微软编译器默认就是静态链接ucrt和C++标准库。要加/MD才会动态链接部分代码。而windows10和windows11预装根本就不安装vcruntime 2015-2022,仍然需要用户手工安装vc 2015-2022 redistributable 这就是你所谓的“桌面环境”。这就是为何很多应用都会带着一堆系统库的dll 即便如此微软STL和libc+实现的流仍然要静态链接一部分,并不是都动态链接的,因而现实中仍然开销巨大。

至于说windows上的GCC libstdc++-6.dll的屁事就更多了。且不说libstdc++-6.dll不是微软的东西更不可能安装,光gcc自己线程模型,异常模型就一堆不同的abi,有 win32,posix,mcf之分,三套标准库运行时互相不兼容,还有sjlj dwarf seh一类的屁事。写个程序就拖个2mb的油瓶就不是二进制体积开销了?

linux上glibc版本就炸妈,之后还有musl, bionic等的,都是一堆不同的abi,不仅是C++标准库abi不同,C库都不同。

更何况动态链接就代表开销小了?代价小了?动态链接仍然要重定位,即使加-fPIC仍然要重定位非代码段。32位windows全部都是重定位,而到64位windows才强制-fPIC
不管哪种情况,每个进程都要复制一份。linus torvalds两年前就开骂过这个问题。

https://lore.kernel.org/lkml/CAHk-=whs8QZf3YnifdLv57+FhBi5_WeNTG1B-suOES=RcUSmQg@mail.gmail.com/


Side note: I really wish Fedora stopped doing that.

Shared libraries are not a good thing in general. They add a lot of
overhead in this case, but more importantly they also add lots of
unnecessary dependencies and complexity, and almost no shared
libraries are actually version-safe, so it adds absolutely zero
upside.

Yes, it can save on disk use, but unless it's some very core library
used by a lot of things (ie particularly things like GUI libraries
like gnome or Qt or similar), the disk savings are often not all that
big - and disk is cheap. And the memory savings are often actually
negative (again, unless it's some big library that is typically used
by lots of different programs at the same time).

In this case, for example, it's true that a parallel build will be
running possibly hundreds of copies of clang at the same time - and
they'll all share the shared llvm library. But they'd share those same
pages even if it wasn't a shared library, because it's the same
executable! And the dynamic linking will actually cause a lot _less_
sharing because of all the fixups.

We hit this in the subsurface project too. We had a couple of
libraries that *nobody* else used. Literally *nobody*. But the Fedora
policy meant that a Fedora package had to go the extra mile to make
those other libraries be shared libraries, for actual negative gain,
and a much more fragile end result (since those libraries were in no
way compatible across different versions - so it all had to be updated
in lock-step).

I think people have this incorrect picture that "shared libraries are
inherently good". They really really aren't. They cause a lot of
problems, and the advantage really should always be weighed against
those (big) disadvantages.

Pretty much the only case shared libraries really make sense is for
truly standardized system libraries that are everywhere, and are part
of the base distro.

[ Or, for those very rare programs that end up dynamically loading
rare modules at run-time - not at startup - because that's their
extension model. But that's a different kind of "shared library"
entirely, even if ELF makes the technical distinction between
"loadable module" and "shared library" be a somewhat moot point ]

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

image

from fast_io.

ikspress avatar ikspress commented on June 27, 2024

未将其余同属 Windows GCC 实现的编译器加入对比列表,而却挑中表现最一般的 MinGW-w64。

mingw-w64 就是 win 下最常用、有效率的 libc,TDM-GCC nuwen GCC mingw-builds 之类的仍然是用 mingw-w64 作为它的 libc,mingw-w64 不仅可以用 msvcrt.dll 作为 crt,还可以有 msvcr{80,90,120} ucrt(ucrt 听说只支持 x64,msys2 到现在也只提供 ucrt64 版本)。
win 下还有个 libc,是 cygwin,对 win api 进行了封装来模拟 posix 环境(msys2 的 libc 实际上也是 cygwin,改了个名字而已)。
除了 mingw-w64 和 cygwin 之外,还有 mingw 这个 libc,不过多年无人维护,2022 年(应该是)上半年官网也没了,寿终正寝,libstdc++ 虽然支持 i386-pc-mingw32 目标(triple,三元组),但是它的代码里用了很多 mingw 没有的东西,所以编译会炸掉……TDM-GCC 在编译的时候就打了补丁来修复这个问题 ,具体三者关系可以看这里
GCC 是编译器,mingw-w64(mingw 一般也指的是这个)是libc,mingw 编译器没有特殊需求最好不要用,这个项目早就死了
其他编译器的话,clang 也算是一个,不过耗时也差不多,iosteam 就是一个失败的组件,不然 WG21 也不会想着搞 std::print 之类的。

以 gcc 为例,请在编译参数加入 -s(或更为激进的-Os -s),然后再试一次。支持 Release 版的,请用 Release 版。您要是禁用了优化或者只开了 -O1、带了符号表和调试信息,我无话可说。

libstdc++.a 库文件已经生成了,不会再进行任何优化,链接器不会对对象文件汇编进行优化。在 libstdc++ 编译的时候会使用 -fdata-sections -ffunctions-sections 尽量减小 C++ 程序的体积,但是这两个参数会导致 libstdc++-6.dll 的膨胀,所以TDM-GCC 选择了两次编译 libstdc++ 来减少 C++ 动态库的大小(我记得有,但是未找到这个补丁)
在编译器层面上没有 Release/Debug 模式,这个只是 IDE(Visual Studio)给你包装好的,只是命令行参数上有所不同。
cl -MD -Ox 同样也可以编译出很小的程序。
-Os 我认为并不算一个很好的编译选项,通常没必要使用,它为了追求可执行文件的体积而降低了速度的优化,-Ofast 也是同理,优化都过于激进
trcrsired 他通常都使用 -Ofast -s -flto -DNDEBUG -fno-ident 一类的来进行测试

未实际测试此库和旧程序(使用流式 I/O 的程序)在复杂使用情况下的互相兼容性。

fast_io 提供了对 stdio iosteam 的标准组件的支持

iostream 包含后暴增 800 K

确实,因为在 libstdc++ 中它有一个全局对象,用来初始化 std::(w)cout std::(w)cin 对象,但是单引入 不会引起二进制的膨胀(编译速度另说)

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

测完了,跑分结果确实有问题。

以下使用默认优化参数/动态链接,测定两次 fast_io 和 std::fstream 完成 1M 数据写入的速度。

后台所有无关进程和网络连接(包括本地)已被挂起,以减小测量误差。

以下是 fast_io 的测试代码:

#include<fast_io.h>                                               #include<fast_io_device.h>
#include<fast_io_legacy.h>                                        #include<fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"fast_io");
  fast_io::filebuf_file fbf(u8"fastio.txt",fast_io::open_mode::out);
  std::ostream fout(fbf.fb);
  for(std::size_t i{};i!=10000000;++i)
    fout<<"Hello World";
}

以下是 std::fstream 的测试代码:

#include <fstream>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"fstream");
  std::ofstream fout("fstream.txt");
  for(std::size_t i{};i!=10000000;++i)
    fout<<"Hello World";
}

Screenshot_1

如图,使用如上参数编译后分别进行测试,fast_io 和 std::fstream 区别不明显(fast_io 比
std::fstream 慢 0.009496769s,可算作误差)。


Screenshot_2

如图,使用 time 工具进行速度对比,此时 fast_io 与 std::fstream 速度差异较为明显(fast_io 比 std::fstream 慢 0.066591615s)。

此外,我们还关注到上下文切换的次数。在此次测试中,fast_io 的上下文切换次数是 std::fstream 的 3 2⁄3 倍,这意味着 fast_io 的成本在 ARM/ARM64 Linux 上更高昂,且吃力不讨好。


我使用了 chroot 容器,以下是它们两个的 uname 数据。

chroot 容器:

Linux kali 4.14.186-perf-gf74b69998c5c #1 SMP PREEMPT Tue Jul 12 20:48:38 CST 2022 aarch64 GNU/Linux

宿主:

Linux kali 4.14.186-perf-gf74b69998c5c #1 SMP PREEMPT Tue Jul 12 20:48:38 CST 2022 aarch64 Android

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

连库都没用正确,扯毛??fast_io支持<<输出???那不是fstream的功能??fast_io是用的print,scan 输出输入的。

#include <fstream>
#include <fast_io.h>
#include <fast_io_device.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"fstream");
  std::ofstream fout("fstream.txt");
  fast_io::filebuf_io_observer fiob{fout.rdbuf()};
  for(std::size_t i{};i!=10000000;++i)
    print(fiob,"Hello World");
}

所谓的兼容性是这么来的.你不信试试这个。这样它就会直接操纵fstream的缓冲区指针,达到与fstream兼容的作用

from fast_io.

FurryR avatar FurryR commented on June 27, 2024
#include<fast_io.h>
#include<fast_io_legacy.h>
int main() {
  fast_io::timer tm(u8"fast_io");
  fast_io::filebuf_file fbf(u8"fastio.txt",fast_io::open_mode::out);
  for(std::size_t i{};i!=10000000;++i)
    print(fbf,"Hello World");
}

这么测的小朋友。你测流的性能搞毛呢???

同时要加-O2 你也可以尝试-flto -march=native -Ofast -s

之后甚至可以-fprofile-generate -fprofile-use

-march=native 在我的架构上无效。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024
#include<fast_io.h>
#include<fast_io_legacy.h>
int main() {
  fast_io::timer tm(u8"fast_io");
  fast_io::filebuf_file fbf(u8"fastio.txt",fast_io::open_mode::out);
  for(std::size_t i{};i!=10000000;++i)
    print(fbf,"Hello World");
}

这么测的小朋友。你测流的性能搞毛呢???
同时要加-O2 你也可以尝试-flto -march=native -Ofast -s
之后甚至可以-fprofile-generate -fprofile-use

-march=native 在我的架构上无效。

无所谓。

还有别忘了每次测试的时候先rm *.txt,不然linux内核删文件要时间

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

两边测试都要删文件,对最终速度无影响。

我会使用 -O3 重测一遍。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

连库都没用正确,扯毛??fast_io支持<<输出???那不是fstream的功能??fast_io是用的print,scan 输出输入的。

#include <fstream>
#include <fast_io.h>
#include <fast_io_device.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"fstream");
  std::ofstream fout("fstream.txt");
  fast_io::filebuf_io_observer fiob{fout.rdbuf()};
  for(std::size_t i{};i!=10000000;++i)
    print(fiob,"Hello World");
}

所谓的兼容性是这么来的.你不信试试这个。这样它就会直接操纵fstream的缓冲区指针,达到与fstream兼容的作用

有没有搞错?纯fstream也要用上fast_io?

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

连库都没用正确,扯毛??fast_io支持<<输出???那不是fstream的功能??fast_io是用的print,scan 输出输入的。

#include <fstream>
#include <fast_io.h>
#include <fast_io_device.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"fstream");
  std::ofstream fout("fstream.txt");
  fast_io::filebuf_io_observer fiob{fout.rdbuf()};
  for(std::size_t i{};i!=10000000;++i)
    print(fiob,"Hello World");
}

所谓的兼容性是这么来的.你不信试试这个。这样它就会直接操纵fstream的缓冲区指针,达到与fstream兼容的作用

有没有搞错?纯fstream也要用上fast_io?

对。这样快的多,不信你测试看看。因为它会直接操作fstream缓冲区指针。同时可以使用fast_io自己的很多功能,例如输出时间,本地化,QString winrt::hstring一类的乱七八糟的。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

同理对于C的FILE*也一样
比如

#include <cstdio>
#include <fast_io.h>
#include <fast_io_device.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"FILE");
  FILE* fp =fopen("cfileptr.txt","wb");
  if(fp==nullptr)
  {
     abort();
  }
  fast_io::c_io_observer_unlocked ciob{fp};
  for(std::size_t i{};i!=10000000;++i)
    print(ciob,"Hello World");
  fclose(fp);//无视异常不析构。只是举例
}

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

fast_io文件实际上是这样用的

#include <fast_io.h>
#include <fast_io_device.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"fast_io::u8obuf_file");
  fast_io::u8obuf_file u8obf(u8"fastioobf.txt");//输出到fast_io自己提供的输出缓冲类型
  for(std::size_t i{};i!=10000000;++i)
    print(u8obf,u8"Hello World");
}

from fast_io.

24bit-xjkp avatar 24bit-xjkp commented on June 27, 2024

再提一点,如果libstdc++、msvc stl和libc++好用的话,为何llvm要自己弄一个libllvm来代替标准库(例如llvm::ofstream)?说到底还是标准库的东西太烂了,还搞本地化之类的。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

把 fstream 换成了另一种奇技淫巧(不碰底层),速度超过了 fast_io。


请欣赏《别样的 FIFO 大战》,作者百度贴吧。

两个程序均采用 -O2 优化,其余编译相关选项默认。

fast_io.cc:

#include<fast_io.h>
#include<fast_io_legacy.h>
#include<fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"fast_io");
  fast_io::filebuf_file fbf(u8"fastio.txt",fast_io::open_mode::out);
  for(std::size_t i{};i!=10000000;++i)
    print(fbf,"Hello World");
}

fd.cpp:

#include <unistd.h>
#include <cstring>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"fd");
  char buf[10240 * 10 + 1];
  const char* w = "Hello World";
  size_t ptr = 0;
  int fd = open("fd.txt", O_CREAT | O_WRONLY | O_NONBLOCK, S_IWUSR);
  for(size_t i = 0;i != 10000000; ++i) {
    if (ptr + 11 >= sizeof(buf) / sizeof(char)) {
      write(fd, buf, ptr);
      ptr = 0;
    }
    memcpy(buf + ptr, w, 11);
    ptr += 11;
  }
  if (ptr) {
    write(fd, buf, ptr);
  }
  close(fd);
}

Screenshot_1

如图,fd 的速度比 fast_io 还要快(约0.07s),并且上下文切换数达到了个位数。

由于 FIFO 特性,非阻塞当同步用也可以保证结果正确,且比 fast_io 还要更快,且成本会更低。

令人疑惑的是,这时候反而 fast_io 的结果好像多了四字节(diff 未检测出异常)。

from fast_io.

24bit-xjkp avatar 24bit-xjkp commented on June 27, 2024

如图,fd 的速度比 fast_io 还要快(约0.07s),并且上下文切换数达到了个位数。

由于 FIFO 特性,非阻塞当同步用也可以保证结果正确,且比 fast_io 还要更快,且成本会更低。

令人疑惑的是,这时候反而 fast_io 的结果好像多了四字节(diff 未检测出异常)。

这样的比较毫无意义,同步与异步没有可比性。这不在一个水平线上。。。

由于 FIFO 特性,非阻塞当同步用也可以保证结果正确

这不跨平台。不是所有平台都能不阻塞而结果正确。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

如图,fd 的速度比 fast_io 还要快(约0.07s),并且上下文切换数达到了个位数。
由于 FIFO 特性,非阻塞当同步用也可以保证结果正确,且比 fast_io 还要更快,且成本会更低。
令人疑惑的是,这时候反而 fast_io 的结果好像多了四字节(diff 未检测出异常)。

这样的比较毫无意义,同步与异步没有可比性。这不在一个水平线上。。。

由于 FIFO 特性,非阻塞当同步用也可以保证结果正确

这不跨平台。不是所有平台都能不阻塞而结果正确。

好好搞懂非阻塞和异步有什么区别再说。

from fast_io.

24bit-xjkp avatar 24bit-xjkp commented on June 27, 2024

如图,fd 的速度比 fast_io 还要快(约0.07s),并且上下文切换数达到了个位数。
由于 FIFO 特性,非阻塞当同步用也可以保证结果正确,且比 fast_io 还要更快,且成本会更低。
令人疑惑的是,这时候反而 fast_io 的结果好像多了四字节(diff 未检测出异常)。

这样的比较毫无意义,同步与异步没有可比性。这不在一个水平线上。。。

由于 FIFO 特性,非阻塞当同步用也可以保证结果正确

这不跨平台。不是所有平台都能不阻塞而结果正确。

好好搞懂非阻塞和异步有什么区别再说。

阻塞和非阻塞就有可比性了?

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

如图,fd 的速度比 fast_io 还要快(约0.07s),并且上下文切换数达到了个位数。
由于 FIFO 特性,非阻塞当同步用也可以保证结果正确,且比 fast_io 还要更快,且成本会更低。
令人疑惑的是,这时候反而 fast_io 的结果好像多了四字节(diff 未检测出异常)。

这样的比较毫无意义,同步与异步没有可比性。这不在一个水平线上。。。

由于 FIFO 特性,非阻塞当同步用也可以保证结果正确

这不跨平台。不是所有平台都能不阻塞而结果正确。

好好搞懂非阻塞和异步有什么区别再说。

阻塞和非阻塞就有可比性了?

未曾看见哪个操作系统用LIFO队列管理文件操作。

至于阻塞和非阻塞有没有可比性,要不要试着在fast_io程序写入后面加一个sync命令呢?

from fast_io.

24bit-xjkp avatar 24bit-xjkp commented on June 27, 2024

如图,fd 的速度比 fast_io 还要快(约0.07s),并且上下文切换数达到了个位数。
由于 FIFO 特性,非阻塞当同步用也可以保证结果正确,且比 fast_io 还要更快,且成本会更低。
令人疑惑的是,这时候反而 fast_io 的结果好像多了四字节(diff 未检测出异常)。

这样的比较毫无意义,同步与异步没有可比性。这不在一个水平线上。。。

由于 FIFO 特性,非阻塞当同步用也可以保证结果正确

这不跨平台。不是所有平台都能不阻塞而结果正确。

好好搞懂非阻塞和异步有什么区别再说。

阻塞和非阻塞就有可比性了?

未曾看见哪个操作系统用LIFO队列管理文件操作。

至于阻塞和非阻塞有没有可比性,要不要试着在fast_io程序写入后面加一个sync命令呢?

那测的时候请加上fast_io::open_mode::no_block,这样才有可比性。。。

未曾看见哪个操作系统用LIFO队列管理文件操作。

不要假定系统会怎么实现。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

不要假定系统会怎么实现。

没有用 LIFO 队列管理文件操作一说。

一旦使用 LIFO 队列管理文件操作,新请求的文件操作不断增多,前面请求的被一而再再而三地延迟,会导致严重的问题。

from fast_io.

24bit-xjkp avatar 24bit-xjkp commented on June 27, 2024

那测的时候请加上fast_io::open_mode::no_block,这样才有可比性。。。

用两个阻塞测更准确,因为fast_io还会检查write返回值之类的,拖慢了。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

那测的时候请加上fast_io::open_mode::no_block,这样才有可比性。。。

用两个阻塞测更准确,因为fast_io还会检查write返回值之类的,拖慢了。

不对,fd 换成阻塞以后会直接用上系统的缓存机制,从而在速度上超越 fast_io。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

那测的时候请加上fast_io::open_mode::no_block,这样才有可比性。。。

用两个阻塞测更准确,因为fast_io还会检查write返回值之类的,拖慢了。

不对,fd 换成阻塞以后会直接用上系统的缓存机制,从而在速度上超越 fast_io。

本来就没加non_block选项,就是默认的O_CREAT | O_WRONLY。
你代码更简单,更有利于编译器优化。就像fast_io比iostream和流的实现简单抽象更少,更有利于优化,很正常。类似的例子也很多。因为没有零开销抽象。当然我可以看看哪里有问题看看能不能进一步改进。
本来就没说过fast_io是fastest_io。fast_io是相比stdio和iostream的快。
你相比流的测试呢?给你吃了??

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

那测的时候请加上fast_io::open_mode::no_block,这样才有可比性。。。

用两个阻塞测更准确,因为fast_io还会检查write返回值之类的,拖慢了。

不对,fd 换成阻塞以后会直接用上系统的缓存机制,从而在速度上超越 fast_io。

我觉得你这个例子和上次coalpha的那个

#424

问题估计是一样的。调用write就是浪费时间。只不过那个是针对的是整数,这个是字符串。我看看有没有办法改一下看看吧。主要是你这里字符串是定长的,fast_io并不能知道你这个是定长串,如果多种长度,它就没办法处理了。

毕竟C++目前没有constexpr参数,无法在编译时得到。不过或许用gcc扩展可以搞看看

from fast_io.

AbrasiveBoar902 avatar AbrasiveBoar902 commented on June 27, 2024

没什么意义的比较,这种小聪明实际上没什么用
原来用封装都没有的基础功能和完整库相比,用针对数据特化的方法和通用方法相比,就是所谓完整和公正

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

好好好,下面上你要的 stdio 测试结果。事情越来越迷惑了。


以下是使用 stdio 进行写文件的情况。为了防止长度优化,我执行了一次 strlen。

编译参数和之前的差不多。

stdio.cpp:

#include <cstring>
#include <cstdio>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"stdio");
  char buf[10240 * 10 + 1];
  const char* w = "Hello World";
  size_t ptr = 0;
  FILE* fout = fopen("stdio.txt", "w");
  for(size_t i = 0;i != 10000000; ++i) {
    size_t len = strlen(w);
    if (ptr + len >= sizeof(buf) / sizeof(char)) {
      fwrite(buf, sizeof(char), ptr, fout);
      ptr = 0;
    }
    memcpy(buf + ptr, w, len);
    ptr += len;
  }
  if (ptr) {
    fwrite(buf, sizeof(char), ptr, fout);
  }
  fclose(fout);
}

编译参数:

clang++ -std=c++2b -I../include -O2 fast_io.cc -o fast_io --save-temps && clang++ -std=c++2b -I../include -O2 stdio.cpp -o stdio --save-temps

测试结果(为方便计算我就不上图片了):

# rm -rf *.txt && ./fast_io && ./stdio && du fastio.txt stdio.txt && diff fastio.txt stdio.txt -s
fast_io:0.200083769s
stdio (mixed):0.19944s
107424  fastio.txt
107424  stdio.txt
文件 fastio.txt 和 stdio.txt 相同
# rm -rf *.txt && \time -v ./fast_io && \time -v ./stdio && du fastio.txt stdio.txt && diff fastio.txt stdio.txt -s
fast_io:0.248277461s
        Command being timed: "./fast_io"
        User time (seconds): 0.08
        System time (seconds): 0.16
        Percent of CPU this job got: 97%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.25
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 2772
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 153
        Voluntary context switches: 21
        Involuntary context switches: 25
        Swaps: 0
        File system inputs: 0
        File system outputs: 214848
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
stdio (mixed):0.188824692s
        Command being timed: "./stdio"
        User time (seconds): 0.02
        System time (seconds): 0.12
        Percent of CPU this job got: 76%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.19
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 2528
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 138
        Voluntary context switches: 12
        Involuntary context switches: 10
        Swaps: 0
        File system inputs: 0
        File system outputs: 214848
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
107424  fastio.txt
107424  stdio.txt
文件 fastio.txt 和 stdio.txt 相同

至于为什么 fast_io 的优化突然不翼而飞了,我百思不得其解。

追记:stdio 变为 stdio (mixed) 的原因是我在源文件上还测试了动态 std::string 初始化(性能拉跨),更正代码为最新源文件时忘记把名字改回来了。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

好好好,下面上你要的 stdio 测试结果。事情越来越迷惑了。

以下是使用 stdio 进行写文件的情况。为了防止长度优化,我执行了一次 strlen。

编译参数和之前的差不多。

stdio.cpp:

#include <cstring>
#include <cstdio>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"stdio");
  char buf[10240 * 10 + 1];
  const char* w = "Hello World";
  size_t ptr = 0;
  FILE* fout = fopen("stdio.txt", "w");
  for(size_t i = 0;i != 10000000; ++i) {
    size_t len = strlen(w);
    if (ptr + len >= sizeof(buf) / sizeof(char)) {
      fwrite(buf, sizeof(char), ptr, fout);
      ptr = 0;
    }
    memcpy(buf + ptr, w, len);
    ptr += len;
  }
  if (ptr) {
    fwrite(buf, sizeof(char), ptr, fout);
  }
  fclose(fout);
}

编译参数:

clang++ -std=c++2b -I../include -O2 fast_io.cc -o fast_io --save-temps && clang++ -std=c++2b -I../include -O2 stdio.cpp -o stdio --save-temps

测试结果(为方便计算我就不上图片了):

# rm -rf *.txt && ./fast_io && ./stdio && du fastio.txt stdio.txt && diff fastio.txt stdio.txt -s
fast_io:0.200083769s
stdio (mixed):0.19944s
107424  fastio.txt
107424  stdio.txt
文件 fastio.txt 和 stdio.txt 相同
# rm -rf *.txt && \time -v ./fast_io && \time -v ./stdio && du fastio.txt stdio.txt && diff fastio.txt stdio.txt -s
fast_io:0.248277461s
        Command being timed: "./fast_io"
        User time (seconds): 0.08
        System time (seconds): 0.16
        Percent of CPU this job got: 97%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.25
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 2772
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 153
        Voluntary context switches: 21
        Involuntary context switches: 25
        Swaps: 0
        File system inputs: 0
        File system outputs: 214848
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
stdio (mixed):0.188824692s
        Command being timed: "./stdio"
        User time (seconds): 0.02
        System time (seconds): 0.12
        Percent of CPU this job got: 76%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.19
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 2528
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 138
        Voluntary context switches: 12
        Involuntary context switches: 10
        Swaps: 0
        File system inputs: 0
        File system outputs: 214848
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
107424  fastio.txt
107424  stdio.txt
文件 fastio.txt 和 stdio.txt 相同

至于为什么 fast_io 的优化突然不翼而飞了,我百思不得其解。

追记:stdio 变为 stdio (mixed) 的原因是我在源文件上还测试了动态 std::string 初始化(性能拉跨),更正代码为最新源文件时忘记把名字改回来了。

你这个strlen早就被编译器优化成常数了。fwrite这么写与write就没区别。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

没什么意义的比较,这种小聪明实际上没什么用 原来用封装都没有的基础功能和完整库相比,用针对数据特化的方法和通用方法相比,就是所谓完整和公正

对。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

好好好,下面上你要的 stdio 测试结果。事情越来越迷惑了。
以下是使用 stdio 进行写文件的情况。为了防止长度优化,我执行了一次 strlen。
编译参数和之前的差不多。
stdio.cpp:

#include <cstring>
#include <cstdio>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"stdio");
  char buf[10240 * 10 + 1];
  const char* w = "Hello World";
  size_t ptr = 0;
  FILE* fout = fopen("stdio.txt", "w");
  for(size_t i = 0;i != 10000000; ++i) {
    size_t len = strlen(w);
    if (ptr + len >= sizeof(buf) / sizeof(char)) {
      fwrite(buf, sizeof(char), ptr, fout);
      ptr = 0;
    }
    memcpy(buf + ptr, w, len);
    ptr += len;
  }
  if (ptr) {
    fwrite(buf, sizeof(char), ptr, fout);
  }
  fclose(fout);
}

编译参数:

clang++ -std=c++2b -I../include -O2 fast_io.cc -o fast_io --save-temps && clang++ -std=c++2b -I../include -O2 stdio.cpp -o stdio --save-temps

测试结果(为方便计算我就不上图片了):

# rm -rf *.txt && ./fast_io && ./stdio && du fastio.txt stdio.txt && diff fastio.txt stdio.txt -s
fast_io:0.200083769s
stdio (mixed):0.19944s
107424  fastio.txt
107424  stdio.txt
文件 fastio.txt 和 stdio.txt 相同
# rm -rf *.txt && \time -v ./fast_io && \time -v ./stdio && du fastio.txt stdio.txt && diff fastio.txt stdio.txt -s
fast_io:0.248277461s
        Command being timed: "./fast_io"
        User time (seconds): 0.08
        System time (seconds): 0.16
        Percent of CPU this job got: 97%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.25
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 2772
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 153
        Voluntary context switches: 21
        Involuntary context switches: 25
        Swaps: 0
        File system inputs: 0
        File system outputs: 214848
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
stdio (mixed):0.188824692s
        Command being timed: "./stdio"
        User time (seconds): 0.02
        System time (seconds): 0.12
        Percent of CPU this job got: 76%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.19
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 2528
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 138
        Voluntary context switches: 12
        Involuntary context switches: 10
        Swaps: 0
        File system inputs: 0
        File system outputs: 214848
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0
107424  fastio.txt
107424  stdio.txt
文件 fastio.txt 和 stdio.txt 相同

至于为什么 fast_io 的优化突然不翼而飞了,我百思不得其解。
追记:stdio 变为 stdio (mixed) 的原因是我在源文件上还测试了动态 std::string 初始化(性能拉跨),更正代码为最新源文件时忘记把名字改回来了。

你这个strlen早就被编译器优化成常数了。fwrite这么写与write就没区别。

strlen 不是 constexpr,std::size 是,而 std::size 不适用于此情况。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

https://godbolt.org/z/nYnnMc95M

#include<cstring>
#include<cstddef>
std::size_t text() noexcept
{
    char const* str = "Hello World";
    return std::strlen(str);
}

编译器生成的汇编

text():
        mov     eax, 11
        ret

直接就是11了

from fast_io.

24bit-xjkp avatar 24bit-xjkp commented on June 27, 2024

fwrite(buf, sizeof(char), ptr, fout);有谁会用stdio了还自己开缓冲区?

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

fwrite(buf, sizeof(char), ptr, fout);有谁会用stdio了还自己开缓冲区?

有谁会用了垂直同步还开三重缓冲?

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

fwrite(buf, sizeof(char), ptr, fout);有谁会用stdio了还自己开缓冲区?

有谁会用了垂直同步还开三重缓冲?

图形学和这个这是一回事???

还有你以为你这个真的有缓冲?stdio的缓冲区要不然4096要不然8192。你fwrite写的长度远远大于8192了。fwrite它有病给你缓冲

from fast_io.

AbrasiveBoar902 avatar AbrasiveBoar902 commented on June 27, 2024

到这就没什么可说的了,小孩子死缠烂打即视感
你要自己搓就把example里那些基本的先实现了封装一下再调用测性能,不然就正常去测stdio和iostream,搞的这些小聪明对实际开发半点用都没有。另外你以为只输出字符串,数字/字符串互转什么都完全不耗时吗?测一下1-1000万整数和字符串交替的混合输出试试?脱离实际的测试不能说明任何问题。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

fwrite(buf, sizeof(char), ptr, fout);有谁会用stdio了还自己开缓冲区?

有谁会用了垂直同步还开三重缓冲?

图形学和这个这是一回事???

还有你以为你这个真的有缓冲?

别急,在测和 std::string 搭配使用的效率。

如果你要说 std::to_string 跟着运行时变量都是编译时计算的,那我无话可说。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

fwrite(buf, sizeof(char), ptr, fout);有谁会用stdio了还自己开缓冲区?

有谁会用了垂直同步还开三重缓冲?

图形学和这个这是一回事???
还有你以为你这个真的有缓冲?

别急,在测和 std::string 搭配使用的效率。

如果你要说 std::to_string 跟着运行时变量都是编译时计算的,那我无话可说。

std::to_string 歇歇吧你。换fast_io::concat

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

到这就没什么可说的了,小孩子死缠烂打即视感 你要自己搓就把example里那些基本的先实现了封装一下再调用测性能,不然就正常去测stdio和iostream,搞的这些小聪明对实际开发半点用都没有。另外你以为只输出字符串,数字/字符串互转什么都完全不耗时吗?测一下1-1000万整数和字符串交替的混合输出试试?脱离实际的测试不能说明任何问题。

正在在这个上面进行测试。目前的初步结果是 stdio 还是比 fast_io 快。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

到这就没什么可说的了,小孩子死缠烂打即视感 你要自己搓就把example里那些基本的先实现了封装一下再调用测性能,不然就正常去测stdio和iostream,搞的这些小聪明对实际开发半点用都没有。另外你以为只输出字符串,数字/字符串互转什么都完全不耗时吗?测一下1-1000万整数和字符串交替的混合输出试试?脱离实际的测试不能说明任何问题。

正在在这个上面进行测试。目前的初步结果是 stdio 还是比 fast_io 快。

笑死了,拿一群乱搞的测试,说stdio比fast_io快。一边去吧你。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

fwrite(buf, sizeof(char), ptr, fout);有谁会用stdio了还自己开缓冲区?

有谁会用了垂直同步还开三重缓冲?

图形学和这个这是一回事???
还有你以为你这个真的有缓冲?

别急,在测和 std::string 搭配使用的效率。
如果你要说 std::to_string 跟着运行时变量都是编译时计算的,那我无话可说。

std::to_string 歇歇吧你。换fast_io::concat

控制变量法就是你说的一下引入多个因素?

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

你重新实现io缓冲不叫“引入多个因素”了?你测试不应该直接测试fprintf对比print的性能??

还有用filebuf_file不叫”引入多个因素“了??filebuf_file是std::filebuf的兼容层,不使用obuf_file扯毛蛋呢

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

你重新实现io缓冲不叫“引入多个因素”了?你测试不应该直接测试fprintf对比print的性能??

我通过 strace 就看到 fast_io 和 stdio 的缓冲大小不同。

按你所说,把 fast_io 的缓冲拉回正常的才叫统一。甚至我这个缓冲还是比你那个小,这就急了。

filebuf_file 是你自己举出来的例子,我是原样复制的。你可以再举一个 obuf_file。这下自己打自己脸了。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024
#include<fast_io.h>
#include<fast_io_legacy.h>
int main() {
  fast_io::timer tm(u8"fast_io");
  fast_io::filebuf_file fbf(u8"fastio.txt",fast_io::open_mode::out);
  for(std::size_t i{};i!=10000000;++i)
    print(fbf,"Hello World");
}

这么测的小朋友。你测流的性能搞毛呢???

同时要加-O2 你也可以尝试-flto -march=native -Ofast -s

之后甚至可以-fprofile-generate -fprofile-use

引用。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

你重新实现io缓冲不叫“引入多个因素”了?你测试不应该直接测试fprintf对比print的性能??

我通过 strace 就看到 fast_io 和 stdio 的缓冲大小不同。

按你所说,把 fast_io 的缓冲拉回正常的才叫统一。甚至我这个缓冲还是比你那个小,这就急了。

filebuf_file 是你自己举出来的例子,我是原样复制的。你可以再举一个 obuf_file。这下自己打自己脸了。

搞笑了。filebuf_file是你的例子里用的,又不是我用的。都说了filebuf_file是C++文件流的兼容层。你扯毛呢?

我都说了你这里是因为你字符串长度比缓冲区小,你自己砍掉了关键路径。如果字符串长度比io缓冲区大怎么办?一会大一会小怎么办??而你的代码逻辑中相当于全砍掉了,还是一堆常量。作为一个通用api怎么可能像你一样知道大小长度?
你是想说根据字符串长度一个长度一个模板?那二进制体积不是炸妈了??

from fast_io.

24bit-xjkp avatar 24bit-xjkp commented on June 27, 2024

输出"hello wrold"有意思么?和事务强耦合的写法当然有优势。要不你测测输出百万整数再重新读出来?

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

输出"hello wrold"有意思么?和事务强耦合的写法当然有优势。要不你测测输出百万整数再重新读出来?

刚刚测完 1-1M 整数的数据,读出暂时没整,stdio 是比 fast_io 快的。

怀疑是我数据太少了,上调到 1-10M 试试。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

输出"hello wrold"有意思么?和事务强耦合的写法当然有优势。要不你测测输出百万整数再重新读出来?

刚刚测完 1-1M 整数的数据,读出暂时没整,stdio 是比 fast_io 快的。

怀疑是我数据太少了,上调到 1-10M 试试。

我就不信你测个输出整数有这么复杂。你肯定是重新胡乱实现了代码。

from fast_io.

24bit-xjkp avatar 24bit-xjkp commented on June 27, 2024

输出"hello wrold"有意思么?和事务强耦合的写法当然有优势。要不你测测输出百万整数再重新读出来?

刚刚测完 1-1M 整数的数据,读出暂时没整,stdio 是比 fast_io 快的。

你指的是标准库的那坨东西比jeaiii/itoa快?要不你去和jeaiii/itoa的作者打一架?

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

输出"hello wrold"有意思么?和事务强耦合的写法当然有优势。要不你测测输出百万整数再重新读出来?

刚刚测完 1-1M 整数的数据,读出暂时没整,stdio 是比 fast_io 快的。

你指的是标准库的那坨东西比jeaiii/itoa快?要不你去和jeaiii/itoa的作者打一架?

我没有测试 format 的必要性,如果需要使用 fast_io 的 format,我会将两个都换成 fast_io 提供的。

当两个都用的烂实现时,不会因为这个而影响实际速度比较。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

输出"hello wrold"有意思么?和事务强耦合的写法当然有优势。要不你测测输出百万整数再重新读出来?

刚刚测完 1-1M 整数的数据,读出暂时没整,stdio 是比 fast_io 快的。

你指的是标准库的那坨东西比jeaiii/itoa快?要不你去和jeaiii/itoa的作者打一架?

它要是就这种手工循环乱搞这种做法,是能比这个快。我2年前就知道了。问题是你api能设计出来??这叫什么公平对比?

合着在他眼中又是除了write以外就不是io函数了。测试的时候拿手工展开所有的信息都已知去和fast_io的print对比,意义在什么地方。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

输出"hello wrold"有意思么?和事务强耦合的写法当然有优势。要不你测测输出百万整数再重新读出来?

刚刚测完 1-1M 整数的数据,读出暂时没整,stdio 是比 fast_io 快的。

你指的是标准库的那坨东西比jeaiii/itoa快?要不你去和jeaiii/itoa的作者打一架?

我没有测试 format 的必要性,如果需要使用 fast_io 的 format,我会将两个都换成 fast_io 提供的。

当两个都用的烂实现时,不会因为这个而影响实际速度比较。

然而fast_io的作用就是将原本都是一堆的烂实现的东西整合在一起,达到整体最优。你用print(fbf,to_string(3));就不如直接print(fbf,3)快

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

输出"hello wrold"有意思么?和事务强耦合的写法当然有优势。要不你测测输出百万整数再重新读出来?

刚刚测完 1-1M 整数的数据,读出暂时没整,stdio 是比 fast_io 快的。

你指的是标准库的那坨东西比jeaiii/itoa快?要不你去和jeaiii/itoa的作者打一架?

它要是就这种手工循环乱搞这种做法,是能比这个快。我2年前就知道了。问题是你api能设计出来??这叫什么公平对比?

合着在他眼中又是除了write以外就不是io函数了。测试的时候拿手工展开所有的信息都已知去和fast_io的print对比,意义在什么地方。

#include <cstring>
#include <cstdio>
#include <string>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"stdio");
  char buf[10240 * 10 + 1];
  size_t ptr = 0;
  FILE* fout = fopen("stdio.txt", "w");
  for(size_t i = 0;i != 10000000; ++i) {
    std::string w = std::to_string(i);
    size_t len = w.size();
    if (ptr + len >= sizeof(buf) / sizeof(char)) {
      fwrite(buf, sizeof(char), ptr, fout);
      ptr = 0;
    }
    memcpy(buf + ptr, w.c_str(), len);
    ptr += len;
  }
  if (ptr) {
    fwrite(buf, sizeof(char), ptr, fout);
  }
  fclose(fout);
}

您可以试试在编译时保存一下 1-1M(0-999999)的长度数据。比如用 log10 计算。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

搞笑了,看来noi考试考输出100万hw这种不切实际的东西,开发一行print之类调用要超级加倍成几十行,输出只有常量字符串打几个info,写文件不需要管正确与否甚至写进去没有,一切程序都可以编译时算出结果然后面向答案编程,标准都是我自己定的也不需要查资料不需要实际测试,使用库也不需要看文档全凭我自己感觉,benchmark应该搞特化编写时计算和别人运行时比得出py比cpp快一万倍,这真是太酷了,完美符合我对新时代信竞生的想象 差不多得了

实际上他这坨能不能性能高都未必。二进制体积就炸妈。代码重复n遍。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

你封装了你这一堆再测,我只希望看到一行print之类的调用

它这个一份代码就重新写一遍,运行时性能都很难保证会高效,原因是二进制大量无意义重复,指令缓存炸妈

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

封装不了还有什么可比的

好的,我会尝试运用一些面向对象编程。

另外,您说的炸妈体积在未进行静态链接的情况下是20K。不知道包含 libc6 以后有多大(std::string 的依赖可以被删除)。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

封装不了还有什么可比的

好的,我会尝试运用一些面向对象编程。

另外,您说的炸妈体积在未进行静态链接的情况下是20K。不知道包含 libc6 以后有多大(std::string 的依赖可以被删除)。

glibc不能静态编译。你就-static-libstdc++就行了

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

封装不了还有什么可比的

好的,我会尝试运用一些面向对象编程。
另外,您说的炸妈体积在未进行静态链接的情况下是20K。不知道包含 libc6 以后有多大(std::string 的依赖可以被删除)。

glibc不能静态编译。你就-static-libstdc++就行了

现在我正在进行对源代码的封装。

考虑到正在使用 Android,这会慢一点儿。

您说的 -static-libstdcxx 我会测试的。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024
#include <cstring>
#include <cstdio>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
int main() {
  fast_io::timer tm(u8"yourmethod");
  char buf[10240 * 10 + 1];
  const char* w = "Hello World";
  size_t ptr = 0;
  fast_io::native_file obf("yourmethod.txt",fast_io::open_mode::out);
  for(size_t i = 0;i != 10000000; ++i) {
    size_t len = strlen(w);
    if (ptr + len >= sizeof(buf) / sizeof(char)) {
      write(obf,buf,buf+ptr);
      ptr = 0;
    }
    memcpy(buf + ptr, w, len);
    ptr += len;
  }
  if (ptr) {
	  write(obf,buf,buf+ptr);
  }
}

我就用你这种愚蠢的办法“控制变量”呢

cqwrteur@HOME-SERVER:~/Libraries/fast_io/.tmp$ ./oh
fd:0.043677213s
cqwrteur@HOME-SERVER:~/Libraries/fast_io/.tmp$ ./testest
yourmethod:0.042583351s

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

https://github.com/cppfastio/fast_io/blob/master/benchmark/0002.file_io_tsc/time/fstream.cc
https://github.com/cppfastio/fast_io/blob/master/benchmark/0002.file_io_tsc/time/stdio.cc
https://github.com/cppfastio/fast_io/blob/master/benchmark/0002.file_io_tsc/time/iobuf_file.cc

cqwrteur@HOME-SERVER:~/Libraries/fast_io/benchmark/0002.file_io_tsc/time$ g++ -o iobuf_file iobuf_file.cc -Ofast -std=c++23 -s -flto -march=native -I../../../include -fuse-ld=gold
cqwrteur@HOME-SERVER:~/Libraries/fast_io/benchmark/0002.file_io_tsc/time$ g++ -o fstream fstream.cc -Ofast -std=c++23 -s -flto -march=native -I../../../include -fuse-ld=gold
cqwrteur@HOME-SERVER:~/Libraries/fast_io/benchmark/0002.file_io_tsc/time$ g++ -o stdio stdio.cc -Ofast -std=c++23 -s -flto -march=native -I../../../include -fuse-ld=gold
cqwrteur@HOME-SERVER:~/Libraries/fast_io/benchmark/0002.file_io_tsc/time$ ./iobuf_file
output:0.046114264s
input:0.049575045s
cqwrteur@HOME-SERVER:~/Libraries/fast_io/benchmark/0002.file_io_tsc/time$ ./stdio
output:0.362640654s
input:0.430437808s
cqwrteur@HOME-SERVER:~/Libraries/fast_io/benchmark/0002.file_io_tsc/time$ ./fstream
output:0.21635805s
input:0.32118017s

你给我解释一下stdio是怎么比fast_io快的?安卓是吧,看样是libc++,之后用的filebuf_file??搞笑呢。libc++ std::filebuf不慢就出鬼了。 LLVM libc++流实现一直都是次品,慢炸。没事干不要用filebuf_file

把我这几个测试数据运行一样,再来扯吧。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

遗憾地,我因为不了解 fmt 的原理,只写出来一个速度极慢的版本。

无论是 sprintf、std::to_chars、std::to_string 还是 fast_io::concat,均不能取得好的速度,于是我选择了 fast_io::concat,它得到了快于 std::to_chars 和 sprintf 而约等于 std::to_string 的性能。

stdio.cpp:

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
namespace test {
  // 不依赖 STL。
  // 没有使用 if 语句。
  inline constexpr size_t BUFSIZE = 10240 * 10 + 1;
  template <typename T>
  inline constexpr void _safe_drop(T&&) noexcept {}
  class rtti_file {
    FILE* _ptr = nullptr;
    bool initalized = false;
   public:
    void close() noexcept {
      // 不抛出异常,暂时省点事。
      _safe_drop(initalized && (
        fclose(_ptr),
        initalized = false,
        _ptr = nullptr
      ));
    }
    void open(FILE* file) noexcept {
      _safe_drop(initalized && (close(), true));
      _ptr = file, setbuf(_ptr, nullptr), initalized = true;
    }
    inline int fwrite(const void* __restrict data, size_t size, size_t count) const noexcept {
      return ::fwrite(data, size, count, _ptr);
    }
    constexpr FILE* ptr() const noexcept {
      return _ptr; // 本来应该进行对 initalized 的检查并抛出错误的,但我们不依赖 STL 标准错误。
    }
    constexpr bool check_if_initalized() const noexcept {
      return initalized;
    }
    ~rtti_file() {
      close();
    }
    rtti_file(const rtti_file&) = delete;
    rtti_file() = default;
  };
  class write_stream {
    rtti_file ptr{};
    char buf[BUFSIZE];
    size_t pos = 0;
    constexpr bool check_if_available(size_t size) const noexcept {
      return size < buf_avail();
    }
   public:
    void flush() noexcept {
      ptr.fwrite(buf, sizeof(char), pos);
      pos = 0;
    }
    constexpr const rtti_file* data() const noexcept {
      return &ptr;
    }
    void open(const char* path) noexcept {
      ptr.open(fopen(path, "w"));
      pos = 0;
    }
    inline void close() noexcept {
      ptr.close();
    }
    constexpr size_t buf_avail() const noexcept {
      return BUFSIZE - pos;
    }
    // 定长版
    template <size_t N>
    const write_stream& operator<<(const char (&str)[N]) noexcept {
      return N < BUFSIZE ? (
        _safe_drop(check_if_available(N) || (flush(), true)),
        memcpy(buf + pos, str, N),
        pos += N
      ) : (
        flush(),
        ptr.fwrite(buf, sizeof(char), pos)
      ), *this;
    }
    // 不推荐使用:会触发很多次检查。
    const write_stream& operator<<(char i) {
      return (
        _safe_drop(check_if_available(1) || (flush(), true)),
        buf[pos++] = i
      ), *this;
    }
    void write_sized(const char* str, size_t size) noexcept {
      size < BUFSIZE ? (
        _safe_drop(check_if_available(size) || (flush(), true)),
        memcpy(buf + pos, str, size),
        pos += size
      ) : (
        flush(),
        ptr.fwrite(buf, sizeof(char), pos)
      );
    }
    // 不定长版
    const write_stream& operator<<(const char* str) noexcept {
      size_t len = strlen(str);
      return len < BUFSIZE ? (
        _safe_drop(check_if_available(len) || (flush(), true)),
        memcpy(buf + pos, str, len),
        pos += len
      ) : (
        flush(),
        ptr.fwrite(buf, sizeof(char), pos)
      ), *this;
    }
    // 摆烂了。
    const write_stream& operator<<(size_t n) noexcept {
      std::string q = fast_io::concat(n);
      return write_sized(q.c_str(), q.size()), *this;
    }
    ~write_stream() {
      _safe_drop(pos && (flush(), true));
    }
    write_stream() = default;
    write_stream(const write_stream&) = delete;
    explicit write_stream(const char* path) {
      open(path);
    }
  };
};
int main() {
  fast_io::timer tm(u8"stdio");
  test::write_stream stream("stdio.txt");
  for (size_t i = 0; i != 10000000; ++i) {
    stream << i;
  }
}

此代码在输出字符串时仍然比 fast_io 快速(我不知道为什么),在数字输出上略快于 fstream 而明显慢于 fast_io。如果有人知道如何改良(不使用 fast_io),请告诉我。

同样的,我努力对这段代码进行了 OOP 抽象,虽然这可能不是正确的抽象方式,但是至少我享受到了 RAII(而不是 RTTI,所以你可以加上 -fno-rtti 编译参数)。

我听从了 @trcrsired 的建议,将 filebuf 换为了 obuf,性能没有任何提升。

为什么认为安卓就是 libc++?我通过 ldd 得知这两个应用程序依赖的是 libstdc++ 而非 libc++。

为回应原作者对旧式编程方法的偏执,此实现也做了一些改变——不含if语句。

if 语句过时了(冗余+意大利面),建议使用优雅的三元表达式和逻辑运算符(不含不格式化的情况),并更多地抽出一些复杂的方法。

(看起来很不错但实际上有点麻烦。你可以看到我在一些地方使用逗号运算符来统一类型,并在一些地方使用 _safe_drop 来回避 unused expression value 警告。)

我尚未测试 benchmark 里面的示例,会在等一下完成。


这个实现可能有一些可供参考的地方,比如 write_sized 适用于可以人工确定大小的位置,而定长 operator<< 则适用于字面量(或许)。

如果说这样做会导致二进制体积膨胀,那么实际上担心错了,因为编译器可以将模板函数内部的内容直接内联(前提是实现够简单)。

from fast_io.

havedifficultyinfindingnames avatar havedifficultyinfindingnames commented on June 27, 2024

遗憾地,我因为不了解 fmt 的原理,只写出来一个速度极慢的版本。

无论是 sprintf、std::to_chars、std::to_string 还是 fast_io::concat,均不能取得好的速度,于是我选择了 fast_io::concat,它得到了快于 std::to_chars 和 sprintf 而约等于 std::to_string 的性能。

stdio.cpp:

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
namespace test {
  // 不依赖 STL。
  // 没有使用 if 语句。
  inline constexpr size_t BUFSIZE = 10240 * 10 + 1;
  template <typename T>
  inline constexpr void _safe_drop(T&&) noexcept {}
  class rtti_file {
    FILE* _ptr = nullptr;
    bool initalized = false;
   public:
    void close() noexcept {
      // 不抛出异常,暂时省点事。
      _safe_drop(initalized && (
        fclose(_ptr),
        initalized = false,
        _ptr = nullptr
      ));
    }
    void open(FILE* file) noexcept {
      _safe_drop(initalized && (close(), true));
      _ptr = file, setbuf(_ptr, nullptr), initalized = true;
    }
    inline int fwrite(const void* __restrict data, size_t size, size_t count) const noexcept {
      return ::fwrite(data, size, count, _ptr);
    }
    constexpr FILE* ptr() const noexcept {
      return _ptr; // 本来应该进行对 initalized 的检查并抛出错误的,但我们不依赖 STL 标准错误。
    }
    constexpr bool check_if_initalized() const noexcept {
      return initalized;
    }
    ~rtti_file() {
      close();
    }
    rtti_file(const rtti_file&) = delete;
    rtti_file() = default;
  };
  class write_stream {
    rtti_file ptr{};
    char buf[BUFSIZE];
    size_t pos = 0;
    constexpr bool check_if_available(size_t size) const noexcept {
      return size < buf_avail();
    }
   public:
    void flush() noexcept {
      ptr.fwrite(buf, sizeof(char), pos);
      pos = 0;
    }
    constexpr const rtti_file* data() const noexcept {
      return &ptr;
    }
    void open(const char* path) noexcept {
      ptr.open(fopen(path, "w"));
      pos = 0;
    }
    inline void close() noexcept {
      ptr.close();
    }
    constexpr size_t buf_avail() const noexcept {
      return BUFSIZE - pos;
    }
    // 定长版
    template <size_t N>
    const write_stream& operator<<(const char (&str)[N]) noexcept {
      return N < BUFSIZE ? (
        _safe_drop(check_if_available(N) || (flush(), true)),
        memcpy(buf + pos, str, N),
        pos += N
      ) : (
        flush(),
        ptr.fwrite(buf, sizeof(char), pos)
      ), *this;
    }
    // 不推荐使用:会触发很多次检查。
    const write_stream& operator<<(char i) {
      return (
        _safe_drop(check_if_available(1) || (flush(), true)),
        buf[pos++] = i
      ), *this;
    }
    void write_sized(const char* str, size_t size) noexcept {
      size < BUFSIZE ? (
        _safe_drop(check_if_available(size) || (flush(), true)),
        memcpy(buf + pos, str, size),
        pos += size
      ) : (
        flush(),
        ptr.fwrite(buf, sizeof(char), pos)
      );
    }
    // 不定长版
    const write_stream& operator<<(const char* str) noexcept {
      size_t len = strlen(str);
      return len < BUFSIZE ? (
        _safe_drop(check_if_available(len) || (flush(), true)),
        memcpy(buf + pos, str, len),
        pos += len
      ) : (
        flush(),
        ptr.fwrite(buf, sizeof(char), pos)
      ), *this;
    }
    // 摆烂了。
    const write_stream& operator<<(size_t n) noexcept {
      std::string q = fast_io::concat(n);
      return write_sized(q.c_str(), q.size()), *this;
    }
    ~write_stream() {
      _safe_drop(pos && (flush(), true));
    }
    write_stream() = default;
    write_stream(const write_stream&) = delete;
    explicit write_stream(const char* path) {
      open(path);
    }
  };
};
int main() {
  fast_io::timer tm(u8"stdio");
  test::write_stream stream("stdio.txt");
  for (size_t i = 0; i != 10000000; ++i) {
    stream << i;
  }
}

此代码在输出字符串时仍然比 fast_io 快速(我不知道为什么),在数字输出上略快于 fstream 而明显慢于 fast_io。如果有人知道如何改良(不使用 fast_io),请告诉我。

同样的,我努力对这段代码进行了 OOP 抽象,虽然这可能不是正确的抽象方式,但是至少我享受到了 RAII(而不是 RTTI,所以你可以加上 -fno-rtti 编译参数)。

我听从了 @trcrsired 的建议,将 filebuf 换为了 obuf,性能没有任何提升。

为什么认为安卓就是 libc++?我通过 ldd 得知这两个应用程序依赖的是 libstdc++ 而非 libc++。

为回应原作者对旧式编程方法的偏执,此实现也做了一些改变——不含if语句。

if 语句过时了(冗余+意大利面),建议使用优雅的三元表达式和逻辑运算符(不含不格式化的情况),并更多地抽出一些复杂的方法。

(看起来很不错但实际上有点麻烦。你可以看到我在一些地方使用逗号运算符来统一类型,并在一些地方使用 _safe_drop 来回避 unused expression value 警告。)

我尚未测试 benchmark 里面的示例,会在等一下完成。

这个实现可能有一些可供参考的地方,比如 write_sized 适用于可以人工确定大小的位置,而定长 operator<< 则适用于字面量(或许)。

如果说这样做会导致二进制体积膨胀,那么实际上担心错了,因为编译器可以将模板函数内部的内容直接内联(前提是实现够简单)。

非常抱歉我完全不能理解你这么多的代码是在胡闹什么。我不能理解你在使用fast_io::concat的情况下是怎么得出比fast_io快的结论的。但凡你稍微看过一点点代码,就知道fast_io库中所有输出函数共享相同的底层代码。也就是说,你这段代码的主要耗时也是由这个库实现的。同时,你提到了使用oop封装,但是在你上面的代码中我没有看到任何oop的**,相反fast_io的六层文件抽象才是李氏替代原则的应用的代表。此外,write_sized函数所对应的逻辑正是fast_io库所使用的,而你比库快是建立在抽象层次低,牺牲通用性得来的,并没有更多可取的点。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

不如换一下

遗憾地,我因为不了解 fmt 的原理,只写出来一个速度极慢的版本。
无论是 sprintf、std::to_chars、std::to_string 还是 fast_io::concat,均不能取得好的速度,于是我选择了 fast_io::concat,它得到了快于 std::to_chars 和 sprintf 而约等于 std::to_string 的性能。
stdio.cpp:

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <fast_io.h>
#include <fast_io_driver/timer.h>
namespace test {
  // 不依赖 STL。
  // 没有使用 if 语句。
  inline constexpr size_t BUFSIZE = 10240 * 10 + 1;
  template <typename T>
  inline constexpr void _safe_drop(T&&) noexcept {}
  class rtti_file {
    FILE* _ptr = nullptr;
    bool initalized = false;
   public:
    void close() noexcept {
      // 不抛出异常,暂时省点事。
      _safe_drop(initalized && (
        fclose(_ptr),
        initalized = false,
        _ptr = nullptr
      ));
    }
    void open(FILE* file) noexcept {
      _safe_drop(initalized && (close(), true));
      _ptr = file, setbuf(_ptr, nullptr), initalized = true;
    }
    inline int fwrite(const void* __restrict data, size_t size, size_t count) const noexcept {
      return ::fwrite(data, size, count, _ptr);
    }
    constexpr FILE* ptr() const noexcept {
      return _ptr; // 本来应该进行对 initalized 的检查并抛出错误的,但我们不依赖 STL 标准错误。
    }
    constexpr bool check_if_initalized() const noexcept {
      return initalized;
    }
    ~rtti_file() {
      close();
    }
    rtti_file(const rtti_file&) = delete;
    rtti_file() = default;
  };
  class write_stream {
    rtti_file ptr{};
    char buf[BUFSIZE];
    size_t pos = 0;
    constexpr bool check_if_available(size_t size) const noexcept {
      return size < buf_avail();
    }
   public:
    void flush() noexcept {
      ptr.fwrite(buf, sizeof(char), pos);
      pos = 0;
    }
    constexpr const rtti_file* data() const noexcept {
      return &ptr;
    }
    void open(const char* path) noexcept {
      ptr.open(fopen(path, "w"));
      pos = 0;
    }
    inline void close() noexcept {
      ptr.close();
    }
    constexpr size_t buf_avail() const noexcept {
      return BUFSIZE - pos;
    }
    // 定长版
    template <size_t N>
    const write_stream& operator<<(const char (&str)[N]) noexcept {
      return N < BUFSIZE ? (
        _safe_drop(check_if_available(N) || (flush(), true)),
        memcpy(buf + pos, str, N),
        pos += N
      ) : (
        flush(),
        ptr.fwrite(buf, sizeof(char), pos)
      ), *this;
    }
    // 不推荐使用:会触发很多次检查。
    const write_stream& operator<<(char i) {
      return (
        _safe_drop(check_if_available(1) || (flush(), true)),
        buf[pos++] = i
      ), *this;
    }
    void write_sized(const char* str, size_t size) noexcept {
      size < BUFSIZE ? (
        _safe_drop(check_if_available(size) || (flush(), true)),
        memcpy(buf + pos, str, size),
        pos += size
      ) : (
        flush(),
        ptr.fwrite(buf, sizeof(char), pos)
      );
    }
    // 不定长版
    const write_stream& operator<<(const char* str) noexcept {
      size_t len = strlen(str);
      return len < BUFSIZE ? (
        _safe_drop(check_if_available(len) || (flush(), true)),
        memcpy(buf + pos, str, len),
        pos += len
      ) : (
        flush(),
        ptr.fwrite(buf, sizeof(char), pos)
      ), *this;
    }
    // 摆烂了。
    const write_stream& operator<<(size_t n) noexcept {
      std::string q = fast_io::concat(n);
      return write_sized(q.c_str(), q.size()), *this;
    }
    ~write_stream() {
      _safe_drop(pos && (flush(), true));
    }
    write_stream() = default;
    write_stream(const write_stream&) = delete;
    explicit write_stream(const char* path) {
      open(path);
    }
  };
};
int main() {
  fast_io::timer tm(u8"stdio");
  test::write_stream stream("stdio.txt");
  for (size_t i = 0; i != 10000000; ++i) {
    stream << i;
  }
}

此代码在输出字符串时仍然比 fast_io 快速(我不知道为什么),在数字输出上略快于 fstream 而明显慢于 fast_io。如果有人知道如何改良(不使用 fast_io),请告诉我。
同样的,我努力对这段代码进行了 OOP 抽象,虽然这可能不是正确的抽象方式,但是至少我享受到了 RAII(而不是 RTTI,所以你可以加上 -fno-rtti 编译参数)。
我听从了 @trcrsired 的建议,将 filebuf 换为了 obuf,性能没有任何提升。
为什么认为安卓就是 libc++?我通过 ldd 得知这两个应用程序依赖的是 libstdc++ 而非 libc++。
为回应原作者对旧式编程方法的偏执,此实现也做了一些改变——不含if语句。

if 语句过时了(冗余+意大利面),建议使用优雅的三元表达式和逻辑运算符(不含不格式化的情况),并更多地抽出一些复杂的方法。

(看起来很不错但实际上有点麻烦。你可以看到我在一些地方使用逗号运算符来统一类型,并在一些地方使用 _safe_drop 来回避 unused expression value 警告。)
我尚未测试 benchmark 里面的示例,会在等一下完成。
这个实现可能有一些可供参考的地方,比如 write_sized 适用于可以人工确定大小的位置,而定长 operator<< 则适用于字面量(或许)。
如果说这样做会导致二进制体积膨胀,那么实际上担心错了,因为编译器可以将模板函数内部的内容直接内联(前提是实现够简单)。

非常抱歉我完全不能理解你这么多的代码是在胡闹什么。我不能理解你在使用fast_io::concat的情况下是怎么得出比fast_io快的结论的。但凡你稍微看过一点点代码,就知道fast_io库中所有输出函数共享相同的底层代码。也就是说,你这段代码的主要耗时也是由这个库实现的。同时,你提到了使用oop封装,但是在你上面的代码中我没有看到任何oop的**,相反fast_io的六层文件抽象才是李氏替代原则的应用的代表。此外,write_sized函数所对应的逻辑正是fast_io库所使用的,而你比库快是建立在抽象层次低,牺牲通用性得来的,并没有更多可取的点。

里氏替换原则是对于继承的。这个示例完全没有继承也没有子类型一说,为何学了个词就乱用呢?

加上 rtti_file 类和 write_stream 用到了组合模式。

在 OO 中,一大原则就是组合优于继承。

不知道您的 fast_io 是用组合而不用继承,还是全是继承呢?

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

来看 strace 的结果。

stdio:

write(3, "269\n575270\n575271\n575272\n575273\n"..., 8192) = 8192

fast_io:

write(3, "7461629\n7461630\n7461631\n7461632\n"..., 131056) = 131056

所谓公平公正就是用 fast_io 调大 buffer?

啊确实,玩模拟器,机能不够导致音频撕裂的时候就会调大buffer大小,但调完延迟大得很。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

来看 strace 的结果。

stdio:

write(3, "269\n575270\n575271\n575272\n575273\n"..., 8192) = 8192

fast_io:

write(3, "7461629\n7461630\n7461631\n7461632\n"..., 131056) = 131056

所谓公平公正就是用 fast_io 调大 buffer?

谁告诉你glibc的缓冲区大小是8192的?它是用的fstat得到的值。操作系统都随便乱设的。之前的wsl2还乱设到512

4096或是8192的缓冲区大小本来就是不合理的。这个值是上世纪70年代80年代的值。现在内存大的多的多,却由于abi问题导致这个值改不了。就是abi bug。C艹abi问题多了去了。

131072是gnu binutils cp测试出来的最优值。然而stdio的问题远远不只是缓冲区大小一类的。

说的好像是什么声音驱动一样。交互式流有tie,需要刷新就手工刷新。完全不用缓冲直接用native_file作非缓冲流,我就没看出任何问题。不要没事干把不相干的东西放到我这来。声卡跟我有毛关系呀。

from fast_io.

havedifficultyinfindingnames avatar havedifficultyinfindingnames commented on June 27, 2024

更大的缓冲区在实际使用中会带来更好的性能,并且如果你同时使用fast_io,他会hack iostream的实现以改善使用iostream时的表现,这是readme中清楚提到的。请完整仔细阅读readme和wiki,再来提出issue

from fast_io.

AbrasiveBoar902 avatar AbrasiveBoar902 commented on June 27, 2024

来看 strace 的结果。

stdio:

write(3, "269\n575270\n575271\n575272\n575273\n"..., 8192) = 8192

fast_io:

write(3, "7461629\n7461630\n7461631\n7461632\n"..., 131056) = 131056

所谓公平公正就是用 fast_io 调大 buffer?

啊确实,玩模拟器,机能不够导致音频撕裂的时候就会调大buffer大小,但调完延迟大得很。

没什么意义的比较,这种小聪明实际上没什么用 原来用封装都没有的基础功能和完整库相比,用针对数据特化的方法和通用方法相比,就是所谓完整和公正

真的是嘴硬
那你自己也调buffer不就行了,怎么性能就上不来呢?用别人库实现转换了性能还差的很,你还在这拿buffer说事?性能不行还找借口,原来你自己实现buffer就是公平公正(乐)

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

来看 strace 的结果。
stdio:

write(3, "269\n575270\n575271\n575272\n575273\n"..., 8192) = 8192

fast_io:

write(3, "7461629\n7461630\n7461631\n7461632\n"..., 131056) = 131056

所谓公平公正就是用 fast_io 调大 buffer?

谁告诉你glibc的缓冲区大小是8192的?它是用的fstat得到的值。操作系统都随便乱设的。之前的wsl2还乱设到512

4096或是8192的缓冲区大小本来就是不合理的。这个值是上世纪70年代80年代的值。现在内存大的多的多,却由于abi问题导致这个值改不了。就是abi bug。C艹abi问题多了去了。

131072是gnu binutils cp测试出来的最优值。然而stdio的问题远远不只是缓冲区大小一类的。

无中生有高手。我没看到任何名字包含 fstat 的系统调用返回了类似的值。

所以还是改 buffer 了?那就没意思了。

高 buffer 另一个缺点就是延迟大得很。

这里百度老哥还是太多了,收收味,这不是贴吧。

from fast_io.

havedifficultyinfindingnames avatar havedifficultyinfindingnames commented on June 27, 2024

请不要陷入无意义的争论。fast_io所有的benchmark测试代码都在benchmark目录下。请提交你的代码以及你的测试结果。在提交代码前请注意:fast_io目标是建立一个通用的输入输出库,我认为如果fast_io/stdio/iostream可以在10行内解决的代码,人们是不会愿意手写20行来实现相同的功能。

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

你这种带模板的定长串的输出方式本身就是问题,C++模板一个长度就会生成一个函数。把数组放模板里本来就是问题。你见过哪个库这么干的?字符串长度的可能性是无穷多种的,你每个都生成一份,代码不能合并导致体积炸妈,进而性能炸妈,就不是性能问题了??你这个api设计就有问题,因而基于这样的测的方式都有问题。

其次,终于承认输出整数“明显慢于fast_io”了?当性能慢于fast_io的时候你连数据都不列出了。说是摆烂。fast_io::concat是你这样用的?亲,初中生回去学习吧,不要在这浪费时间。

什么狗屁“内联”,C++里的内联指的是防ODR违反。函数都展开就比不展开快了,多出来的指令二进制体积被你吃了?间接造成上层函数体积增加,开销比你想的大的多的多。

安卓不是libc++就出鬼了。除非你是静态链接。libstdc++根本就不支持bionic

# ldd stdio
          linux-vdso.so.1 (0x0000007764bcd000)
          libstdc++.so.6 => /lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000007764940000)
          libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x00000077648a0000)
          libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000007764860000)
          libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x00000077646b0000)
          /lib/ld-linux-aarch64.so.1 (0x0000007764b90000)

from fast_io.

FurryR avatar FurryR commented on June 27, 2024

你这种带模板的定长串的输出方式本身就是问题,C++模板一个长度就会生成一个函数。把数组放模板里本来就是问题。你见过哪个库这么干的?字符串长度的可能性是无穷多种的,你每个都生成一份,代码不能合并导致体积炸妈,进而性能炸妈,就不是性能问题了??你这个api设计就有问题,因而基于这样的测的方式都有问题。
其次,终于承认输出整数“明显慢于fast_io”了?当性能慢于fast_io的时候你连数据都不列出了。说是摆烂。fast_io::concat是你这样用的?亲,初中生回去学习吧,不要在这浪费时间。
什么狗屁“内联”,C++里的内联指的是防ODR违反。函数都展开就比不展开快了,多出来的指令二进制体积被你吃了?间接造成上层函数体积增加,开销比你想的大的多的多。
安卓不是libc++就出鬼了。除非你是静态链接。libstdc++根本就不支持bionic

# ldd stdio
          linux-vdso.so.1 (0x0000007764bcd000)
          libstdc++.so.6 => /lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000007764940000)
          libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x00000077648a0000)
          libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000007764860000)                  libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x00000077646b0000)
          /lib/ld-linux-aarch64.so.1 (0x0000007764b90000)

请不要陷入无意义的争论。fast_io所有的benchmark测试代码都在benchmark目录下。请提交你的代码以及你的测试结果。在提交代码前请注意:fast_io目标是建立一个通用的输入输出库,我认为如果fast_io/stdio/iostream可以在10行内解决的代码,人们是不会愿意手写20行来实现相同的功能。

你这讲的,好比格式化日期。

如果我是商业应用,我不会傻到去用格式化库。

如果我是个人应用,我也不会为了这点性能就加上一个第三方库。

你要是整个 LD_PRELOAD 库,劫持 sprintf 等 glibc 操作并将其换成更为优化的实现,这样只要一加上 LD_PRELOAD 甚至能给 C 语言和非 C/C++ 语言程序提速,那肯定没人骂你。

但是你搞个基于 C++ 20 不说(ABI 不兼容),还和旧范式完全不兼容(能兼容,能提速吗?),那就跟个鸡肋一样食之无味弃之可惜,作者还个个跟贴吧老哥一样,那就肯定被骂了。

加上各位的测试建立在开优化的基础上,可惜很多工程不开 -O2,也没有测试时那么激进的编译参数。

from fast_io.

trcrsired avatar trcrsired commented on June 27, 2024

你这种带模板的定长串的输出方式本身就是问题,C++模板一个长度就会生成一个函数。把数组放模板里本来就是问题。你见过哪个库这么干的?字符串长度的可能性是无穷多种的,你每个都生成一份,代码不能合并导致体积炸妈,进而性能炸妈,就不是性能问题了??你这个api设计就有问题,因而基于这样的测的方式都有问题。
其次,终于承认输出整数“明显慢于fast_io”了?当性能慢于fast_io的时候你连数据都不列出了。说是摆烂。fast_io::concat是你这样用的?亲,初中生回去学习吧,不要在这浪费时间。
什么狗屁“内联”,C++里的内联指的是防ODR违反。函数都展开就比不展开快了,多出来的指令二进制体积被你吃了?间接造成上层函数体积增加,开销比你想的大的多的多。
安卓不是libc++就出鬼了。除非你是静态链接。libstdc++根本就不支持bionic

# ldd stdio
          linux-vdso.so.1 (0x0000007764bcd000)
          libstdc++.so.6 => /lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000007764940000)
          libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x00000077648a0000)
          libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000007764860000)
          libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x00000077646b0000)
          /lib/ld-linux-aarch64.so.1 (0x0000007764b90000)

aarch64-linux-gnu就不是安卓的三值。aarch64-linux-android才是安卓的三值。只能证明你刷机或是别的怎样的。

你这种带模板的定长串的输出方式本身就是问题,C++模板一个长度就会生成一个函数。把数组放模板里本来就是问题。你见过哪个库这么干的?字符串长度的可能性是无穷多种的,你每个都生成一份,代码不能合并导致体积炸妈,进而性能炸妈,就不是性能问题了??你这个api设计就有问题,因而基于这样的测的方式都有问题。
其次,终于承认输出整数“明显慢于fast_io”了?当性能慢于fast_io的时候你连数据都不列出了。说是摆烂。fast_io::concat是你这样用的?亲,初中生回去学习吧,不要在这浪费时间。
什么狗屁“内联”,C++里的内联指的是防ODR违反。函数都展开就比不展开快了,多出来的指令二进制体积被你吃了?间接造成上层函数体积增加,开销比你想的大的多的多。
安卓不是libc++就出鬼了。除非你是静态链接。libstdc++根本就不支持bionic

# ldd stdio
          linux-vdso.so.1 (0x0000007764bcd000)
          libstdc++.so.6 => /lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000007764940000)
          libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x00000077648a0000)
          libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000007764860000)                  libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x00000077646b0000)
          /lib/ld-linux-aarch64.so.1 (0x0000007764b90000)

请不要陷入无意义的争论。fast_io所有的benchmark测试代码都在benchmark目录下。请提交你的代码以及你的测试结果。在提交代码前请注意:fast_io目标是建立一个通用的输入输出库,我认为如果fast_io/stdio/iostream可以在10行内解决的代码,人们是不会愿意手写20行来实现相同的功能。

你这讲的,好比格式化日期。

如果我是商业应用,我不会傻到去用格式化库。

如果我是个人应用,我也不会为了这点性能就加上一个第三方库。

你要是整个 LD_PRELOAD 库,劫持 sprintf 等 glibc 操作并将其换成更为优化的实现,这样只要一加上 LD_PRELOAD 甚至能给 C 语言和非 C/C++ 语言程序提速,那肯定没人骂你。

但是你搞个基于 C++ 20 不说(ABI 不兼容),还和旧范式完全不兼容(能兼容,能提速吗?),那就跟个鸡肋一样食之无味弃之可惜,作者还个个跟贴吧老哥一样,那就肯定被骂了。

加上各位的测试建立在开优化的基础上,可惜很多工程不开 -O2,也没有测试时那么激进的编译参数。

C++20 ABI哪里不兼容了?libstdc++ libc++还是msvc stl哪个说了C++20 abi不兼容了?
劫持函数就不出问题了?劫持函数直接把别的程序搞炸了。

你脑子有问题,我求你用了。弱智?爱用用不用滚。

对glibc开-O2优化预编译好了,你怎么还用优化过的glibc呢。

直接屏蔽+举报。按github的规定钓鱼你号大概率没了。

重新实现io库的原因很多很多。最大的问题就是stdio和流本身api就有问题,导致根本没办法用。
stdio本身格式串不安全,流线程不安全,异常不安全,操作符重载滥用。本地化线程不安全。内核里也不能用。(事实上嵌入式全自己实现一套io,openssl都实现一套io)等等的问题就决定了不可能通过二进制层面替换解决任何问题。除非将整个io系统重写,否则根本就无解。

https://www.bilibili.com/video/av375684439/
这里有视频介绍为何需要这样一个库,解决了什么问题。你连这个库的历史都不了解,在这扯毛呢?从历史唯物主义的角度来说fast_io一定会存在,没有我最终也会有别人有类似的做法。

from fast_io.

AbrasiveBoar902 avatar AbrasiveBoar902 commented on June 27, 2024

image
差不多得了,数字+字符串混合输出直接慢十几倍,还在这嘴硬
测试1-5000万数字和"Hello World"间隔输出,用的你给的代码和最新的fast_io
如果看不到上面的图:

F:\benchmark>fast_io.exe
fast_io output:0.6916643s

F:\benchmark>yourio.exe
yourmethod output: 11.235121 s
F:\benchmark>certutil -hashfile fast_io.txt sha256
SHA256 的 fast_io.txt 哈希:
efa208d50fbcd5866fa81c2946421d4fd5668670c59c8729b084e61bd297a1c8
CertUtil: -hashfile 命令成功完成。

F:\benchmark>certutil -hashfile yourio.txt sha256
SHA256 的 yourio.txt 哈希:
efa208d50fbcd5866fa81c2946421d4fd5668670c59c8729b084e61bd297a1c8
CertUtil: -hashfile 命令成功完成。

另外,浮点输出等等你完全没有实现。

from fast_io.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.