内存泄露PHP
① php-fpm子进程会自动重启吗
服务器出现异常,网站不能正常访问。经排查�php的问题。
在重启php-fpm时,恢复正常。1分钟之后又出现故障。查看php日志文件/usr/local/php/var/log 后提示
WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
子进程数已经达到设置的最大值。
要设置php进程数量。需要在php-fpm.conf文件中修改。
先看/usr/local/php/etc/php-fpm.conf文件各项配置解析
pid = run/php-fpm.pid
#pid设置,默认在安装目录中的var/run/php-fpm.pid,建议开启
error_log = log/php-fpm.log
#错误日志,默认在安装目录中的var/log/php-fpm.log
log_level = notice
#错误级别. 可用级别为: alert(必须立即处理), error(错误情况), warning(警告情况), notice(一般重要信息), debug(调试信息). 默认: notice.
emergency_restart_threshold = 60
emergency_restart_interval = 60s
#表示在emergency_restart_interval所设值内出现SIGSEGV或者SIGBUS错误的php-cgi进程数如果超过 emergency_restart_threshold个,php-fpm就会优雅重启。这两个选项一般保持默认值。
process_control_timeout = 0
#设置子进程接受主进程复用信号的超时时间. 可用单位: s(秒), m(分), h(小时), 或者 d(天) 默认单位: s(秒). 默认值: 0.
daemonize = yes
#后台执行fpm,默认值为yes,如果为了调试可以改为no。在FPM中,可以使用不同的设置来运行多个进程池。 这些设置可以针对每个进程池单独设置。
listen = 127.0.0.1:9000
#fpm监听端口,即nginx中php处理的地址,一般默认值即可。可用格式为: ‘ip:port’, ‘port’, ‘/path/to/unix/socket’. 每个进程池都需要设置.
listen.backlog = -1
#backlog数,-1表示无限制,由操作系统决定,此行注释掉就行。backlog含义参考:
http://www.3gyou.cc/?p=41
listen.allowed_clients = 127.0.0.1
#允许访问FastCGI进程的IP,设置any为不限制IP,如果要设置其他主机的nginx也能访问这台FPM进程,listen处要设置成本地可被访问的IP。默认值是any。每个地址是用逗号分隔. 如果没有设置或者为空,则允许任何服务器请求连接
listen.owner = www
listen.group = www
listen.mode = 0666
#unix socket设置选项,如果使用tcp方式访问,这里注释即可。
user = www
group = www
#启动进程的帐户和组
pm = dynamic #对于专用服务器,pm可以设置为static。
#如何控制子进程,选项有static和dynamic。如果选择static,则由pm.max_children指定固定的子进程数。如果选择dynamic,则由下开参数决定:
pm.max_children #,子进程最大数
pm.start_servers #,启动时的进程数
pm.min_spare_servers #,保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程
pm.max_spare_servers #,保证空闲进程数最大值,如果空闲进程大于此值,此进行清理
pm.max_requests = 1000
#设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 ’0′ 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0.
pm.status_path = /status
#FPM状态页面的网址. 如果没有设置, 则无法访问状态页面. 默认值: none. munin监控会使用到
ping.path = /ping
#FPM监控页面的ping网址. 如果没有设置, 则无法访问ping页面. 该页面用于外部检测FPM是否存活并且可以响应请求. 请注意必须以斜线开头 (/)。
ping.response = pong
#用于定义ping请求的返回相应. 返回为 HTTP 200 的 text/plain 格式文本. 默认值: pong.
request_terminate_timeout = 0
#设置单个请求的超时中止时间. 该选项可能会对php.ini设置中的’max_execution_time’因为某些特殊原因没有中止运行的脚本有用. 设置为 ’0′ 表示 ‘Off’.当经常出现502错误时可以尝试更改此选项。
request_slowlog_timeout = 10s
#当一个请求该设置的超时时间后,就会将对应的PHP调用堆栈信息完整写入到慢日志中. 设置为 ’0′ 表示 ‘Off’
slowlog = log/$pool.log.slow
#慢请求的记录日志,配合request_slowlog_timeout使用
rlimit_files = 1024
#设置文件打开描述符的rlimit限制. 默认值: 系统定义值默认可打开句柄是1024,可使用 ulimit -n查看,ulimit -n 2048修改。
rlimit_core = 0
#设置核心rlimit最大限制值. 可用值: ‘unlimited’ 、0或者正整数. 默认值: 系统定义值.
chroot =
#启动时的Chroot目录. 所定义的目录需要是绝对路径. 如果没有设置, 则chroot不被使用.
chdir =
#设置启动目录,启动时会自动Chdir到该目录. 所定义的目录需要是绝对路径. 默认值: 当前目录,或者/目录(chroot时)
catch_workers_output = yes
#重定向运行过程中的stdout和stderr到主要的错误日志文件中. 如果没有设置, stdout 和 stderr 将会根据FastCGI的规则被重定向到 /dev/null . 默认值: 空.
根据以上配置的解析,在php-fpm.conf文件中添加如下配置:
pm.max_children = 100
pm.start_servers = 30
pm.min_spare_servers = 20
pm.max_spare_servers = 100
以观后效。
另附豆瓣技术贴:https://www.douban.com/note/315222037/
1、php-fpm优化参数介绍
他们分别是:pm、pm.max_children、pm.start_servers、pm.min_spare_servers、pm.max_spare_servers。
pm:表示使用那种方式,有两个值可以选择,就是static(静态)或者dynamic(动态)。
在更老一些的版本中,dynamic被称作apache-like。这个要注意看配置文件的说明。
下面4个参数的意思分别为:
pm.max_children:静态方式下开启的php-fpm进程数量
pm.start_servers:动态方式下的起始php-fpm进程数量
pm.min_spare_servers:动态方式下的最小php-fpm进程数
pm.max_spare_servers:动态方式下的最大php-fpm进程数量
区别:
如果dm设置为 static,那么其实只有pm.max_children这个参数生效。系统会开启设置数量的php-fpm进程。
如果dm设置为 dynamic,那么pm.max_children参数失效,后面3个参数生效。
系统会在php-fpm运行开始 的时候启动pm.start_servers个php-fpm进程,
然后根据系统的需求动态在pm.min_spare_servers和pm.max_spare_servers之间调整php-fpm进程数
2、服务器具体配置
对于我们的服务器,选择哪种执行方式比较好呢?事实上,跟Apache一样,运行的PHP程序在执行完成后,或多或少会有内存泄露的问题。
这也是为什么开始的时候一个php-fpm进程只占用3M左右内存,运行一段时间后就会上升到20-30M的原因了。
对于内存大的服务器(比如8G以上)来说,指定静态的max_children实际上更为妥当,因为这样不需要进行额外的进程数目控制,会提高效率。
因为频繁开关php-fpm进程也会有时滞,所以内存够大的情况下开静态效果会更好。数量也可以根据 内存/30M 得到,比如8GB内存可以设置为100,
那么php-fpm耗费的内存就能控制在 2G-3G的样子。如果内存稍微小点,比如1G,那么指定静态的进程数量更加有利于服务器的稳定。
这样可以保证php-fpm只获取够用的内存,将不多的内存分配给其他应用去使用,会使系统的运行更加畅通。
对于小内存的服务器来说,比如256M内存的VPS,即使按照一个20M的内存量来算,10个php-cgi进程就将耗掉200M内存,那系统的崩溃就应该很正常了。
因此应该尽量地控制php-fpm进程的数量,大体明确其他应用占用的内存后,给它指定一个静态的小数量,会让系统更加平稳一些。或者使用动态方式,
因为动态方式会结束掉多余的进程,可以回收释放一些内存,所以推荐在内存较少的服务器或VPS上使用。具体最大数量根据 内存/20M 得到。
比如说512M的VPS,建议pm.max_spare_servers设置为20。至于pm.min_spare_servers,则建议根据服务器的负载情况来设置,比如服务器上只是部署php环境的话,比较合适的值在5~10之间。
本服务器配置
1、服务器基本信息:
硬盘:数据盘30G、系统盘20G
内存:1.5G
CPU:双核
系统:CentOS 6.3 64位
带宽:独享2M
2、部署的应用
Git、SVN、Apache、Tomcat、PHP、Nginx、mysql、JDK
3、优化后的参数
pm = dynamic
pm.start_servers = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 8
② php如何释放file函数的内存
file函数一般只占用系统
句柄
资源。读取其中的内容并保存至某个变量会占用内存,跟file函数无关。
file函数在打开之后,需要用close关闭并释放file句柄,否则可能会导致其他程序不能打开这个文件(文件锁定)。
除了用alloc等函数显式分配内存的外,一般不需要专门
释放内存
,系统会在结束时自动回收内存。
③ 什么是php垃圾回收机制
以下摘自网络:
对象引用计数器机制回收:
php 5.3之前使用的垃圾回收机制是单纯的“引用计数”,也就是每个内存对象都分配一个计数器,当内存对象被变量引用时,计数器+1;当变量引用撤掉后,计数器-1;当计数器=0时,表明内存对象没有被使用,该内存对象则进行销毁,垃圾回收完成。
“引用计数”存在问题,就是当两个或多个对象互相引用形成环状后,内存对象的计数器则不会消减为0;这时候,这一组内存对象已经没用了,但是不能回收,从而导致内存泄露。
php5.3开始,使用了新的垃圾回收机制,在引用计数基础上,实现了一种复杂的算法,来检测内存对象中引用环的存在,以避免内存泄露。
示例代码:
class A{
private $b;
function __construct(){
$this->b = new B($this);
}
function __destruct(){
//echo "A destruct\n";
}
function out(){
echo 'oooo',"\n";
}
}
class B{
private $a;
function __construct($a){
$this->a = $a;
}
function __destruct(){
//echo "B descturct\n";
}
}
for($i=0;;$i++){
$a = new A();
if($i00 == 0){
echo memory_get_usage()."\n";
}
}
引起计数器+1的操作:
$a=new A();
$b=&$a;
引起计数器-1的操作:
unset($a);
引起计数器值0对象并释放内存:
$a=null;
内存相关的函数:
memory_get_usage()返回当前分配给你的 PHP 脚本的内存量,单位是字节(byte)
memory_get_peak_usage()返回分配给 PHP 内存的峰值
mysql_free_result() 手动释放mysql结果集内存
gc_enable();//开启gc自动回收
gc_collect_cycles();//执行一次回收周期
gc_disable();//关闭gc自动回收周期
xdebug_debug_zval(变量名)//加载完xdebug后,可以用这个函数查看变量的状态
请采纳!
④ php是什么意思
php通常指超文本预处理器,用于面向对象、命令式编程,是一种通用开源脚本语言。
主要特点:
为开源性和免费性、快捷性、数据库连接的广泛性、面向过程和面向对象并用。优点是利于学习,使用广泛。此外,php还可以指菲律宾比索的标准货币代码符号,MPLS网络中的倒数第二跳弹出功能。是英文超级文本预处理语言Hypertext Preprocessor的缩写。PHP 是一种HTML 内嵌式的语言,是一种在服务器端执行嵌入HTML文档的脚本语言,语言风格有些类似于C语言,被广泛的运用。
简介:
PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。
特性包括:
1、PHP 独特的语法混合了 C、Java、Perl 以及 PHP 自创新的语法
2、PHP可以比CGI或者Perl更快速的执行动态网页——动态页面方面,与其他的编程语言相比,PHP是将程序嵌入到HTML文档中去执行,执行效率比完全生成htmL标记的CGI要高许多;PHP具有非常强大的功能,所有的CGI的功能PHP都能实现
3、 PHP支持几乎所有流行的数据库以及操作系统。
4、最重要的是PHP可以用C、C++进行程序的扩展!
语言特点:
开源免费
PHP是一个受众大并且拥有众多开发者的开源软件项目,linux + Nginx + Mysql + PHP是它的经典安装部署方式,相关的软件全部都是开源免费的,所以使用PHP可以节约大量的正版授权费用。不过PHP作为一个开源软件,它缺乏大型科技公司的支持背景,网络上对它的唱衰也是经久不衰,不过它的持续迭代和性能持续增强的现实却是鼓舞人心的,PHP社区用实际行动给予各种质疑强有力的回击。
快捷高效
PHP的内核是C语言编写的基础好效率高,可以用C语言开发高性能的扩展组件;PHP的核心包含了数量超过1000的内置函数,功能应有尽有很全面,开箱即用程序代码简洁; PHP数组支持动态扩容,支持以数字、字符串或者混合键名的关联数组,能大幅提高开发效率; PHP是一门弱类型语言,程序编译通过率高,相对其他强类型语言开发效率快;PHP天然热部署,在php-fpm运行模式下代码文件覆盖即完成热部署;PHP经过20多年的发展,在互联网上可以搜到海量的参考资料供参考学习。
性能提升
PHP版本越高它的整体性能越高,根据官方介绍,PHP7.0.0 对比PHP5.6性能就提升了2倍,PHP7.4已经比PHP7.0快了约30%,PHP8.0在性能上又相对PHP7.4大约改进了10%。PHP 8.0 引入了 JIT编译器特性,同时加入多种新的语言功能,例如命名参数、联合类型、注解、Constructor Property Promotion、match 表达式、nullsafe 运算符以及对类型系统、错误处理和一致性的改进。PHP拥有自己的核心开发团队,保持5年发布一个大版本、1个月发布2个小版本的频率,最新的版本是PHP8.08 。
跨平台
每个平台都有对应的php解释器版本,指针对不同平台均编译出目标平台的二进制码(PHP解释器),php开发的程序可以不经修改运行在windows、linux、unix等多个操作系统上。
常驻内存
php-cli模式下可以实现程序常驻内存,各种变量和数据库连接都能长久保存在内存实现资源复用,比较常用的做法是结合swoole 组件编写cli框架。
页面生命周期
在php-fpm模式下,所有的变量都是页面级的,无论是全局变量还是类的静态成员,都会在页面执行完毕后被清空,对程序员水平要求低,占用内存非常少,特别适合中小型系统的开发。
运行机制:
PHP常见的运行模式有2种,分别是php-fpm 和php-cli 。当PHP 选择运行在php-fpm模式下,所有的变量都是页面级的,无论是全局变量还是类的静态成员,都会在页面执行完毕后被清空。运行在php-cli模式下可以实现程序常驻内存,各种变量和数据库连接都能长久保存在内存 实现资源复用,性能可以得到很大的提升,php-cli开发比较复杂能但是能够获取更高的性能,对开发者的要求比较高需要比较高的开发水平,比较常用的模式是结合swoole 组件编写cli框架,各种变量能保存在跨进程的高性能共享内存 Table ,可以开发出支持热启动的php-cli可靠各类应用系统。
php-fpm在PHP 5.3.3 版本成为了官方正式组件(2010-07-22),它提供了稳定可靠的进程管理服务,进程不足时候可以智能扩充数量,闲置时候可以自动回收销毁多余的进程,同时它对程序的容错能力很强大运行非常稳定,可以应付企业级的开发需求。php-fpm友好的完成了使用HTTP/HTTPS等TCP/IP互联网协议下进行的用户的输入输出,页面级生命周期各种资源用完即释放,不存在内存泄漏的问题。php-fpm也提供有一些常驻内存的技术支持,例如PHP 7.4引入的opcache.preload也能实现局部的PHP类和函数的常驻内存,不过这个方法不够灵活,和服务器配置捆绑的太死了。
php-cli因为能实现各类资源的常驻内存,所以可以资源复用,更高效完成多进程编程和异步编程,可以开发出负载能力更高的应用系统。但是相对php-fpm的简单编程开发,开发者要注意很多的事项和需要做很多附加的控制器开发,否则就无法实现期待中的高性能。
首先开发者需要去实现可靠的进程管理服务,保证系统进程遇到各类错误退出运行后能够自动创建新的进程,只有这样才能保证后续的服务请求有足够空闲进程可分配。每个业务代码段都要做异常处理,让进程遇到非致命错误时候不会退出,因为进程重启意味程序和各类资源需要再次加载,这个过程性能消耗不小,所以只有进程稳定运行了常驻内存才有意义。
其次因为常驻内存,编写的新的程序必须重启服务才能生效,这一点习惯了fpm模式的开发者会感到比较陌生。另外开发者需要手工释放内存,否则系统长时间运行后会出现内存泄露。同时在cli模式下,我们不能像fpm里直接用 $_SERVER、$_POST、$_GET、$_COOKI和$_FILES 进行编程工作,需要自己去解析各种互联网通讯协议完成用户的输入输出。要实现多进程编程利用多核CPU计算,还有学习使用pcntl和posix编程,这里涉及到了异步编程逻辑,这块难度还是比较大的。比较常用的模式是结合swoole 组件编写cli框架。
PHP是一个活跃的社区开发语言,有专业的核心开发团队在持续不断的迭代,最近一个版本就是PHP 8.0.8 引入了很多的新特性。
语言参考:
内置函数
PHP 有很多标准的函数和结构。还有一些函数需要和特定的扩展模块一起编译,否则在使用它们的时候就会得到一个致命的“未定义函数”错误。例如,要使用 image 函数中的 imagecreatetrue,需要在编译 PHP 的时候加上 GD 的支持。或者要使用 mysqli_connect函数,就需要在编译 PHP 的时候加上 MySQLi 支持。有很多核心函数已包含在每个版本的 PHP 中如字符串和变量函数。调用 phpinfo或者 get_loaded_extensions可以得知 PHP 加载了那些扩展库。同时还应该注意,很多扩展库默认就是有效的。
静态网站与动态网站的区别
静态网站:web1.0 时代
动态网站:web2.0 时代
静态网站特点:
1、网页内容一经发布到网站服务器,无论是否有用户访问,每个静态页面的内容都是保存在网站服务器上的。也就是说,静态网页是实实在在保存在服务器上的文件,每个网页都是一个独立的文件。
2、静态网页的内容相对稳定,因此容易被搜索引擎检索。
3、 静态网页没有数据库的支持,在网站制作和维护方面工作量较大,因此当网站信息量很大时完全依靠静态网页制作方式比较困难。
4、静态网页的交互性较差,在功能方面有较大的限制。
⑤ 怎么查php代码内存泄露的问题,有没有好的解决办法
没用的代码及时摧毁比什么都有效。
⑥ 关于PHP中 MySQLi扩展库的问题
首先,指针是指向内存的某一地址的。所以第一个语句是修改该指针指向的地址为0,即NULL。
其次,动态分配内存malloc是在内存的堆上为开辟一块内存空间。通常会用一个指针来指向该内存,(否则就没法访问它了)。free是用来释放指针所指向的由malloc开辟的内存的。所以free和malloc是成对使用的。
区别就是:一个只是修改了指针的指向,没有销毁内存里面的数据。另一个是销毁了数据,但是没有修改指针指向。
如果malloc的内存,直接让指针赋值NULL,则导致之后无法释放该内存。进而导致无法再次利用这部分内存,即内存泄露。当然也不能对同一块内存多次free,那样也是错误的。一般来说,先执行free释放内存,再赋值为NULL,以避免失误被再次释放。
⑦ 内存泄漏是怎么一回事
一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显示释放的内存。应用程序一般使用malloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。
对照这个定义看你的程序,只使用malloc分配内存,而没有使用free释放内存,所以出现了内存泄露。
检测内存泄露的方法可以参考以下两篇文章:
1、浅谈内存泄漏(二),http://www.vczx.com/article/show.php?id=68
2、一个跨平台的 C++ 内存泄漏检测器,http://www-900.ibm.com/developerWorks/cn/linux/l-mleak2/index.shtml.htm
⑧ swoole 执行过程 内存升高什么原因
swoole与golang相比有哪些优势
nodejs有个巨大的问题,就是 JavaScript不是特别适合软件工程。 你们难道忘记了JavaScript的属性和原型链嘛? 每个对象随便点一下就添加了一个属性。 这种哲学会导致内存泄露(或者对象遗忘)非常常见,而且非常容易出现。
phpswoole只能运行在php-cli环境吗
一直想写点Swoole的东西,毕竟它重新定义了php,却一直不知道怎么下手写Swoole涉及的知识点非常多,互为表里,每次想写都发现根本理不出一个头绪Swoole是一个php的扩展,它的核心目的就是解决php在实现server服务中可能遇到的一系列问题,这些问...
Swoole比Node.js有哪些优势?有哪些知名的Swoole案例
nodejs有个巨大的问题,就是 JavaScript不是特别适合软件工程。 你们难道忘记了JavaScript的属性和原型链嘛? 每个对象随便点一下就添加了一个属性。 这种哲学会导致内存泄露(或者对象遗忘)非常常见,而且非常容易出现。
swoole服务层代码怎么写
swoole-1.7.7 发布,内置Http服务器性能是Node.js的12倍 PHP的异步并发扩展swoole发布了 1.7.7 版本,此版本主要有: 增加对cygwin环境的支持 增加单次定时器的after接口 onClose事件调整为在close前触发 增加内置Http服务器 修复目前已知的所有...
⑨ PHP里面的include是什么意思连接数据库的时候才用吗后面括号里面的以.php为结尾的文件
$usernc是获取到的用户输入信息($_POST['usernc']),trim()去除字符串首尾的无意义的字符(空格、制表符(就是键盘上的Tab键)、换行符" "(unix及类unix系统的换行符)、回车符" "(又称软换行符,Mac OS X的换行符))。(另外说一下,windows的换行符是" ",也支持" ",但不支持单独的" ")
另外,少用双引号,单引号更快。
双引号支持在字符串中嵌入变量,也支持更多的字符转义("
","
"之类的必须用双引号)。
例如:
<?php
$b='b';
$str="a{$b}c";//相当于$str='a'.$b.'c';但双引号更慢
?>
单引号仅支持很少的转义序列。事实上,它只支持
'''//这是一个单引号字符,相当于"'"
和
'\'//这是一个反斜线
不过,单引号的速度要快得多。
include可以引入一个PHP文件或HTML文件。
如果引入php文件,那么php会先执行被include的文件中的代码,再执行后面的代码。
如果引入html文件,那么php会直接输出这个文件。
在本例中,连接数据库的代码被放在了conn文件夹下的conn.php中。
所以,在这里包含此文件,就可以连接到数据库。
参见PHP手册:include 和 include_once:
http://php.net/manual/zh/function.include.php
http://php.net/manual/zh/function.include-once.php
举个例子:
inc.php
<?php
echo'a';
?>
b.php
<?php
echo'm';
//include允许相对路径与绝对路径,这里是相对路径
//PHP手册推荐在使用include和require时不使用括号
//因为它们是语法结构(就像if,echo之类的),而不是函数
include'inc.php';
echo'n';
?>
你运行b.php,将会输出:
man
加不加_once都可以,不过建议你不要加,这样运行起来会很慢(慢了好几倍)。
include_once主要是为了防止某些函数被重复定义(多次包含)而报错。
这应该用合理的代码规划来避免,而不是使用_once后缀。
虽然性能问题在小程序中不会得到太大体现,但是在一些复杂的项目中,差劲的代码导致的性能问题一定会让你抓狂。
你结合microtime()函数来测试一下,就可以看出来了。
代码如下:
<?php
//获取代码运行的时间
$t=microtime(TRUE);
//这里放上你要测试的代码
//输出运行时间,代码以毫秒为单位
//直接echo很可能会输出为科学计数法,看起来不直观
printf('%f',microtime(TRUE)-$t);
unset($t);//变量用完就注销是个好习惯
?>
另外,如果文件不存在,include会产生警告。
还有一个函数require,与include类似,不过如果文件不存在会产生错误。require比include快一些,因为include有返回值,而require没有。同样,最好不要使用require_once。
参见PHP手册:require 和 require_once:
http://php.net/manual/zh/function.require.php
http://php.net/manual/zh/function.require-once.php
另外,我建议您不要再看这本书了,这本书的代码就好像是一个初学者写的一样,根本不符合规范,而且会有很大的性能问题。
例如:
(1)数组键名没有加上引号。php会首先查找是否存在以这个键名为名称的常量。如果存在,这段代码就很可能会出问题。如果不存在,php没有办法,只能返回这个字符串。在这查找的过程中,就会造成相当大的性能损失。
(2)大量使用双引号,而且还没有正确利用双引号的特性。
(3)没有过滤用户输入,存在SQL注入漏洞。应该把单引号转义。
应该改为:
//适用于大多数数据库,不适用于Sybase
$usernc=addslashes(trim($_POST['usernc']));
//或者
$usernc=mysql_real_escape_string(trim($_POST['usernc']));//仅适用于MySQL
(4)既然有了$_POST['usernc'],为什么还要再用$usernc呢?难道就为了少输几个字符?浪费服务器内存资源。服务器内存资源是非常宝贵的,不应该这样浪费。每执行一次PHP程序都会创建一个新的操作系统线程,并分配2MB的配套内存。使用不当,可能会造成内存泄露(Out of Memory)!如果是在大型网站上,更应注意此类问题。
(5)既然只是判断一条数据是否存在(用户名是否存在),就应该在SQL语句的末尾加上
LIMIT1
否则,会严重影响MySQL性能。不加的话,MySQL找到一条数据后,还会继续查找符合条件的数据(即使并不存在)。如果这个数据表的数据量非常大,那浪费的时间是相当恐怖的!
而加上后,MySQL 搜索到一条数据后就会停止,不会浪费时间。
(6)依赖JavaScript中的history.back()是不对的。如果用户没有保存历史记录(一些浏览器有无痕浏览模式,例如Firefox,Chrome等),或者用户刚好将历史记录清除了,这条语句就会失效。最好的办法是新建一个session变量,例如$_SESSION['history'],将历史记录保存在里面就可以了。再说本例中,程序是应该知道应该跳转到哪个页面的(不是有getuserinfo.php吗?)。
应该直接302重定向。可以使用下面的代码:
//把“网址”替换为相应的URL就行了
//注意:是从http://一直到URL最后
header('Location:网址');
注意,这之前不能有输出。或者,在程序最开始的php文件上方加上:
ob_start();
这样就可以了。
以上这些问题都是应该避免的。
⑩ 如何从log中看到内存泄露问题点
(一) 生成.hprof文件
生成.hprof 文件的方法有很多,而且Android 的不同版本中生成.hprof 的方式也稍有差别,我使用的版本的是2.1,各个版本中生成.prof 文件的方法请参考: http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/heapprofiling.html;hb=HEAD。
1. 打开eclipse 并切换到DDMS 透视图,同时确认Devices、Heap 和logcat 视图已经打开了;
2. 将手机设备链接到电脑,并确保使用“USB 调试”模式链接,而不是“Mass Storage“模式;
3. 链接成功后在Devices 视图中就会看到设备的序列号,和设备中正在运行的部分进程;
4. 点击选中想要分析的应用的进程,在Devices 视图上方的一行图标按钮中,同时选中“Update Heap”和“Dump HPROF file”两个按钮;
5. 这是DDMS 工具将会自动生成当前选中进程的.hprof 文件,并将其进行转换后存放在sdcard 当中,如果你已经安装了MAT 插件,那么此时MAT 将会自动被启用,并开始对.hprof 文件进行分析;
注意:第4 步和第5 步能够正常使用前提是我们需要有sdcard,并且当前进程有向sdcard中写入的权限(WRITE_EXTERNAL_STORAGE),否则.hprof 文件不会被生成,
在logcat 中会显示诸如 ERROR/dalvikvm(8574): hprof: can't open /sdcard/com.xxx.hprof-hptemp: Permission denied.的信息。
如果我们没有sdcard,或者当前进程没有向sdcard 写入的权限(如system_process), 那我们可以这样做:
6. 在当前程序中,例如framework 中某些代码中,可以使用android.os.Debug 中的: public static void mpHprofData(String fileName) throws IOException 方法,手动的指定.hprof 文件的生成位置。
例如: xxxButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { android.os.Debug.mpHprofData("/data/temp/myapp.hprof"); ... ... } }
上述代码意图是希望在xxxButton 被点击的时候开始抓取内存使用信息,并保存在我们指定的位置:/data/temp/myapp.hprof,这样就没有权限的限制了,而且也无须用sdcard。
但要保证/data/temp 目录是存在的。这个路径可以自己定义,当然也可以写成sdcard 当中的某个路径。
(二) 使用MAT导入.hprof文件
1. 如果是eclipse 自动生成的.hprof 文件,可以使用MAT 插件直接打开(可能是比较新的ADT才支持);
2. 如果eclipse 自动生成的.hprof 文件不能被MAT 直接打开, 或者是使用android.os.Debug.mpHprofData()方法手动生成的.hprof 文件,则需要将.hprof 文件进行转换,转换的方法: 例如我将.hprof 文件拷贝到PC 上的/ANDROID_SDK/tools 目录下,并输入命令hprofconv xxx.hprof yyy.hprof,其中xxx.hprof 为原始文件,yyy.hprof 为转换过后的文件。转换过后的文件自动放在/ANDROID_SDK/tools 目录下。OK,到此为止,.hprof 文件处理完毕,可以用来分析内存泄露情况了。
3. 在Eclipse 中点击Windows->Open Perspective->Other->Memory Analyzer,或者打Memory Analyzer Tool 的RCP。在MAT 中点击File->Open File,浏览并导入刚刚转换而得到的.hprof文件。
(三) 使用MAT的视图工具分析内存
导入.hprof 文件以后,MAT 会自动解析并生成报告,点击Dominator Tree,并按Package分组,选择自己所定义的Package 类点右键,在弹出菜单中选择List objects->With incoming references。这时会列出所有可疑类,右键点击某一项,并选择Path to GC Roots -> exclude weak/soft references,会进一步筛选出跟程序相关的所有有内存泄露的类。据此,可以追踪到代码中的某一个产生泄露的类。
MAT 的界面如下图所示。
具体的分析方法在此不做说明了,因为在MAT 的官方网站和客户端的帮助文档中有十分详尽的介绍。 了解MAT 中各个视图的作用很重要,例如www.eclipse.org/mat/about/screenshots.php 中介绍的。
总之使用MAT 分析内存查找内存泄漏的根本思路,就是找到哪个类的对象的引用没有被释放,找到没有被释放的原因,也就可以很容易定位代码中的哪些片段的逻辑有问题了。
另外在测试过程首先需要分析怎么样操作一个应用会产生内存泄露然后在不断的操作中抓取该进程产生的hhprof文件使用MAT工具分析。目前自己的了解查看内存分析内存泄露还有以下几种方法:
1.使用top命令查看某个进程的内存。例如创建一个脚本文件music.sh 该文件内容为指定程序每隔一秒钟输出某个进程的内存使用情况,在此具体实现如下 :
#!/bin/bash
while true; do
adb shell procrank | grep "com.android.music"
sleep 1
done
并且配合使用procank工具可以查看music进程每一秒钟内存使用情况。
2.另外使用top命令也可是查看内存具体为:
adb shell top -m 10.(查看使用资源最多的10个进程)
adb shell top|grep com.android.music(查看music进程的内存)
3.free命令
free
1.作用free命令用来显示内存的使用情况,使用权限是所有用户。
2.格式free [-b|-k|-m] [-o] [-s delay] [-t] [-V]
3.主要参数-b -k -m:分别以字节(KB、MB)为单位显示内存使用情况。
-s delay:显示每隔多少秒数来显示一次内存使用情况。
-t:显示内存总和列。
-o:不显示缓冲区调节列。
4.应用实例free命令是用来查看内存使用情况的主要命令。和top命令相比,它的优点是使用简单,并且只占用很少的系统资源。通过-S参数可以使用free命令不间断地监视有多少内存在使用,这样可以把它当作一个方便实时监控器。
#free -b -s5使用这个命令后终端会连续不断地报告内存使用情况(以字节为单位),每5秒更新一次。