linux文件读取中的Readahead预读机制

Page Cache之Readahead   readahead即预读,提前从块设备(如硬盘)里多读一些page缓存到page cache tree,以便下次读时能直接从page cache中命中,而不需要触发实际块设备的访问,提高IO效率。  那么什么时候readahead,readahead多少个page呢?     调用系统调用read时,先find page cache,若cache miss则进行sync readahead;若... 阅读详情
AI摘要

本文深入探讨Linux的Readahead预读机制,详细分析其如何通过同步和异步预读提升文件读取效率,减少磁盘I/O延迟。通过实际案例,展示预读机制在连续读操作中的工作流程。

Readahead预读机制

由于内存的速度比磁盘速度快很多,如果每一次访问文件数据都要从磁盘读取一次数据,就会导致非常严重的时延。因此Linux为了提高性能,通过page cache机制,将多个用户数据缓存在内存当中,从而避免多次再磁盘读取。Readahead预读机制正是将用户数据缓存到内存的方法之一。

Readahead机制的介绍

Readahead预读机制是Linux针对顺序读的性能优化机制。它的核心思想是当用户访问连续多个page的时候,一次性将多个连续的页从磁盘读取到内存中,从而避免多次与磁盘交互,降低性能。

Readahead机制的源码分析

预读行为的在generic_file_buffered_read函数做了具体实现,如下:

static ssize_t generic_file_buffered_read(struct kiocb *iocb,
        struct iov_iter *iter, ssize_t written)
{
    ...
    for (;;) {
        page = find_get_page(mapping, index); // 访问特定index的page
        if (!page) { // 如果是NULL,即在page cache找不到
            page_cache_sync_readahead(mapping,
                    ra, filp,
                    index, last_index - index); // 进行同步预读
            page = find_get_page(mapping, index); // 预读以后再获取一次
        }
        if (PageReadahead(page)) { // 如果读取出来的page包含Readahead的特殊标志
            page_cache_async_readahead(mapping,
                    ra, filp, page,
                    index, last_index - index); // 进行一次异步预读
        }
    }
    ...
}

从上面可以知道,当find_get_page函数无法在page cache中找到该index对应的page的实例,就会调用page_cache_sync_readahead函数进行同步预读,预读完的数据就会加入到page cache中,再一次调用find_get_page函数就可以获取出来。

page index=1的页以及异步预读出来的最后一个页会包含特殊标志,这个标志可以通过PageReadahead函数进行判断,从而判断是否需要调用page_cache_async_readahead进行异步预读。

同步预读以及异步预读都会调用同一个函数ondemand_readahead,只是输入参数不一样,如下所示:

void page_cache_sync_readahead(struct address_space *mapping,
                   struct file_ra_state *ra, struct file *filp,
                   pgoff_t offset, unsigned long req_size)
{
    if (!ra->ra_pages)
        return;

    if (blk_cgroup_congested())
        return;

    if (filp && (filp->f_mode & FMODE_RANDOM)) {
        force_page_cache_readahead(mapping, filp, offset, req_size);
        return;
    }

    ondemand_readahead(mapping, ra, filp, false, offset, req_size);
}
page_cache_async_readahead(struct address_space *mapping,
               struct file_ra_state *ra, struct file *filp,
               struct page *page, pgoff_t offset,
               unsigned long req_size)
{
    if (!ra->ra_pages)
        return;

    if (PageWriteback(page))
        return;

    ClearPageReadahead(page); // 如前面所述,异步预读的最后一个页会特殊的标志,再一次触发异步预读后在这里清除标志

    if (inode_read_congested(mapping->host))
        return;

    if (blk_cgroup_congested())
        return;

    ondemand_readahead(mapping, ra, filp, true, offset, req_size);
}

根据代码,同步预读和异步预读传入ondemand_readahead函数的第四个参数不一样,一个是False一个是True。为了搞清楚差异,继续分析ondemand_readahead函数的源码。

static unsigned long
ondemand_readahead(struct address_space *mapping,
           struct file_ra_state *ra, struct file *filp,
           bool hit_readahead_marker, pgoff_t offset,
           unsigned long req_size)
{
    struct backing_dev_info *bdi = inode_to_bdi(mapping->host);
    unsigned long max_pages = ra->ra_pages; // 一般值是32
    unsigned long add_pages;
    pgoff_t prev_offset;
    
    /*
     * 根据条件,计算本次预读最大预读取多少个页,一般情况下是max_pages=32个页
     */
    if (req_size > max_pages && bdi->io_pages > max_pages)
        max_pages = min(req_size, bdi->io_pages);
    /*
     * offset即page index,如果page index=0,表示这是文件第一个页,跳转到initial_readahead进行处理
     */
    if (!offset)
        goto initial_readahead;

    /*
     * 默认情况下是 ra->start=0, ra->size=0, ra->async_size=0 ra->prev_pos=0
     * 但是经过第一次预读后,上面三个值会出现变化
     */
    if ((offset == (ra->start + ra->size - ra->async_size) ||
         offset == (ra->start + ra->size))) {
        ra->start += ra->size;
        ra->size = get_next_ra_size(ra, max_pages);
        ra->async_size = ra->size;
        goto readit;
    }

    /*
     * 异步预读的时候会进入这个判断,更新ra的值,然后预读特定的范围的页
     * 异步预读的调用表示Readahead出来的页连续命中
     */
    if (hit_readahead_marker) {
        pgoff_t start;

        rcu_read_lock();
        // 这个函数用于找到offset + 1开始到offset + 1 + max_pages这个范围内,第一个不在page cache的页的index
        start = page_cache_next_miss(mapping, offset + 1, max_pages);
        rcu_read_unlock();

        if (!start || start - offset > max_pages)
            return 0;

        ra->start = start;
        ra->size = start - offset;    /* old async_size */
        ra->size += req_size;
        /* 
         * 由于连续命中,get_next_ra_size会加倍上次的预读页数
         * 第一次预读了4个页
         * 第二次命中以后,预读8个页
         * 第三次命中以后,预读16个页
         * 第四次命中以后,预读32个页,达到默认情况下最大的读取页数
         * 第五次、第六次、第N次命中都是预读32个页
         * */
        ra->size = get_next_ra_size(ra, max_pages);
        ra->async_size = ra->size;
        goto readit;
    }

    if (req_size > max_pages)
        goto initial_readahead;

    prev_offset = (unsigned long long)ra->prev_pos >> PAGE_SHIFT;
    if (offset - prev_offset <= 1UL)
        goto initial_readahead;

    if (try_context_readahead(mapping, ra, offset, req_size, max_pages))
        goto readit;
    // 这个函数执行具体的从磁盘读取的流程
    return __do_page_cache_readahead(mapping, filp, offset, req_size, 0);

initial_readahead:
    ra->start = offset;
    /* get_init_ra_size初始化第一次预读的页的个数,一般情况下第一次预读是4个页 */
    ra->size = get_init_ra_size(req_size, max_pages);
    ra->async_size = ra->size > req_size ? ra->size - req_size : ra->size;

readit:
    if (offset == ra->start && ra->size == ra->async_size) {
        add_pages = get_next_ra_size(ra, max_pages);
        if (ra->size + add_pages <= max_pages) {
            ra->async_size = add_pages;
            ra->size += add_pages;
        } else {
            ra->size = max_pages;
            ra->async_size = max_pages >> 1;
        }
    }
    /* 
     * 经过一点处理以后,会调用__do_page_cache_readahead函数,执行具体的从磁盘读取的流程 
     * 区别在于它是基于ra->start ra->async_size等信息进行读取
     * */
    return ra_submit(ra, mapping, filp);
}

当第一个页(page index=0)传入函数时,跳到initial_readahead部分,初始化ra->start、ra->size以及ra->async_size等信息,然后调用ra_submit进行读取。

当第一个页以外传入函数时,需要根据hit_readahead_marker判断同步预读还是异步预读,同步则根据offset和req_size进行预读,如果是异步则通过ra->start以及ra->async_size进行预读。

ondemand_readahead函数的核心是__do_page_cache_readahead函数,它会根据传入的参数,从磁盘读取特定范围的数据:

unsigned int __do_page_cache_readahead(struct address_space *mapping,
        struct file *filp, pgoff_t offset, unsigned long nr_to_read,
        unsigned long lookahead_size)
{
    struct inode *inode = mapping->host;
    struct page *page;
    unsigned long end_index;
    LIST_HEAD(page_pool); // 将要读取的页存入到这个list当中
    int page_idx;
    unsigned int nr_pages = 0;
    loff_t isize = i_size_read(inode); // 得到文件的大小
    gfp_t gfp_mask = readahead_gfp_mask(mapping);

    end_index = ((isize - 1) >> PAGE_SHIFT); // 根据文件大小计算得到最后一个页的index

    for (page_idx = 0; page_idx < nr_to_read; page_idx++) {
        pgoff_t page_offset = offset + page_idx; // 计算得到page index

        if (page_offset > end_index) // 超过了文件的尺寸就break,停止读取
            break;

        rcu_read_lock();
         // 查看是否在page cache,如果已经在了cache中,再判断是否为脏,要不要进行读取
        page = radix_tree_lookup(&mapping->i_pages, page_offset);
        rcu_read_unlock();
        if (page && !radix_tree_exceptional_entry(page)) {
            if (nr_pages)
                read_pages(mapping, filp, &page_pool, nr_pages, gfp_mask);
            nr_pages = 0;
            continue;
        }
        // 如果不存在,则创建一个page cache结构
        page = __page_cache_alloc(gfp_mask);
        if (!page)
            break;
        // 设定page cache的index
        page->index = page_offset;
        // 加入到list当中
        list_add(&page->lru, &page_pool);
        // !!! 注意计算值,给这一个页加上Readahead的标志
        if (page_idx == nr_to_read - lookahead_size)
            SetPageReadahead(page);
        nr_pages++;
    }

    /*
     * 如果nr_pages大于0,则表示有页要进行读取
     * 执行read_pages从磁盘进行读取
     */
    if (nr_pages)
        read_pages(mapping, filp, &page_pool, nr_pages, gfp_mask);
out:
    return nr_pages;
}

Readahead机制的实例分析

下面通过一个顺序读的例子说明Linux预读机制的执行:

用户需要连续访问某个文件连续32个页(page index=0~31)的数据,那么它在预读机制下的访问行为是:

用户访问第一个页,page index=0,触发同步预读机制,一次性从磁盘读取4个页,即第1~4个页(page index=0~3)
用户访问第二个页,page index=1,含有特殊标志,触发异步预读机制,一次性从磁盘读取8个页,即第5~12个页(page index=4~11)
用户访问第三个页,page index=2,命中,直接返回给用户
用户访问第四个页,page index=3,命中,直接返回给用户
用户访问第五个页,page index=4,含有特殊标志,触发异步预读机制,一次性从磁盘读取16个页,即第13~28个页(page index=12~27)
用户访问第六个页,page index=5,命中,直接返回给用户
用户访问第七个页,page index=6,命中,直接返回给用户
用户访问第八个页,page index=7,命中,直接返回给用户
用户访问第九个页,page index=8,命中,直接返回给用户
用户访问第十个页,page index=9,命中,直接返回给用户
用户访问第十一个页,page index=10,命中,直接返回给用户
用户访问第十二个页,page index=11,命中,直接返回给用户
用户访问第十三个页,page index=12,含有特殊标志,触发异步预读机制,一次性从磁盘读取32个页,即第12~42个页(page index=13~43),但是由于page index=12~27的页上一次预读就将页读入了page cache,因此会跳过,实际上只会从磁盘读取page index=28~43页。
…以此类推

当访问第一个页时,跳到initial_readahead部分,初始化ra->start=0、ra->size=4以及ra->async_size=3,因此预读取了page index=0~3的页,并且给page index=1的页加上了标志。

访问第二个页(page index=1)时,由于有预读标志,因此进行异步预读。异步预读会增大预读页数,将预读页数由4个页增大到8个页,以次类推。
 

Linux文件系统预读(一) 本博客主要阐述最新内核(linux-3.12)的文件系统预读及时的设计和实现,可能有理解不全面的地方,望各位能多多指教。 所谓的预读,值的是文件系统为应用程序一次读出比预期更多的文件内容,当然,这个细节对应用程序透明,应用程序可能的感觉唯一就是下次读的速度会更快,当然这是好事。 同步预读         让我们设想这样一种情境:进程P打开文件f,读offset从0开始size 阅读详情

相关推荐

BEVFusion实战:从零搭建LiDAR-Camera融合的3D目标检测环境(附避坑指南)

本文提供了BEVFusion实战指南,详细讲解如何从零搭建LiDAR-Camera融合的3D目标检测环境。内容涵盖环境配置、数据预处理、模型训练与性能优化等关键步骤,并附有实用的避坑技巧,帮助开发者高效部署这一先进的BEV感知算法。

p4q5r6s7t的博客 514

Linux 读文件 - readahead预读算法

根据ondemand_readahead中initial_readahead label处逻辑看,ra->size是由get_init_ra_size函数计算,该函数第一个参数是应用read的数据页(每个数据页4K)的数量,该场景每次读取4K bytes,相当于调用get_init_ra_size(1,32)返回4。这里async readahead就是指generic_file_buffered_read函数中的:page_cache_async_readahead函数调用。: 开始预读的数据页索引,

GetnextWindow的专栏 1557

CentOS 7下Multipath多路径存储的实战配置与性能优化

本文详细介绍了在CentOS 7系统中配置与优化Multipath多路径存储的完整实战流程。从安装部署、核心配置文件解读,到性能调优与生产环境避坑指南,全面解析如何利用Device Mapper Multipath构建高可用、负载均衡的存储链路,提升存储系统可靠性与I/O性能。

weixin_29278805的博客 320

Linux read的核心函数generic_file_buffered_read

【代码】Linux read的核心函数generic_file_buffered_read。

GetnextWindow的专栏 1179

中国1986-2024年30米分辨率年最大NDVI数据集:条带修复技术与植被动态监测

本文介绍了中国1986-2024年30米分辨率年最大NDVI数据集的构建,重点阐述了针对Landsat 7 SLC-off故障等问题的条带修复技术。通过应用GapFill等核心算法,该数据集有效修复了数据缺失,为长时间序列的植被动态监测、生态变迁分析和极端气候事件评估提供了高质量、连续可靠的数据基础。

weixin_29200485的博客 167

内网环境下的高德地图离线化实战:从瓦片下载到交互功能集成

本文详细介绍了在内网环境中部署离线高德地图的完整实战方案。针对军工、能源、金融等对网络隔离与数据安全有严格要求的场景,文章核心解决了离线地图的两大基石:地图瓦片数据的高效下载与本地化,以及高德地图JS API的获取与插件集成。通过具体代码示例,进一步讲解了如何实现地图初始化、海量点标注与聚合、自定义图标及框选查询等核心交互功能,并分享了内网部署的路径配置、性能优化及法律合规等关键注意事项,为开发者在封闭网络环境下构建稳定、可控的地图应用提供了清晰指南。

Apple的专栏 394

Linux readahead文件预读

​ Linux read/mmap 时将文件从磁盘读区到内存当中,read读取文件操作必然会带来IO如果能直接从内存当中读取文件这样就能有效的解决IO及延迟问题。page cache的诞生就是解决这个问题,文件读取后将文件对应的物理page 添加到redix tree当中管理后续在做同样的读取操作时就直接从page cache当中直接读取文件。这个机制本质上来讲与硬件架构的cache原理上是想通的,理解cache机制有助于理解page cache。

谨以此记录下自己的每一点、每一滴、每一步,以督促自己,不忘目标,不忘理想。 1530

BitLocker磁盘锁定解决方法

摘要:本文介绍了BitLocker加密磁盘被锁的两种情况及解决方法。对于系统盘锁定,建议在微软账户中查找48位恢复密钥;数据盘锁定可尝试密码或恢复密钥解锁。若密钥丢失,可通过IT支持或数据恢复服务尝试解决。预防措施包括妥善备份密钥到微软账户和离线位置,避免随意更改系统硬件配置。BitLocker安全性高,恢复密钥是解锁关键,提醒用户务必做好备份以防数据丢失。(148字)

yueke06442300的专栏 2672

科普文:软件架构Linux系列之【Linux的文件预读readahead】

在前面讲MySQL优化器时,我们有讲到MySQL的MRR多范围读取优化。 MRR,全称 Multi-Range Read Optimization可以知道它是对范围读取的优化,MRR 是对索引读取的优化,提高索引的查询性能,原理是充分利用磁盘预读机制,把磁盘随机读取,转换为磁盘顺序读取,从而提高磁盘读取的性能。今天我们继续看看操作系统Linux的文件预读readahead。

为无为,事无事,味无味。 1797

MFC Windows 程序设计[105]之彩色滚动条(附源码)

MFC是微软公司提供的一个类库(class libraries),用以减少应用程序开发人员的工作量。其中包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。有很多初学MFC的小伙伴们都觉得MFC比较难学,看书吧,看了就忘了,网上的一些教程又是写的含糊不清,故而学习起来很吃力...... 故此,本专栏亲自研究,实践,由易到难,层层深入,将调试过程中所遭所遇进行详细讲解,注意事项进行一一列举,希望能够帮助到各位初学MFC的小伙伴,避免走弯路,费时费力。

hnjzfwy的博客 518

多体动力学分析软件:SIMPACK_(3).SIMPACK模型创建与编辑

在 SIMPACK 中,模型的创建与编辑是多体动力学分析的基础。通过了解模型的基本结构、创建方法、编辑技巧和高级功能,用户可以高效地构建和优化复杂的多体系统模型。无论是手动创建、通过脚本创建还是导入现有的 CAD 模型,SIMPACK 都提供了强大的工具和灵活的接口,帮助用户实现精确和高效的仿真分析。希望本节内容对您在 SIMPACK 中进行多体系统建模有所帮助。如有任何问题或需要进一步的指导,请参考 SIMPACK 的官方文档或联系技术支持。

kkchenjj的博客 1011

Linux内核的文件预读值的修改,Linux内核的文件预读readahead

Linux的文件预读readahead,指Linux系统内核将指定文件的某区域预读进页缓存起来,便于接下来对该区域进行读取时,不会因缺页(pagefault)而阻塞。因为从内存读取比从磁盘读取要快很多。预读可以有效的减少磁盘的寻道次数和应用程序的I/O等待时间,是改进磁盘读I/O性能的重要优化手段之一。维基百科上关于readhead的介绍资料:readaheadis a system call o...

weixin_36377635的博客 747

【ubuntu24.04】auto remove后,重启,kernel panic ,please reboot your computer vfs unable to mount root fs

Ubuntu 24.04系统在运行auto remove后出现内核恐慌(kernel panic)无法启动,显示"VFS: unable to mount root fs"错误。该问题是由于当前内核被清除导致系统无法挂载根分区。解决步骤包括:1)尝试用GRUB菜单中的旧内核启动;2)在GRUB中临时编辑启动参数;3)使用Ubuntu启动盘进行chroot修复;4)使用Boot-Repair工具一键修复。成功启动后,需要重新安装linux-generic等元包,重建initramfs并更新

突围 1209

VFS源码分析-Readahead预读机制

Readahead预读机制 由于内存的速度比磁盘速度快很多,如果每一次访问文件数据都要从磁盘读取一次数据,就会导致非常严重的时延。因此Linux为了提高性能,通过page cache机制,将多个用户数据缓存在内存当中,从而避免多次再磁盘读取。Readahead预读机制正是将用户数据缓存到内存的方法之一。 Readahead机制的介绍 Readahead预读机制是Linux针对顺序读的性能优化机制。...

Hubery的存储点滴 1896

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

文件预读readahead内核优化提升文件读取性能

之前写过一篇文章《page cache之文件预读readahead内核源码详解》,主要讲解了内核vfs层文件预读内核源码。受内核block层io_uring异步机制的影响,觉得可以对内核预读机制优化,提升文件读取性能。 首先,我们需知晓,内核文件预读机制本身可以一定程度提升文件读取性能,这点在《page cache之文件预读readahead内核源码详解》中就提到过,我们这里再简单提下。比如,我们cat test读取文件,每次read系统调用只读取64K字节的文件数据: 第1次执行read系统调用,读

dongzhiyan_hjp 3302

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

page cache之文件预读readahead内核源码详解

提起linux内核的文件预读机制,很多小伙伴肯定是听说过的,为什么预读机制可以提高性能?怎么让初学者快速理解预读机制呢?实践下来觉得还是用示意图举例最简单。本文首先根据实际读取文件的测试数据,用示意图讲解讲解预读机制,然后讲解相关内核源码。内核源码基于3.10.96,详细源码注释见https://github.com/dongzhiyan-stack/kernel-code-comment。 1 文件预读示意图讲解 测试命令很简单cat test >/dev/null,test文件之前没有...

dongzhiyan_hjp 3519

Linux内核的文件预读(readahead)

编者按:Linux文件预读算法磁盘I/O性能的发展远远滞后于CPU和内存,因而成为现代计算机系统的一个主要瓶颈。预读可以有效的减少磁盘的寻 道次数和应用程序的I/O等待时间,是改进磁盘读I/O性能的重要优化手段之一。本文作者是中国科学技术大学自动化系的博士生,他在1998年开始学习 Linux,为了优化服务器的性能,他开始尝试改进Linux kernel,并最终重写了内核的文件预读部分,这些改进被...

夏天Alex 2766

Linux内核的文件预读readahead

nux的文件预读readahead,指Linux系统内核将指定文件的某区域预读进页缓存起来,便于接下来对该区域进行读取时,不会因缺页(page fault)而阻塞。因为从内存读取比从磁盘读取要快很多。预读可以有效的减少磁盘的寻道次数和应用程序的I/O等待时间,是改进磁盘读I/O性能的重要优化手段之一。 维基百科上关于readhead的介绍资料: readahead is a system call of the Linux kernel that loads a file's contents into

qq_42894864的博客 571

[转]Linux内核的文件预读(readahead)

编者按:Linux文件预读算法磁盘I/O性能的发展远远滞后于CPU和内存,因而成为现代计算机系统的一个主要瓶颈。预读可以有效的减少磁盘的寻道次数和应用程序的I/O等待时间,是改进磁盘读I/O性能的重要优化手段之一。本文作者是中国科学技术大学自动化系的博士生,他在1998年开始学习Linux,为了优化服务器的性能,他开始尝试改进Linux kernel,并最终重写了内核的文件预读部分,这些改进被收录到Linux Kernel 2.6.23及其后续版本中。从寄存器、L1/L2高速缓存、内存、闪存,到磁盘/光盘/

6437

文件的预读

为了优化读取文件的时间延迟,文件系统(FS)在去磁盘读取文件时会有一个read_ahead的动作。主要思路是:当FS发现用户读取文件是按照文件的顺序读取,FS就假定用户在下一次读取时大概率会读取下一个block。所以FS在把当前的block读取到内存后,会发送读取下一个block的命令,然后将当前block数据返回给用户。这样用户在处理数据的时候,磁盘IO也在并行的执行(如果是DMA的方式,磁盘IO在完成之后,会通过中断的方式告诉FS)

qq_41104683的博客 534

Linux内核的文件预读机制详解

为什么需要文件预读机制? 算法磁盘I/O性能的发展远远滞后于CPU和内存,因而成为现代计算机系统的一个主要瓶颈。预读可以有效的减少磁盘的寻道次数和应用程序的I/O等待时间,是改进磁盘读I/O性能的重要优化手段之一。 从寄存器、L1/L2高速缓存、内存、闪存,到磁盘/光盘/磁带/存储网络,计算机的各级存储器硬件组成了一个金字塔结构。越是底层存储容量越大。然而访问速度也越慢,具体表现为更小的带宽和更大的延迟。因而这很自然的便成为一个金字塔形的逐层缓存结构。由此产生了三类基本的缓存管理和优化问题: 预取

私房菜 1562

Linux内核的文件预读机制

前者自动自发的进行预读决策,对上层应用是透明的,但是对算法的要求较高,存在命中率的问题;改进后的算法通过监控所有完整的read()调用,同时得到读请求的页面偏移量和数量,因而能够更好的区分顺序读和随机读。磁盘的机械臂+旋转盘片的数据定位与读取方式,决定了它最突出的性能特点:擅长顺序读写,不善于随机I/O,I/O延迟非常大。预读可以有效的减少磁盘的寻道次数和应用程序的I/O等待时间,是改进磁盘读I/O性能的重要优化手段之一。批量,也就是把小I/O聚集为大I/O,以改善磁盘的利用率,提升系统的吞吐量。

nb_zsy的博客 753

Linux文件预读对系统的影响

Linux系统很重要的一个性能提升点就是它的Pagecache, 因为内存比IO快太多了,所以大家都想进办法来利用这个cache。 文件系统也不例外,为了达到高性能,文件读取通常采用预读来预测用户的行为,把用户可能需要的数据预先读取到cache去,达到高性能的目的。 Linux各个发行版readahead的实现差异很大,我们这里重点讨论2.6.18, RHEL 5U4发行版的行为.文件预读的

mimi886的专栏 848

3、预读机制与预读失效

预读机制(Readahead)是操作系统或数据库的一种性能优化策略:当程序读取某个文件块时,系统会预先把后续相邻的数据块也加载到内存中以减少将来可能发生的磁盘 I/O。📖例子(Linux Page Cache)磁盘最小读取单位是 4KB block;操作系统不仅读 [0,4KB),还会额外读 [4KB,8KB)、[8KB,12KB)、[12KB,16KB);这样下一次若访问 8KB 数据时,就可以直接命中缓存。📈减少磁盘 I/O 次数,提高吞吐量。

bamboo_tt的博客 417

文件的预读操作分析

预读的两个优势: 1 )每个 IO 一般涉及一组较大相邻的扇区,预读使磁盘控制器处理较少的命令。 2 )提高系统的响应能力,顺序读取的文件一般不需要等待请求的数据   文件的顺序访问:如果请求的第一页紧跟上次访问所请求的最后一页,就认为是顺序的。   1.   主要的数据结构 /*   * Track a single files readahead state

guogaofeng1219的专栏 976
上一篇: 宋宝华:关于Ftrace的一个完整案例
下一篇: Linux内核中的likely()和unlikely()宏
土豆西瓜大芝麻
博客等级 码龄18年 1189粉丝 238原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值