linux 文件系统 && inode cache
2009-10-10 3:52 pm最近在跟踪apc.stat参数的效果的时候遇到很多问题,为了一弄究竟,一直跟踪下来了,先上一个测试报告,
对zend framework空框架测试,开启apc或者eaccelerator这样的opcode缓存会提升很大的性能(废话),这个并不是我们要研究的,空的zend框架大概需要include 38个文件左右,试过将38个文件中大部分合并成一个文件,再测试,发现性能提升近50%,这个是非常诱人的,不管有没有opcode的缓存是一样的。apc.stat参数来控制每次是否检测涉及到的文件修改过没有,但是在仍然不是很理想,如对include_once和require_once是无效的,也对zend框架的require_once做了优化(官方提供的),改成autoload形式,效果也不明显,(修改文件缓存不更新,但是删除文件会报错),如果不使用zend框架来测试,写几个php文件包含apc.stat是完全没问题的,但是发现效果并不明显。
所以我认为在opcode缓存的情况下,每次检查文件是否修改过的操作并不是瓶颈,用strace(freebsd 下是ktrace)跟踪即使fstat操作。为了证实这点,也顺便对linux的文件系统做一个简单的分析。
引用一些linux文件系统的基础知识:原文地址: http://www.ibm.com/developerworks/linux/library/l-linux-filesystem/?S_TACT=105AGX52&S_CMP=cn-a-l

这个图很好的概述了linux文件系统,
Linux 以一组通用对象的角度看待所有文件系统。这些对象是超级块(superblock)、inode、dentry 和文件。超级块在每个文件系统的根上,超级块描述和维护文件系统的状态。文件系统中管理的每个对象(文件或目录)在 Linux 中表示为一个 inode。inode 包含管理文件系统中的对象所需的所有元数据(包括可以在对象上执行的操作)。另一组结构称为 dentry,它们用来实现名称和 inode 之间的映射,有一个目录缓存用来保存最近使用的 dentry。dentry 还维护目录和文件之间的关系,从而支持在文件系统中移动。
从图中也可以看出,inode和dentry(directory cache)都有cache,会将最近使用到的文件更新inode等缓存,缓存是保存在内存中的,所以读取缓存中的inode是没有io操作的,也就是非常高效的,下面附上linux 内核对inode结构的部分定义,/kernel/include/linux/fs.h中716行:
716 struct inode {
717 struct hlist_node i_hash;
718 struct list_head i_list;
719 struct list_head i_sb_list;
720 struct list_head i_dentry;
721 unsigned long i_ino;
722 atomic_t i_count;
723 unsigned int i_nlink;
727 u64 i_version;
728 loff_t i_size;
729 #ifdef __NEED_I_SIZE_ORDERED
730 seqcount_t i_size_seqcount;
731 #endif
732 struct timespec i_atime;
733 struct timespec i_mtime;
734 struct timespec i_ctime;
742 const struct inode_operations *i_op;
743 const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
}
能看出包括mtime和link等的元信息都在里面,所以要检查文件是否修改只需查看inode就足够了,inode 和目录缓存分别保存最近使用的 inode 和 dentry,且对于 inode 缓存中的每个 inode,在目录缓存中都有一个对应的 dentry。
其实 inode_operations 和 file_operations。这些结构表示可以在这个 inode 上执行的操作。inode_operations 定义直接在 inode 上执行的操作,而 file_operations 定义与文件和目录相关的方法(标准系统调用)。
dentry和super_block的结构在上面的文件中也有,不打出来了。
总结:从以上的分析来看,有理由相信系统在判断一个文件是否修改过的操作上是花销是极小的,不会成为opcode检查中的瓶颈。 接下来继续往下跟踪,说明瓶颈可能出现在opcode的compile(include的开销)。