在Linux上,access()比stat()更快吗?

编程入门 行业动态 更新时间:2024-10-25 12:20:36
本文介绍了在Linux上,access()比stat()更快吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 假设access()只是stat()的一个包装,但是我一直在用google搜索,并有发现一些轶事有关更便宜的访问电话替换统计电话。假设你只是想检查一个文件是否存在,访问速度更快?它是完全不同的文件系统?

解决方案

理论

在内核的低层, access()和 stat()调用都在执行查找操作:它们将文件名映射到 dentry cache 中的一个条目和 inode (它是实际的内核结构, inode )。查找是慢操作,因为您需要为路径的每个部分执行它,即对于 / usr / bin / cat ,您需要查找 usr , bin ,然后 cat ,它可能需要从磁盘读取 - 这就是为什么inode并将内存缓存在内存中。 $ b 这个调用的主要区别在于 stat()执行 inode code>结构为 stat 结构,而 access()会做一个简单的检查,但那个时间是与 lookup 时间比较小。

真正的性能增益可以通过 $ c> faccessat()和 fstatat(),允许 open()目录一次,只是比较:

struct stat s; stat(/ usr / bin / cat,& s); //查找usr,bin和cat = 3 stat(/ usr / bin / less,& s); //查找usr,bin和less = 3 int fd = open(/ usr / bin); // lookups usr,bin = 2 fstatat(fd,cat,& s); // lookups cat = 1 fstatat(fd,less,& s); // $ lookup less = 1

实验

我写了一个调用 stat()和 access()的小python脚本:

import os,time,random files = ['gzexe','catchsegv','gtroff','gencat','neqn', 'gzip','getent','sdiff','zcat','iconv','not_exists','ldd','unxz','zcmp','locale','xz (1,80000)中的i, 访问= lambda fn:os.access(fn,os.R_OK) :尝试: random.choice((access,os.stat))(/ usr / bin /+ random.choice(files))除外: continue

使用SystemTap跟踪系统来度量在不同操作中花费的时间。 stat()和 access()系统调用都使用 user_path_at_empty()核心函数代表查找操作:

stap -ve'global tm,times,path; probe lookup = kernel.function(user_path_at_empty) {name =lookup; pathname = user_string_quoted($ name); } probe lookup.return = kernel.function(user_path_at_empty)。return {name =lookup; } probe stat = syscall.stat {pathname = filename; } probe stat,syscall.access,lookup {if(pid()== target()&& isinstr(pathname,/ usr / bin)){ tm [name] = local_clock_ns(); }} probe syscall.stat.return,syscall.access.return,lookup.return {if(pid()== target()&& tm [name]){次[名称]< local_clock_ns() - tm [name]; 删除tm [name]; }} '-c'python stat-access.py'

结果如下: pre codeOUNT AVG lookup 80018 1.67 us stat 40106 3.92 us 访问39903 4.27 us

注意我在我的实验中禁用了SELinux,因为它增加了对结果。

I would have assumed that access() was just a wrapper around stat(), but I've been googling around and have found some anecdotes about replacing stat calls with 'cheaper' access calls. Assuming you are only interested in checking if a file exists, is access faster? Does it completely vary by filesystem?

解决方案

Theory

I doubt that.

In lower layers of kernel there is no much difference between access() and stat() calls both are performing lookup operation: they map file name to an entry in dentry cache and to inode (it is actual kernel structure, inode). Lookup is slow operation because you need to perform it for each part of path, i.e. for /usr/bin/cat you will need to lookup usr, bin and then cat and it can require reading from disk -- that is why inodes and dentries are cached in memory.

Major difference between that calls is that stat() performs conversion of inode structure to stat structure, while access() will do a simple check, but that time is small comparing with lookup time.

The real performance gain can be achieved with at-operations like faccessat() and fstatat(), which allow to open() directory once, just compare:

struct stat s; stat("/usr/bin/cat", &s); // lookups usr, bin and cat = 3 stat("/usr/bin/less", &s); // lookups usr, bin and less = 3 int fd = open("/usr/bin"); // lookups usr, bin = 2 fstatat(fd, "cat", &s); // lookups cat = 1 fstatat(fd, "less", &s); // lookups less = 1

Experiments

I wrote a small python script which calls stat() and access():

import os, time, random files = ['gzexe', 'catchsegv', 'gtroff', 'gencat', 'neqn', 'gzip', 'getent', 'sdiff', 'zcat', 'iconv', 'not_exists', 'ldd', 'unxz', 'zcmp', 'locale', 'xz', 'zdiff', 'localedef', 'xzcat'] access = lambda fn: os.access(fn, os.R_OK) for i in xrange(1, 80000): try: random.choice((access, os.stat))("/usr/bin/" + random.choice(files)) except: continue

I traced system with SystemTap to measure time spent in different operations. Both stat() and access() system calls use user_path_at_empty() kernel function which represents lookup operation:

stap -ve ' global tm, times, path; probe lookup = kernel.function("user_path_at_empty") { name = "lookup"; pathname = user_string_quoted($name); } probe lookup.return = kernel.function("user_path_at_empty").return { name = "lookup"; } probe stat = syscall.stat { pathname = filename; } probe stat, syscall.access, lookup { if(pid() == target() && isinstr(pathname, "/usr/bin")) { tm[name] = local_clock_ns(); } } probe syscall.stat.return, syscall.access.return, lookup.return { if(pid() == target() && tm[name]) { times[name] <<< local_clock_ns() - tm[name]; delete tm[name]; } } ' -c 'python stat-access.py'

Here are the results:

COUNT AVG lookup 80018 1.67 us stat 40106 3.92 us access 39903 4.27 us

Note that I disabled SELinux in my experiments, as it adds significant influence on the results.

更多推荐

在Linux上,access()比stat()更快吗?

本文发布于:2023-06-01 10:30:21,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/412999.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:更快   Linux   access   stat

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!