base64_encode源码解析
首先找到对应的c文件 base64.c,找到里面php_base64_encode函数
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); ... }
我们先来分析这段代码,因为这里涉及到内存的问题,那么我们就看
result = zend_string_safe_alloc(((length + 2) / 3), 4 * sizeof(char), 0, 0);
这啥意思呢?
申请内存,最终调用的函数是:
safe_emalloc(size_t nmemb, size_t size, size_t offset)
在wiki上解释是:
void *safe_emalloc(size_t nmemb, size_t size, size_t offset)分配缓冲区来存放每块大小为 size 字节的 nmemb 块,并附加 offset 字节。类似于 emalloc(nmemb * size + offset),但增加了针对溢出的特殊保护。
那么我可以简单的认为,就是在encode过程中,重新申请了内存,申请的内存大小是文件本身的 4/3 大小,加上原来的文件本身大小,那么峰值大小可以理解为
峰值内存= 7/3 *4.89 = 11.41
那么与我们实验过程中峰值大小基本是相符。
base64_decode操作
同样我们进行源码分析
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来进行申请内存,那么底层使用的函数就是emalloc函数,来看下wiki的解释
void *emalloc(size_t size)分配 size 字节的内存。
这个就比较好理解了,传入参数内存再进行一个double拷贝就可以,
那么我们进行一个decode的内存峰值的计算:
峰值内存=(4/3+4/3) *4.89 =13.04
基本与我们测试的结果相差不多,因为精度关系,我们进行四舍五入的计算,测试代码是精准计算,所以会有小数点偏差。
五、总结
那这就可以理解为什么一个为什么在我们一个37M的文件,不能再128M内存进行base64_encode与base64_decode操作,当然这里有一些临时变量没有及时释放内存的情况,但是通过源码分析可以知道,要做一次这样场景来进行文件上传,单纯文件的内存损耗是2.6倍左右,所以为了节省内存,我们不要再用这个方式来进行操作了,很费内存的
更多PHPCMS内容来自木庄网络博客
标签:PHPCMS
相关阅读 >>
phpcms v9后台登陆模板修改方法和程序版本更新提示修改方法
最新phpcms v9编辑器代码高亮显示亲测可用(提前格式化)
phpcms缓存使用总结(memcached、eaccelerator、shm)
更多相关阅读请进入《phpcms》频道 >>