写入 Linux 管道的速度比文件快,但在内核级别,为啥?

     2023-02-16     110

关键词:

【中文标题】写入 Linux 管道的速度比文件快,但在内核级别,为啥?【英文标题】:Writing to Linux pipe faster than file, but on a kernel level, why?写入 Linux 管道的速度比文件快,但在内核级别,为什么? 【发布时间】:2020-12-31 12:35:00 【问题描述】:

我正在研究写入文件与管道的速度。请看这段代码,除非有命令行参数,否则写入文件句柄,否则写入管道:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <chrono>
#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

using namespace std;


void do_write(int fd)

    const char* data = "Hello world!";
    int to_write = strlen(data), total_written = 0;
    
    int x = 0;
    auto start = chrono::high_resolution_clock::now();

    
    while (x < 50000)
           
        int written = 0;
        while (written != to_write)
        
            written += write(fd, data + written, to_write - written);
        
        total_written += written;
        ++x;
    
    auto end = chrono::high_resolution_clock::now();

    auto diff = end - start;
    
    cout << "Total bytes written: " <<  total_written << " in " << chrono::duration<double, milli>(diff).count() 
        << " milliseconds, " << endl;

    
int main(int argc, char *argv[])
  
    //
    // Write to file if we have not specified any extra argument
    //
    
    if (argc == 1)
       
           
            int fd = open("test.txt", O_WRONLY | O_TRUNC | O_CREAT, 0655);
            if (fd == -1) return -1;
            do_write(fd);
           
        
        return 0;
    
    
    //
    // Otherwise, write to pipe
    //
    int the_pipe[2];
    if (pipe(the_pipe) == -1) return -1;
    
    pid_t child = fork();
    switch (child)
    
    case -1:
        
            return -1;
        
    case 0:
        
            char buf[128];
            int bytes_read = 0, total_read = 0;
            close(the_pipe[1]);
            while (true)
            
                if ((bytes_read = read(the_pipe[0], buf, 128)) == 0)
                    break;
                total_read += bytes_read;
            
            cout << "Child: Total bytes read: " << total_read << endl;
            break;
        
    default:
        
            close(the_pipe[0]);
            do_write(the_pipe[1]);
            break;
        
    
    return 0;

这是我的输出:

$ time ./LinuxFlushTest pipe

Total bytes written: 600000 in 59.6544 milliseconds,

real    0m0.064s
user    0m0.020s
sys     0m0.040s
Child: Total bytes read: 600000

$ time ./LinuxFlushTest
Total bytes written: 600000 in 154.367 milliseconds,

real    0m0.159s
user    0m0.028s
sys     0m0.132s

time 输出和我的 C++ 代码时序中,您可以看到写入管道比文件快得多。

现在,据我所知,当我们调用write() 时,数据将被复制到内核缓冲区,此时pdflush 样式线程实际上会将其从页面缓存刷新到底层文件。 我没有在我的代码中强制刷新,因此没有磁盘查找延迟。

但是我不知道(而且似乎无法找到:是的,我看过内核代码但迷失在其中,所以没有像“看代码”这样的 cmets请) 写入管道时会发生什么不同:它不只是内核中某个孩子可以读取的内存块吗?那么,为什么它比写入文件的基本相同的过程要快得多?

【问题讨论】:

【参考方案1】:

现在,据我所知,当我们调用 write() 时,数据将被复制 到内核​​缓冲区,此时pdflush 样式线程将 实际上将它从页面缓存刷新到底层文件。 我是 没有在我的代码中强制刷新,因此没有磁盘查找延迟。

您似乎对此有一些误解,包括:

    您不必显式地为内核执行任何操作来将写入的数据刷新到底层输出设备。它可能会自行决定将内存中的部分甚至全部数据缓冲一段时间,但可以预期的是,即使没有来自用户空间的明确指令,内核也会在某个时候确实写入数据。这可能会受到写入数据量的影响,在您的情况下,写入的数据量似乎是中等大小的 600000 字节。

    磁盘查找并不是磁盘 I/O(相对)慢的唯一原因。即使是使用 SSD 的 I/O 也比仅使用内存的数据传输要慢。

    除其他外,标准文件系统不仅仅是一个扁平的字节跨度。即使没有任何移动部件,仍然需要与文件系统的数据结构交互以确定写入位置,并在写入时更新它。通常希望该信息立即对其他进程可见,因此它不会通常无限期延迟。

但我不知道 [...] 写信给 管道:它不只是内核中某处的一块内存吗? 孩子能读出来吗?

除此之外还有更多,但这是一个合理的初步近似值。

既然如此,为什么比 写入文件的过程基本相同?

因为写入常规文件基本相同。还有很多。

【讨论】:

谢谢;也许我确实有一些误解。让我们解决它们:对于#1,关于刷新到文件,我的概念基于@James Kanze 来自here 的答案和最终评论。此外,如果文件和管道之间的区别还有很多,您能否指出一些关于此的内容? @Wad,正如 Kanze 所说,以同步模式打开文件将确保 each write 写入的数据在 @987654325 之前传递到设备@调用返回。这并不意味着对于未在同步模式下打开的文件,永远不会有任何延迟或内核启动的刷新。 @Wad,对异地资源的请求在此不在主题范围内,但我已经对主要相关差异进行了高级视图。特别是,有一个实际的硬件设备可以在文件案例中与之交互,并且在此之上还有一个必须调解访问的文件系统。 是的,@Wad,我知道你没有使用这些标志。关键是您所指向的评论不支持您对案件行为的结论。它根本不涉及您的情况,只是可以公平地得出结论,那里的行为不知何故不同。 我怀疑您缺少的一点是您正在执行许多写入,而不仅仅是一个。在管道的情况下,接收器可以足够快地耗尽管道,从而最小化延迟写入。在文件案例中,如果(内核)I/O 缓冲区远小于您的总写入大小,您将被限制在内核可以将数据传输到磁盘以进行大部分传输的速度。

linux访问win网络快,反过来慢

您好,Linux访问Windows网络的速度可能会比反过来慢,这是由于Windows网络的安全性较高,Linux系统可能会遇到更多的安全检查,从而影响访问速度。此外,Linux和Windows系统之间的文件共享也可能会影响访问速度,因为Linux系统和Wind... 查看详情

为啥顺序写入比 HDD 上的随机写入快

】为啥顺序写入比HDD上的随机写入快【英文标题】:whysequentialwriteisfasterthanrandomwriteonHDD为什么顺序写入比HDD上的随机写入快【发布时间】:2020-08-2722:50:36【问题描述】:就像在文件尾部附加日志条目,或者就像mysql记录它的重做... 查看详情

linux查看日志文件写入速度的4种方法

...件,以此来感受系统的负载情况,因为一般情况下,日志写入越快,说明系统负载越重。本文就来介绍下Linux中查看日志增长速度的几种方法,如下:首先要介绍的是dd,因为dd命令几乎所有主流发行版都自带,无需额外安装,如... 查看详情

在linux内核级别,如何读取和写入一个硬[重复]的扇区(代码片段)

这个问题在这里已有答案: Readandwriteharddisksectordirectlyandefficiently[duplicate]2回答 出于某些原因,我需要在我的模块中读写一个硬盘扇区。我想通过内核级编程来读写扇区我的linux内核版本是3.13.0。有没有人可... 查看详情

mysqlhotcopy命令详解

...源较多,支持常用的MyISAM,innodbmysqlhotcopy只是简单的缓存写入和文件复制的过程,占用资源和备份速度比mysqldump快很多很多。特别适合大的数据库,但需要注意的是:mysqlhotcopy只支持MyISAM引擎使用mysqlhotcopy需 查看详情

java中常用io流类:bufferedreader和bufferedwriter读取文件操作(优势:使用bufferedreader读取字符文件的速度要比我们之前使用的字节流和filereader快

//复制字符文件操作BufferedReaderbf=newBufferedReader(newFileReader("//地址"));BufferedWriterwriter=newBufferedWriter(newFileWriter("//地址"));Stringstr="";while((str=bf.readLine())!=null){//一行一行的读入写入writer.write( 查看详情

linux重定向与管道符

...在屏幕上0标准输入键盘stdin仅读取1标准输出终端stdout仅写入2标准错误终端stderr仅写入3+filename其他文件读/写在Linux中构建了一个带有编号标记的通道(文件米描述符)的进程来管理打开文件通过进程连接到文件,进行文件数据的... 查看详情

ipc进程通信

...构成一种文件系统,并且只存在与内存中。数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。  管道的实质:... 查看详情

为什么.o(目标文件)链接速度比.lib(静态库)快?

在我的工作场所,我们的产品编译成可执行文件,子项目链接为静态库(.lib)或共享库(.dll)。我们使用MicrosoftC++编译器。最近我的一个同事将子项目目标从.lib(静态库)转换为.o(目标文件),并且该子项目的链接时间大幅... 查看详情

为啥 sklearn 交叉验证的 rbf 内核比线性内核快得多?

】为啥sklearn交叉验证的rbf内核比线性内核快得多?【英文标题】:Whyistherbfkernelmuchfasterthanlinearkernelforsklearncrossvalidation?为什么sklearn交叉验证的rbf内核比线性内核快得多?【发布时间】:2020-11-2916:33:34【问题描述】:我正在对250... 查看详情

LINUX FIFO 命名管道 (IPC) 在特定文件描述符处停止写入/读取消息

】LINUXFIFO命名管道(IPC)在特定文件描述符处停止写入/读取消息【英文标题】:LINUXFIFOnamedpipe(IPC)stopswriting/readingmessageatspecificfiledescriptor【发布时间】:2021-10-1311:28:08【问题描述】:我正在使用命名管道(fifo模式)在两个不相关的... 查看详情

linux6.3对ext4文件系统写入性能改进补丁

...6.3合并窗口中再获得了一些直接I/O性能改进补丁,改进了写入速度。EXT4(第四代扩展文件系统)是Linux系统下的日志文件系统,目前该系统已趋于稳定,但在Linux6.3合并窗口中再获得了一些直接I/O性能改进补丁,改进了写入速度... 查看详情

linux6.3对ext4文件系统写入性能改进补丁

...6.3合并窗口中再获得了一些直接I/O性能改进补丁,改进了写入速度。EXT4(第四代扩展文件系统)是Linux系统下的日志文件系统,目前该系统已趋于稳定,但在Linux6.3合并窗口中再获得了一些直接I/O性能改进补丁,改进了写入速度... 查看详情

kafka消息的管理

...给broker后,消息日志会被存储在broker的磁盘上,采用顺序写入的方式。顺序写可以加快磁盘访问速度,并且可以将将多个小型的逻辑写合并成一次大型的物理磁盘写入,官方数据显示顺序写比随机写入快6000倍以上。另外,操作... 查看详情

mysqldump导出来.sql文件导入数据库的速度为啥比自己写的insert语句快

...技术A导出的sql文件有锁表,插入数据时不更新索引所以速度快。 参考技术B应该不会吧···mysqldump导出来的文件可以打开的,里面的数据就是用insert插入的啊是不是因为自己做数据的话需要做循环,而导入数据库时直接执行插入... 查看详情

为啥 GPU 做矩阵乘法的速度比 CPU 快?

】为啥GPU做矩阵乘法的速度比CPU快?【英文标题】:WhycanGPUdomatrixmultiplicationfasterthanCPU?为什么GPU做矩阵乘法的速度比CPU快?【发布时间】:2018-12-2222:48:20【问题描述】:我已经使用GPU一段时间了,但现在我很好奇。为什么GPU做矩... 查看详情

写入大于系统内存的内存映射区域?

】写入大于系统内存的内存映射区域?【英文标题】:Writingtoamemorymappedregionlargerthansystemmemory?【发布时间】:2014-06-0520:42:16【问题描述】:如果我完全内存映射一个比系统内存大的文件并且写入它的速度比磁盘IO快,会发生什么... 查看详情

内核参数

...参数。可以将这些内核参数追加到Linux系统的/etc/sysctl.conf文件中,然后使用/sbin/sysctl-p命令使参数生效。1、net.core.netdev_max_backlog=262144表示当每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许发送到队列的数据... 查看详情