日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

PHP 實(shí)現(xiàn)base64編碼文件上傳出現(xiàn)問題詳解

瀏覽:171日期:2022-09-09 09:23:42

一、場(chǎng)景

領(lǐng)導(dǎo):小A同學(xué),我們要做一個(gè)樣本上傳進(jìn)行分析的功能,你看下是否使用base64編碼加進(jìn)去,這樣客戶端的同學(xué)就不需要用form-data方式來上傳了,直接使用json格式就可以上報(bào),可以讓格式上報(bào)統(tǒng)一。

小A:好的,領(lǐng)導(dǎo),馬上搞定!

咋看上面的對(duì)話沒啥問題,很多公司團(tuán)隊(duì)內(nèi)部為了一些標(biāo)準(zhǔn)化的問題,都會(huì)進(jìn)行一些技術(shù)選型問題,但是噩夢(mèng)也就從這個(gè)對(duì)話開始,功能實(shí)現(xiàn)當(dāng)然都是很簡(jiǎn)單的,先來看簡(jiǎn)單流程圖:

PHP 實(shí)現(xiàn)base64編碼文件上傳出現(xiàn)問題詳解

本身的流程是一個(gè)很簡(jiǎn)單的文件轉(zhuǎn)換成base64上傳,再服務(wù)端decode保存,在開發(fā)聯(lián)調(diào)過程中沒有問題,非常完美的走下去了。

二、問題來了

突然有一天終端同學(xué)誤操作將一個(gè)37M文件上傳,nginx與php-fpm文件上傳限制均為(60M),但是在界面出現(xiàn)500錯(cuò)誤,進(jìn)入docker 日志查看有一條數(shù)據(jù):

Allowed memory size of 8388608 bytes exhausted (tried to allocate 1298358 bytes)

玩php的基本都知道這是啥意思,就是代碼運(yùn)行過程中使用內(nèi)存超過 我們php.ini設(shè)置的memory_limit 的值,然后就屁顛屁顛進(jìn)入php.ini找參數(shù)配置,很快找到:

memory_limit=128M

然后就轉(zhuǎn)念一想,不應(yīng)該出現(xiàn)這個(gè)問題,我們知道,php的內(nèi)部變量使用cow(寫時(shí)復(fù)制)機(jī)制來實(shí)現(xiàn),那么內(nèi)存申請(qǐng)只有在變量賦值變更才會(huì)進(jìn)行

三、測(cè)驗(yàn)

接下來我們單獨(dú)寫一個(gè)程序來進(jìn)行測(cè)試,將一個(gè)4.89M文件進(jìn)行base64_encode 編碼 與base64_decode解碼,查看各自占用內(nèi)存以及過程中占用峰值內(nèi)存

<?php$mid = memory_get_usage();$apk_content = file_get_contents(__DIR__ . ’/4bc1c8a05b8505662be778b6dad23b55.apk’);var_dump(’文件加載到內(nèi)存:’ . round((memory_get_usage() - $mid) / 1024 / 1024, 2) . ’M’);var_dump(’過程中峰值使用的內(nèi)存:’ . round(memory_get_peak_usage() / 1024 / 1024, 2) . ’M’);unset($mid);$mid = memory_get_usage();$base64_encode = base64_encode($apk_content);unset($apk_content);var_dump(’base64_encode占用內(nèi)存:’ . round((memory_get_usage() - $mid) / 1024 / 1024, 2) . ’M’);var_dump(’過程中峰值使用的內(nèi)存:’ . round(memory_get_peak_usage() / 1024 / 1024, 2) . ’M’);unset($mid);$mid = memory_get_usage();base64_decode($base64_encode);var_dump(’base64_decode占用內(nèi)存:’ . round((memory_get_usage() - $mid) / 1024 / 1024, 2) . ’M’);var_dump(’過程中峰值使用的內(nèi)存:’ . round(memory_get_peak_usage() / 1024 / 1024, 2) . ’M’);unset($mid);

執(zhí)行結(jié)果:

string(29) '文件加載到內(nèi)存:4.89M'string(38) '過程中峰值使用的內(nèi)存:5.25M'string(33) 'base64_encode占用內(nèi)存:1.63M'string(39) '過程中峰值使用的內(nèi)存:11.76M'string(30) 'base64_decode占用內(nèi)存:0M'string(38) '過程中峰值使用的內(nèi)存:13.4M'

通過上面結(jié)果可以看出

加載文件使用內(nèi)存沒有太大問題,加載過程使用的峰值在5.25M,高出整體文件大小不多,這在文件加載過程有一些臨時(shí)申請(qǐng)內(nèi)存的問題 base64_encode占用內(nèi)存,這個(gè)在使用的時(shí)候,就已經(jīng)將內(nèi)存差不多進(jìn)行一個(gè)double,而這基本上也是在內(nèi)核解析過程中,進(jìn)行了內(nèi)存申請(qǐng),可以理解,文件本身占用內(nèi)存+base64_encode 解析后的內(nèi)存,兩份內(nèi)存同時(shí)存在的 base64_decode操作,這個(gè)操作就是解密了,解密過程中,這里直接就占用了3倍多的內(nèi)存操作,問題就出在這里,在場(chǎng)景中出現(xiàn)的問題是一個(gè)37M的文件,為什么就把單個(gè)fpm的128M內(nèi)存占滿了呢

四、源碼解析

base64_encode源碼解析

首先找到對(duì)應(yīng)的c文件 base64.c,找到里面php_base64_encode函數(shù)

PHPAPI zend_string *php_base64_encode(const unsigned char *str, size_t length) /* {{{ */{const unsigned char *current = str;unsigned char *p;zend_string *result;result = zend_string_safe_alloc(((length + 2) / 3), 4 * sizeof(char), 0, 0);p = (unsigned char *)ZSTR_VAL(result); ...}

我們先來分析這段代碼,因?yàn)檫@里涉及到內(nèi)存的問題,那么我們就看

result = zend_string_safe_alloc(((length + 2) / 3), 4 * sizeof(char), 0, 0);

這啥意思呢?

申請(qǐng)內(nèi)存,最終調(diào)用的函數(shù)是:

safe_emalloc(size_t nmemb, size_t size, size_t offset)

在wiki上解釋是:

void *safe_emalloc(size_t nmemb, size_t size, size_t offset)分配緩沖區(qū)來存放每塊大小為 size 字節(jié)的 nmemb 塊,并附加 offset 字節(jié)。類似于 emalloc(nmemb * size + offset),但增加了針對(duì)溢出的特殊保護(hù)。

那么我可以簡(jiǎn)單的認(rèn)為,就是在encode過程中,重新申請(qǐng)了內(nèi)存,申請(qǐng)的內(nèi)存大小是文件本身的 4/3 大小,加上原來的文件本身大小,那么峰值大小可以理解為

峰值內(nèi)存= 7/3 *4.89 = 11.41

那么與我們實(shí)驗(yàn)過程中峰值大小基本是相符。

base64_decode操作

同樣我們進(jìn)行源碼分析

PHPAPI zend_string *php_base64_decode_ex(const unsigned char *str, size_t length, zend_bool strict) /* {{{ */{const unsigned char *current = str;int ch, i = 0, j = 0, padding = 0;zend_string *result;result = zend_string_alloc(length, 0);...}

這里使用的zend_string_alloc來進(jìn)行申請(qǐng)內(nèi)存,那么底層使用的函數(shù)就是emalloc函數(shù),來看下wiki的解釋

void *emalloc(size_t size)分配 size 字節(jié)的內(nèi)存。

這個(gè)就比較好理解了,傳入?yún)?shù)內(nèi)存再進(jìn)行一個(gè)double拷貝就可以,

那么我們進(jìn)行一個(gè)decode的內(nèi)存峰值的計(jì)算:

峰值內(nèi)存=(4/3+4/3) *4.89 =13.04

基本與我們測(cè)試的結(jié)果相差不多,因?yàn)榫汝P(guān)系,我們進(jìn)行四舍五入的計(jì)算,測(cè)試代碼是精準(zhǔn)計(jì)算,所以會(huì)有小數(shù)點(diǎn)偏差。

五、總結(jié)

那這就可以理解為什么一個(gè)為什么在我們一個(gè)37M的文件,不能再128M內(nèi)存進(jìn)行base64_encode與base64_decode操作,當(dāng)然這里有一些臨時(shí)變量沒有及時(shí)釋放內(nèi)存的情況,但是通過源碼分析可以知道,要做一次這樣場(chǎng)景來進(jìn)行文件上傳,單純文件的內(nèi)存損耗是2.6倍左右,所以為了節(jié)省內(nèi)存,我們不要再用這個(gè)方式來進(jìn)行操作了,很費(fèi)內(nèi)存的

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: PHP
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
黄色精品视频| 国产免费av一区二区三区| 久久国产婷婷国产香蕉| 亚洲人成高清| 91精品啪在线观看国产爱臀| 69堂免费精品视频在线播放| 青青国产精品| 国产精品qvod| 亚洲国产成人二区| 九九九精品视频| 国产一区丝袜| 性感美女一区二区在线观看| 91精品国产自产在线观看永久∴ | 国产精品白浆| 青青草伊人久久| 国产精品亚洲四区在线观看| 久久99久久久精品欧美| 成人国产精品久久| 亚洲激情中文| 国产精品av一区二区| 亚洲大全视频| 黄色免费成人| 亚洲毛片视频| 久久wwww| 日韩在线观看一区| 1024精品久久久久久久久| 最新国产精品| 久久精品国产亚洲aⅴ | 国产精品亚洲综合久久| 国产suv精品一区| 亚洲精品一区二区妖精| 亚洲精品在线a| 韩日一区二区| 99视频一区| 国产欧美69| 日韩欧美视频专区| 视频在线观看国产精品| 国产精品高清一区二区| 色婷婷久久久| 日本一不卡视频| sm捆绑调教国产免费网站在线观看 | 午夜电影一区| 精品国产午夜肉伦伦影院| 久久精品欧美一区| 亚洲三级国产| 精品99久久| 国产精品99久久免费| 久久精品青草| 奇米狠狠一区二区三区| 午夜精品婷婷| 久久精品国产亚洲夜色av网站| 四季av一区二区凹凸精品| 国产精品主播| 国产99精品一区| 日韩国产欧美在线播放| 日韩免费小视频| 日韩一区网站| 国产99久久| 国产黄色一区| 国产精品女主播一区二区三区| 久久av电影| 国产亚洲毛片在线| 国产精品福利在线观看播放| 99久久亚洲精品蜜臀| 91精品国产经典在线观看| 秋霞影院一区二区三区| 国产免费av一区二区三区| 免费av一区| 成午夜精品一区二区三区软件| 亚洲视频二区| 91看片一区| 欧美精品aa| 免费在线视频一区| 激情亚洲影院在线观看| 国产美女精品视频免费播放软件| 米奇777超碰欧美日韩亚洲| 国产经典一区| 天堂va欧美ⅴa亚洲va一国产| 色在线中文字幕| 欧美日韩一区二区三区不卡视频 | 久久精品九色| 色欧美自拍视频| 国产精品探花在线观看| 亚洲网址在线观看| 在线一区二区三区视频| 国产精品中文字幕亚洲欧美 | 久久99视频| 亚洲性视频h| 国产精品v亚洲精品v日韩精品| 老鸭窝亚洲一区二区三区| 亚洲国产成人二区| 国产精品亚洲人成在99www| 亚洲一区观看| 欧美日韩免费观看视频| 老司机免费视频一区二区| 亚洲三级网站| 蜜臀久久久99精品久久久久久| 99久久精品费精品国产| 久久久久久自在自线| 国产精品2023| 91欧美精品| 久久高清国产| 亚洲福利国产| 美女av在线免费看| 91中文字幕精品永久在线| 久久国产视频网| 日韩精品一页| 日韩精品91亚洲二区在线观看| 一区二区亚洲视频| 国产精品婷婷| 国产亚洲高清视频| 亚洲激情偷拍| 中文亚洲免费| 丝瓜av网站精品一区二区| 最新日韩欧美| 夜夜嗨av一区二区三区网站四季av| 日韩不卡在线| 91看片一区| 99视频精品全国免费| 久久在线电影| 黄色日韩在线| 天堂成人国产精品一区| 鲁大师影院一区二区三区| 国产视频亚洲| 免费日韩av| 亚洲精品亚洲人成在线观看| 少妇精品久久久一区二区| 亚洲精品大片| 奇米狠狠一区二区三区| 欧美精品国产白浆久久久久| **爰片久久毛片| 日韩av网站在线观看| 国产毛片久久久| 精品久久中文| 亚洲性色av| 欧美久久精品一级c片| 中日韩男男gay无套| 男人的天堂久久精品| 日本在线成人| 国产麻豆精品久久| 国内在线观看一区二区三区| av免费不卡国产观看| 一区二区三区视频免费观看| 午夜久久久久| 中文不卡在线| 国产精品videossex久久发布| 国产精品成久久久久| 超碰在线99| 婷婷中文字幕一区| 亚洲另类黄色| 国产精品久久久久久久久免费高清| 久久久久97| 99久久亚洲精品蜜臀| 国产亚洲在线| 91精品国产自产精品男人的天堂| 国产精品白浆| 久久精品青草| 亚洲欧美日本国产| 国产精品久久久久久久久免费高清| 精品72久久久久中文字幕| 999国产精品| 一区二区三区四区在线观看国产日韩 | 国产精品国产三级在线观看| 免费一级欧美在线观看视频| 色偷偷偷在线视频播放| 午夜一级久久| 国产精品久久久久久妇女 | 丝袜国产日韩另类美女| 91亚洲精品在看在线观看高清 | 国产精品视频一区视频二区| 成人在线视频免费| 欧美日韩水蜜桃| 欧美日韩亚洲一区二区三区在线| av资源中文在线天堂| 久久xxxx精品视频| 精品三级国产| 亚洲欧美日韩在线观看a三区| 国产日本精品| 不卡在线一区二区| 国产精品一区高清| 蜜桃国内精品久久久久软件9| 日韩精品福利一区二区三区| 麻豆网站免费在线观看| 日韩精品一二三| 精品久久美女| 亚洲精品少妇| 欧美三级网址| 日韩高清不卡在线| 久久精品观看| 国产精品极品国产中出| 在线视频亚洲| av中文字幕在线观看第一页| 亚洲乱亚洲高清| 日本欧美不卡| 嫩草伊人久久精品少妇av杨幂| 红桃视频国产一区| 国产精品xx| 欧美日韩亚洲一区二区三区在线| 激情婷婷久久| 激情久久一区二区|