成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux文件讀寫(xiě)機(jī)制及優(yōu)化方式

運(yùn)維 系統(tǒng)運(yùn)維
本文只討論Linux下文件的讀寫(xiě)機(jī)制,不涉及不同讀取方式如read,fread,cin等的對(duì)比,這些讀取方式本質(zhì)上都是調(diào)用系統(tǒng)api read,只是做了不同封裝。

[[171781]]

本文只討論Linux下文件的讀寫(xiě)機(jī)制,不涉及不同讀取方式如read,fread,cin等的對(duì)比,這些讀取方式本質(zhì)上都是調(diào)用系統(tǒng)api read,只是做了不同封裝。以下所有測(cè)試均使用open, read, write這一套系統(tǒng)api

緩存

緩存是用來(lái)減少高速設(shè)備訪問(wèn)低速設(shè)備所需平均時(shí)間的組件,文件讀寫(xiě)涉及到計(jì)算機(jī)內(nèi)存和磁盤(pán),內(nèi)存操作速度遠(yuǎn)遠(yuǎn)大于磁盤(pán),如果每次調(diào)用read,write都去直接操作磁盤(pán),一方面速度會(huì)被限制,一方面也會(huì)降低磁盤(pán)使用壽命,因此不管是對(duì)磁盤(pán)的讀操作還是寫(xiě)操作,操作系統(tǒng)都會(huì)將數(shù)據(jù)緩存起來(lái)

Page Cache

頁(yè)緩存(Page Cache)是位于內(nèi)存和文件之間的緩沖區(qū),它實(shí)際上也是一塊內(nèi)存區(qū)域,所有的文件IO(包括網(wǎng)絡(luò)文件)都是直接和頁(yè)緩存交互,操作系統(tǒng)通過(guò)一系列的數(shù)據(jù)結(jié)構(gòu),比如inode, address_space, struct page,實(shí)現(xiàn)將一個(gè)文件映射到頁(yè)的級(jí)別,這些具體數(shù)據(jù)結(jié)構(gòu)及之間的關(guān)系我們暫且不討論,只需知道頁(yè)緩存的存在以及它在文件IO中扮演著重要角色,很大一部分程度上,文件讀寫(xiě)的優(yōu)化就是對(duì)頁(yè)緩存使用的優(yōu)化

Dirty Page

頁(yè)緩存對(duì)應(yīng)文件中的一塊區(qū)域,如果頁(yè)緩存和對(duì)應(yīng)的文件區(qū)域內(nèi)容不一致,則該頁(yè)緩存叫做臟頁(yè)(Dirty Page)。對(duì)頁(yè)緩存進(jìn)行修改或者新建頁(yè)緩存,只要沒(méi)有刷磁盤(pán),都會(huì)產(chǎn)生臟頁(yè)

查看頁(yè)緩存大小

linux上有兩種方式查看頁(yè)緩存大小,一種是free命令

  1. $ free 
  2.              total       used       free     shared    buffers     cached 
  3. Mem:      20470840    1973416   18497424        164     270208    1202864 
  4. -/+ buffers/cache:     500344   19970496 
  5. Swap:            0          0          0 

cached那一列就是頁(yè)緩存大小,單位Byte

另一種是直接查看/proc/meminfo,這里我們只關(guān)注兩個(gè)字段

  1. Cached:          1202872 kB 
  2. Dirty:                52 kB 

Cached是頁(yè)緩存大小,Dirty是臟頁(yè)大小

臟頁(yè)回寫(xiě)參數(shù)

Linux有一些參數(shù)可以改變操作系統(tǒng)對(duì)臟頁(yè)的回寫(xiě)行為

  1. $ sysctl -a 2>/dev/null | grep dirty 
  2. vm.dirty_background_ratio = 10 
  3. vm.dirty_background_bytes = 0 
  4. vm.dirty_ratio = 20 
  5. vm.dirty_bytes = 0 
  6. vm.dirty_writeback_centisecs = 500 
  7. vm.dirty_expire_centisecs = 3000 

vm.dirty_background_ratio是內(nèi)存可以填充臟頁(yè)的百分比,當(dāng)臟頁(yè)總大小達(dá)到這個(gè)比例后,系統(tǒng)后臺(tái)進(jìn)程就會(huì)開(kāi)始將臟頁(yè)刷磁盤(pán)(vm.dirty_background_bytes類(lèi)似,只不過(guò)是通過(guò)字節(jié)數(shù)來(lái)設(shè)置)

vm.dirty_ratio是絕對(duì)的臟數(shù)據(jù)限制,內(nèi)存里的臟數(shù)據(jù)百分比不能超過(guò)這個(gè)值。如果臟數(shù)據(jù)超過(guò)這個(gè)數(shù)量,新的IO請(qǐng)求將會(huì)被阻擋,直到臟數(shù)據(jù)被寫(xiě)進(jìn)磁盤(pán)

vm.dirty_writeback_centisecs指定多長(zhǎng)時(shí)間做一次臟數(shù)據(jù)寫(xiě)回操作,單位為百分之一秒

vm.dirty_expire_centisecs指定臟數(shù)據(jù)能存活的時(shí)間,單位為百分之一秒,比如這里設(shè)置為30秒,在操作系統(tǒng)進(jìn)行寫(xiě)回操作時(shí),如果臟數(shù)據(jù)在內(nèi)存中超過(guò)30秒時(shí),就會(huì)被寫(xiě)回磁盤(pán)

這些參數(shù)可以通過(guò) sudo sysctl -w vm.dirty_background_ratio=5 這樣的命令來(lái)修改,需要root權(quán)限,也可以在root用戶(hù)下執(zhí)行 echo 5 > /proc/sys/vm/dirty_background_ratio 來(lái)修改

文件讀寫(xiě)流程

在有了頁(yè)緩存和臟頁(yè)的概念后,我們?cè)賮?lái)看文件的讀寫(xiě)流程

讀文件

  • 用戶(hù)發(fā)起read操作
  • 操作系統(tǒng)查找頁(yè)緩存
  • 若未***,則產(chǎn)生缺頁(yè)異常,然后創(chuàng)建頁(yè)緩存,并從磁盤(pán)讀取相應(yīng)頁(yè)填充頁(yè)緩存
  • 若***,則直接從頁(yè)緩存返回要讀取的內(nèi)容
  • 用戶(hù)read調(diào)用完成

寫(xiě)文件

  • 用戶(hù)發(fā)起write操作
  • 操作系統(tǒng)查找頁(yè)緩存
  • 若未***,則產(chǎn)生缺頁(yè)異常,然后創(chuàng)建頁(yè)緩存,將用戶(hù)傳入的內(nèi)容寫(xiě)入頁(yè)緩存
  • 若***,則直接將用戶(hù)傳入的內(nèi)容寫(xiě)入頁(yè)緩存
  • 用戶(hù)write調(diào)用完成
  • 頁(yè)被修改后成為臟頁(yè),操作系統(tǒng)有兩種機(jī)制將臟頁(yè)寫(xiě)回磁盤(pán)
  • 用戶(hù)手動(dòng)調(diào)用fsync()
  • 由pdflush進(jìn)程定時(shí)將臟頁(yè)寫(xiě)回磁盤(pán)

頁(yè)緩存和磁盤(pán)文件是有對(duì)應(yīng)關(guān)系的,這種關(guān)系由操作系統(tǒng)維護(hù),對(duì)頁(yè)緩存的讀寫(xiě)操作是在內(nèi)核態(tài)完成,對(duì)用戶(hù)來(lái)說(shuō)是透明的

文件讀寫(xiě)的優(yōu)化思路

不同的優(yōu)化方案適應(yīng)于不同的使用場(chǎng)景,比如文件大小,讀寫(xiě)頻次等,這里我們不考慮修改系統(tǒng)參數(shù)的方案,修改系統(tǒng)參數(shù)總是有得有失,需要選擇一個(gè)平衡點(diǎn),這和業(yè)務(wù)相關(guān)度太高,比如是否要求數(shù)據(jù)的強(qiáng)一致性,是否容忍數(shù)據(jù)丟失等等。優(yōu)化的思路有以下兩個(gè)考慮點(diǎn)

1.***化利用頁(yè)緩存

2.減少系統(tǒng)api調(diào)用次數(shù)

***點(diǎn)很容易理解,盡量讓每次IO操作都***頁(yè)緩存,這比操作磁盤(pán)會(huì)快很多,第二點(diǎn)提到的系統(tǒng)api主要是read和write,由于系統(tǒng)調(diào)用會(huì)從用戶(hù)態(tài)進(jìn)入內(nèi)核態(tài),并且有些還伴隨這內(nèi)存數(shù)據(jù)的拷貝,因此在有些場(chǎng)景下減少系統(tǒng)調(diào)用也會(huì)提高性能

readahead

readahead是一種非阻塞的系統(tǒng)調(diào)用,它會(huì)觸發(fā)操作系統(tǒng)將文件內(nèi)容預(yù)讀到頁(yè)緩存中,并且立馬返回,函數(shù)原型如下

  1. ssize_t readahead(int fd, off64_t offset, size_t count); 

在通常情況下,調(diào)用readahead后立馬調(diào)用read并不會(huì)提高讀取速度,我們通常在批量讀取或在讀取之前一段時(shí)間調(diào)用readahead,假設(shè)如下場(chǎng)景,我們需要連續(xù)讀取1000個(gè)1M的文件,有如下兩個(gè)方案,偽代碼如下

直接調(diào)用read函數(shù)

  1. char* buf = (char*)malloc(10*1024*1024); 
  2. for (int i = 0; i < 1000; ++i) 
  3.     int fd = open_file(); 
  4.     int size = stat_file_size(); 
  5.     read(fd, buf, size); 
  6.     // do something with buf 
  7.     close(fd); 

先批量調(diào)用readahead再調(diào)用read

  1. int* fds = (int*)malloc(sizeof(int)*1000); 
  2. int* fd_size = (int*)malloc(sizeof(int)*1000); 
  3. for (int i = 0; i < 1000; ++i) 
  4.     int fd = open_file(); 
  5.     int size = stat_file_size(); 
  6.     readahead(fd, 0, size); 
  7.     fds[i] = fd; 
  8.     fd_size[i] = size; 
  9. char* buf = (char*)malloc(10*1024*1024); 
  10. for (int i = 0; i < 1000; ++i) 
  11.     read(fds[i], buf, fd_size[i]); 
  12.     // do something with buf 
  13.     close(fds[i]); 

感興趣的可以寫(xiě)代碼實(shí)際測(cè)試一下,需要注意的是在測(cè)試前必須先回寫(xiě)臟頁(yè)和清空頁(yè)緩存,執(zhí)行如下命令

  1. sync && sudo sysctl -w vm.drop_caches=3 

可通過(guò)查看/proc/meminfo中的Cached及Dirty項(xiàng)確認(rèn)是否生效

通過(guò)測(cè)試發(fā)現(xiàn),第二種方法比***種讀取速度大約提高10%-20%,這種場(chǎng)景下是批量執(zhí)行readahead后立馬執(zhí)行read,優(yōu)化空間有限,如果有一種場(chǎng)景可以在read之前一段時(shí)間調(diào)用readahead,那將大大提高read本身的讀取速度

這種方案實(shí)際上是利用了操作系統(tǒng)的頁(yè)緩存,即提前觸發(fā)操作系統(tǒng)將文件讀取到頁(yè)緩存,并且操作系統(tǒng)對(duì)缺頁(yè)處理、緩存***、緩存淘汰都由一套完善的機(jī)制,雖然用戶(hù)也可以針對(duì)自己的數(shù)據(jù)做緩存管理,但和直接使用頁(yè)緩存比并沒(méi)有多大差別,而且會(huì)增加維護(hù)代價(jià)

mmap

mmap是一種內(nèi)存映射文件的方法,即將一個(gè)文件或者其它對(duì)象映射到進(jìn)程的地址空間,實(shí)現(xiàn)文件磁盤(pán)地址和進(jìn)程虛擬地址空間中一段虛擬地址的一一對(duì)映關(guān)系,函數(shù)原型如下

  1. void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 

實(shí)現(xiàn)這樣的映射關(guān)系后,進(jìn)程就可以采用指針的方式讀寫(xiě)操作這一段內(nèi)存,而系統(tǒng)會(huì)自動(dòng)回寫(xiě)臟頁(yè)面到對(duì)應(yīng)的文件磁盤(pán)上,即完成了對(duì)文件的操作而不必再調(diào)用read,write等系統(tǒng)調(diào)用函數(shù)。如下圖所示

 

 

mmap除了可以減少read,write等系統(tǒng)調(diào)用以外,還可以減少內(nèi)存的拷貝次數(shù),比如在read調(diào)用時(shí),一個(gè)完整的流程是操作系統(tǒng)讀磁盤(pán)文件到頁(yè)緩存,再?gòu)捻?yè)緩存將數(shù)據(jù)拷貝到read傳遞的buffer里,而如果使用mmap之后,操作系統(tǒng)只需要將磁盤(pán)讀到頁(yè)緩存,然后用戶(hù)就可以直接通過(guò)指針的方式操作mmap映射的內(nèi)存,減少了從內(nèi)核態(tài)到用戶(hù)態(tài)的數(shù)據(jù)拷貝

mmap適合于對(duì)同一塊區(qū)域頻繁讀寫(xiě)的情況,比如一個(gè)64M的文件存儲(chǔ)了一些索引信息,我們需要頻繁修改并持久化到磁盤(pán),這樣可以將文件通過(guò)mmap映射到用戶(hù)虛擬內(nèi)存,然后通過(guò)指針的方式修改內(nèi)存區(qū)域,由操作系統(tǒng)自動(dòng)將修改的部分刷回磁盤(pán),也可以自己調(diào)用msync手動(dòng)刷磁盤(pán)。

責(zé)任編輯:趙寧寧 來(lái)源: 小白之家
相關(guān)推薦

2011-08-10 10:12:35

2015-09-18 10:40:04

OpenStackMetadata虛擬機(jī)配置

2009-12-18 09:27:23

Ruby讀寫(xiě)excel

2011-05-23 18:12:09

SEO

2009-07-05 11:23:44

2023-11-15 18:46:49

HBase數(shù)據(jù)庫(kù)開(kāi)源

2014-06-23 17:04:25

2009-08-03 11:38:57

linux at命令詳linux at命令

2017-08-01 17:34:47

Linux內(nèi)核驅(qū)動(dòng)文件讀寫(xiě)

2024-07-08 12:51:05

2025-04-15 06:00:00

2010-04-27 09:16:49

2020-07-29 07:40:19

Linux系統(tǒng)Vim

2012-10-09 16:37:20

FastDFS

2021-02-26 20:55:56

JavaNIO隨機(jī)

2011-01-11 13:10:31

2010-05-12 14:04:29

Oracle優(yōu)化器

2024-07-26 21:29:37

2021-08-05 10:00:02

Python編程語(yǔ)言

2022-10-20 09:26:24

MySQLOracleSqlServer
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 黄久久久 | 久久成人国产精品 | 蜜桃毛片 | 中文字幕av在线播放 | 紧缚调教一区二区三区视频 | 97精品超碰一区二区三区 | 免费同性女女aaa免费网站 | 99精品欧美一区二区三区 | 一区二区三区在线播放 | 成年人免费在线视频 | 免费xxxx大片国产在线 | 国产精品九九 | 一区二区影视 | 欧美黄页| 国产一区不卡 | 国产人成精品一区二区三 | 成人免费在线 | 国产日韩免费观看 | 久久综合九色综合欧美狠狠 | 国产在线观看一区二区三区 | 自拍 亚洲 欧美 老师 丝袜 | 欧美激情精品久久久久久 | 成年无码av片在线 | 亚洲精品日日夜夜 | 久久久www成人免费精品张筱雨 | 国产黄色av网站 | 久久国产成人 | www.99热.com | 久久黄网 | 喷潮网站 | 午夜影院在线观看 | 久久99精品久久久97夜夜嗨 | 99热.com| 国产精品成人一区二区三区吃奶 | 亚洲免费三区 | 欧美狠狠操 | 日韩中文字幕2019 | 午夜寂寞福利视频 | 亚洲一区二区免费看 | 亚洲 欧美 另类 综合 偷拍 | 成人国产精品免费观看 |