摘要:然而,剛進(jìn)來(lái)就擰螺絲的人如果能夠?qū)ψx取一個(gè)的超大文件有所見(jiàn)解的話(huà),造火箭也是遲早的事兒。其中,用于告知當(dāng)前文件讀取指針?biāo)谖恢茫梢允謩?dòng)設(shè)定文件讀取指針的位置。
作為一名常年深耕curd的PHPer,關(guān)注內(nèi)存那是不可能的,反正apache或者fpm都幫我們做了,況且運(yùn)行一次就銷(xiāo)毀,根本就不存在什么內(nèi)存問(wèn)題。
然而偏偏就有些個(gè)不開(kāi)眼的人把這些個(gè)東西當(dāng)面試題,比如總有刁民用“php讀取一個(gè)10G的超大文件”當(dāng)面試題來(lái)問(wèn)你。當(dāng)然了,作為一個(gè)和我一樣的普普通通的蠢貨,你聽(tīng)到這個(gè)問(wèn)題的第一瞬間是懵逼,第二瞬間是臥槽,第三瞬間是保持結(jié)巴狀態(tài)。
“面試造火箭,入職擰螺絲”。然而,剛進(jìn)來(lái)就擰螺絲的人如果能夠?qū)Α癙HP讀取一個(gè)10G的超大文件”有所見(jiàn)解的話(huà),“造火箭”也是遲早的事兒。當(dāng)前為了能夠來(lái)這里“擰螺絲”,還是得先搞定“讀取10G文件”這個(gè)問(wèn)題。
要想讀取10G的文件,首先,你得有個(gè)10G的文件
... ...
其實(shí),相對(duì)來(lái)說(shuō)也是比較簡(jiǎn)單的事情,我們隨便找一個(gè)nginx的日志文件,哪怕只有10KB,假設(shè)文件名是test.log,然后呢執(zhí)行" cat test.log >> test.log ",聽(tīng)我說(shuō)少年,30秒左右你就該按下ctrl + C了,比如我這里,你們感受一下:
202MB,作為實(shí)驗(yàn)演示,夠意思了。難不成真要造10G的文件?
首先,我們嘗試用php的file函數(shù)來(lái)作一把死,你們感受一下:
保存為test.php,然后命令行下執(zhí)行一把,結(jié)果如下圖所示:
這句英文的大概意思就是“PHP最大只給每個(gè)進(jìn)程分配了128MB內(nèi)存,然而你特么張口要202MB?”所以,我們修改一下php配置文件... ...
千萬(wàn)不要手軟,把這個(gè)參數(shù)改成1024MB,然后再次執(zhí)行上面的php腳本:
然后,我們?cè)僭囋囎類(lèi)?ài)的file_get_contents()函數(shù),結(jié)果如下圖:
文件已經(jīng)一次性全部被載入到內(nèi)存中并將文件的每一行保存到了一個(gè)php數(shù)組中,我的機(jī)器是10G內(nèi)存+256G固態(tài)硬盤(pán),一次性載入這個(gè)202MB的文件file函數(shù)用了0.67秒鐘、file_get_contents函數(shù)用了0.25秒鐘(看起來(lái)file_get_content要比f(wàn)ile靠譜的多),不過(guò),敲重點(diǎn)的我們調(diào)整了配置文件才可以讀取202MB的文件,如果擺在我們面前的是一個(gè)100G的文件呢?或者說(shuō),系統(tǒng)提供的php配置最多之給20MB內(nèi)存而你又無(wú)法修改呢?
我們重點(diǎn)是如何在內(nèi)存有限的機(jī)器上讀取體積幾百倍于內(nèi)存的文件。下面,我們把memory_limit調(diào)整成16M,開(kāi)啟困難模式。
202MB的文件,允許被分配的內(nèi)存為16MB,所以,總體思路其實(shí)也很簡(jiǎn)單,就是一點(diǎn)兒一點(diǎn)兒地讀,只要每次讀取的內(nèi)容小于16MB,那就一定不會(huì)有問(wèn)題,首先我們感受一下一個(gè)字符一個(gè)字符讀,出場(chǎng)嘉賓是fgetc函數(shù):
運(yùn)行結(jié)果如下圖:
雖然只有給了16M內(nèi)存,但我們還是成功將202M文件全部讀出來(lái)了,只不過(guò)這個(gè)運(yùn)行速度是差了那么點(diǎn)兒意思,不大行。不能一個(gè)字母一個(gè)字母地讀,這次我們一行一行地讀:
運(yùn)行結(jié)果如下圖:
一行一行果然比一個(gè)一個(gè)字符要快很多,轉(zhuǎn)念一想吧,系統(tǒng)分配給我們的內(nèi)存上限是16MB,那我們索性一次讀取一定量容量數(shù)據(jù)看看,會(huì)不會(huì)更快:
保存代碼,運(yùn)行一把,屌了屌了?。。≡趦?nèi)存有限的情況下,我們還把時(shí)間縮短到了0.1秒!
然后我們考慮將問(wèn)題升級(jí)一下,依然是上述這個(gè)202M的文件,這次我們要求讀取倒數(shù)后5行的內(nèi)容,這個(gè)問(wèn)題看起來(lái)屌了些許,用原來(lái)的fread啥的雖然奏效但總感覺(jué)比較愚蠢。所以,現(xiàn)在又得引入全新的函數(shù)來(lái)解決這個(gè)問(wèn)題:ftell和fseek。其中,ftell用于告知當(dāng)前文件讀取指針?biāo)谖恢?,fseek可以手動(dòng)設(shè)定文件讀取指針的位置。我建議大家去手冊(cè)上重點(diǎn)觀(guān)摩一下fseek函數(shù):點(diǎn)擊這里。
0 ){ while( $ch != " " ){ fseek( $fp, $pos, SEEK_END ); $ch = fgetc( $fp ); $pos--; } $ch = ""; $content .= fgets( $fp ); $line--; } echo $content; exit;其中test1.log文件的內(nèi)容如下:
aa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccc ffffdffffdffffdffffdffffdffffdffffdffffdffffdffffddd eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ffffffffffffffffffffffffffffffff bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccc ffffdffffdffffdffffdffffdffffdffffdffffdffffdffffddd eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ffffffffffffffffffffffffffffffff bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccc ffffdffffdffffdffffdffffdffffdffffdffffdffffdffffddd eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ffffffffffffffffffffffffffffffff bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccc ffffdffffdffffdffffdffffdffffdffffdffffdffffdffffddd eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ffffffffffffffffffffffffffffffff bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccc ffffdffffdffffdffffdffffdffffdffffdffffdffffdffffddd eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ffffffffffffffffffffffffffffffff bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccc ffffdffffdffffdffffdffffdffffdffffdffffdffffdffffddd eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ffffffffffffffffffffffffffffffff 1111111111 2222222222保存文件并運(yùn)行,結(jié)果如下圖所示:
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/29736.html
摘要:在中,會(huì)為每個(gè)不同的用戶(hù)生成一個(gè)隨機(jī)的,每個(gè)人擁有的都是不同的。值得注意的是,過(guò)期了不代表這個(gè)文件會(huì)馬上被垃圾回收機(jī)制刪除掉,還是有可能會(huì)殘存一段時(shí)間的。 原文地址:https://t.ti-node.com/thread/... 這基本上算是個(gè)老舊的話(huà)題了,幾乎所有phper在第一次面試的時(shí)候都會(huì)被問(wèn)到關(guān)于session的問(wèn)題,如果不出意外,往往是如下三板斧: php的sessi...
摘要:這篇筆記主要解決這么幾個(gè)問(wèn)題如何使用超低內(nèi)存快速遍歷數(shù)以萬(wàn)計(jì)的目錄文件如何使用超低內(nèi)存快速讀取幾百甚至是級(jí)文件順便解決哪天我忘了可以通過(guò)搜索引擎搜到我自己寫(xiě)的筆記來(lái)看看。 這不是一篇教程,這是一篇筆記,所以我不會(huì)很系統(tǒng)地論述原理和實(shí)現(xiàn),只簡(jiǎn)單說(shuō)明和舉例。 前言 我寫(xiě)這篇筆記的原因是現(xiàn)在網(wǎng)絡(luò)上關(guān)于 PHP 遍歷目錄文件和 PHP 讀取文本文件的教程和示例代碼都是極其低效的,低效就算了,有...
摘要:場(chǎng)景和痛點(diǎn)說(shuō)明今天因?yàn)橐粋€(gè)老同學(xué)找我,說(shuō)自己公司的物流業(yè)務(wù)都是現(xiàn)在用處理,按月因?yàn)閿?shù)據(jù)量大,一個(gè)差不多有百萬(wàn)數(shù)據(jù),文件有接近,打開(kāi)和搜索就相當(dāng)?shù)穆?lián)想到場(chǎng)景要導(dǎo)入數(shù)據(jù),可能數(shù)據(jù)量很大,這里利用常用的一些方法比如會(huì)常有時(shí)間和內(nèi)存限制問(wèn)題下面我 場(chǎng)景和痛點(diǎn) 說(shuō)明 今天因?yàn)橐粋€(gè)老同學(xué)找我,說(shuō)自己公司的物流業(yè)務(wù)都是現(xiàn)在用excel處理,按月因?yàn)閿?shù)據(jù)量大,一個(gè)excel差不多有百萬(wàn)數(shù)據(jù),文件有接...
摘要:能異步地發(fā)送任意數(shù)據(jù)的技術(shù)稱(chēng)為,表示異步的和。若你使用,使用發(fā)送表單還會(huì)影響同源策略,并導(dǎo)致內(nèi)容被發(fā)送到一個(gè)無(wú)法訪(fǎng)問(wèn)的中。但要手動(dòng)發(fā)送二進(jìn)制數(shù)據(jù)的話(huà),還有很多額外工作要做。用來(lái)發(fā)送二進(jìn)制是很直接的,使用方法就好了。 系列文章說(shuō)明 原文 在[發(fā)送表單數(shù)據(jù)]()一文中,HTML表單可以聲明式地發(fā)送一個(gè)HTTP請(qǐng)求。但表單也可以用JavaScript來(lái)準(zhǔn)備一個(gè)HTTP請(qǐng)求。本文將探索如何...
閱讀 1464·2021-11-24 09:39
閱讀 1783·2021-11-22 15:25
閱讀 3736·2021-11-19 09:40
閱讀 3296·2021-09-22 15:31
閱讀 1296·2021-07-29 13:49
閱讀 1205·2019-08-26 11:59
閱讀 1318·2019-08-26 11:39
閱讀 929·2019-08-26 11:00