在 ramfs 中,如何根据 NUMA 节点跟踪文件访问模式?

Posted

技术标签:

【中文标题】在 ramfs 中,如何根据 NUMA 节点跟踪文件访问模式?【英文标题】:in ramfs, how can i trace file access pattern in terms of NUMA node? 【发布时间】:2017-05-09 16:46:35 【问题描述】:

由于Ramfs 将文件存储到内存中并且该内存绑定到某个NUMA 节点,我认为有一些方法可以跟踪请求文件的nodes(例如a.txt)。

例如,如果有 4 个 NUMA 节点及其本地内存,则访问 a.txt 的节点列表可能是 0 0 0 1 1 0 2 2 2 0 3 3 3 3 3

一种可能的解决方案如下:

    查找低级ramfs文件操作函数(如readwrite) 获取正在执行该函数的线程的节点号 将该节点号存储到某处(例如 a.txt 的 inode 或其他内容)

但是我没有找到ramfs这么低级的功能,无法继续。

有没有办法做到这一点?

【问题讨论】:

什么是 Ramfs?是Linux吗?你的机器是 NUMA 吗(有超过 1 个插槽,每个插槽都有自己的集成内存控制器)? NUMA 放置物理 4KB(或 2MB)页面。有用于 linux 的 libnuma (man7.org/linux/man-pages/man3/numa.3.html),如果来自 Ramfs 的数据是 mmaped,要查找数据在哪里,您可以尝试 numa_move_pages/move_pages (man7.org/linux/man-pages/man2/move_pages.2.html) 在节点中使用 NULL:“节点也可以为 NULL,在这种情况下 move_pages() 不会移动任何页面,而是会在状态数组中返回每个页面当前所在的节点。" 我的问题是:我怎么知道哪个节点需要数据,而不是数据驻留在哪个节点。更具体地说,我想在 Ramfs 中为每个文件(每个 inode)保留日志。日志是 NUMA 节点的列表,并会告诉我们哪些节点访问了该文件。 Bot,请多解释。是Linux(哪个内核版本)?是tmpfs吗?程序如何访问文件/文件(是读取、mmap、写入还是什么)。是你的程序(你能修改它)还是很多不是你的程序?您可以更改什么(补丁+重新编译内核,补丁 ramfs 兼容模块,FUSE;您可以使用 ftrace/stap/dprobe/strace/ltrace 吗?您不能在 inode 中存储太多。(PS 如果是您的任务)当然,告诉我们这门课程是关于什么的,内核编程还是 unix 编程还是什么?) 感谢您的好意,就像我会经常访问***一样。基本上我是研究生院的新生,我研究(未来)大规模非易失性基于内存的文件系统的 NUMA 效应。我想我需要了解一般基于内存的文件系统的文件访问模式(就 NUMA 节点而言)。所以我选择了 Ramfs(因为我不得不假设没有磁盘设备)。我的 linux 版本是 4.7.4(如果需要,我可以使用其他内核版本启动)。这只是关于 Ramfs 而不是 Tmpfs,所以我什至不需要考虑磁盘。 使用简单的读写。我想我可以尝试修补 ramfs 兼容的模块,但我对 FUSE 一无所知。我尝试使用 ftrace 来跟踪 ramfs 写入,但由于某种原因,没有看到“ramfs.write”(因为我在 ftrace 方面很差)。 【参考方案1】:

不是一个完整的解决方案,而是一些想法。

一些fs将文件存储到内存中,并且该内存绑定到某些NUMA节点,..我认为存在一些方法可以跟踪请求文件的节点

在现代 Linux(4.x 内核)中有许多方法可以跟踪文件访问(一些基本类型;open/read/write/mmap;但不是 mmaped 区域的使用)。对于单个 pid,您可以使用strace 系统调用跟踪器(或ltrace -S,它还可以捕获库调用)。对于许多 pid(完整系统跟踪),您可以尝试 sysdig

也有可以使用的内核内(和树外内核模式)跟踪框架。就像基于 perf + probe / ftrace (trace-cmd) 的东西,或者更高级的跟踪解决方案,如 stap/dtrace/lttng,并定义并启用了相应的跟踪点。 Gregg 在他的presentations 和site 中列出了更多工具,都是经典的(VFS 的小列表)https://www.slideshare.net/brendangregg/linux-systems-performance-2016#slide=7;和基于密件抄送/eBPF:https://www.slideshare.net/brendangregg/designing-tracing-tools-67693476#slide=3。

大多数系统范围的工具已经有很好的框架来执行时间戳和进程记帐,并将大量跟踪数据从内核模式下载到一些日志/转储文件中。其中一些(stap/dtrace/bcc + 探针)允许您编写小代码片段以在调用跟踪函数时执行。

Gregg 工具的示例是“iosnoop”(它位于debugfs & /sys/kernel/debug/tracing 之上,即ftrace 和trace-cmd)。它显示了每个真实读/写操作的延迟(进入真实磁盘;不能访问页面缓存中已读取的数据,就像在 ramfs 中一样):

文档http://www.brendangregg.com/blog/2014-07-16/iosnoop-for-linux.html, src https://github.com/brendangregg/perf-tools/blob/master/iosnoop (几乎可以在任何地方使用nop ftraceing 两个事件:events/block/block_rq_insert 和 events/block/block_rq_complete) (通过将 iosnoop src 中的 cat trace 行替换为 cat trace | tee -a ~/iotrace.$$.dump 并查看它来添加原始跟踪的调试保存)
    查找低级ramfs文件操作函数(如读或写)

不幸的是,ramfs 是太基本的 FS,无法实现任何有趣的东西。 ramfs有地址空间操作和文件操作:

http://elixir.free-electrons.com/linux/v4.7.4/source/fs/ramfs/inode.c#L46

static const struct address_space_operations ramfs_aops = 
    .readpage   = simple_readpage,
    .write_begin    = simple_write_begin,
    .write_end  = simple_write_end,
    .set_page_dirty = __set_page_dirty_no_writeback,
;

http://elixir.free-electrons.com/linux/v4.7.4/source/fs/ramfs/file-mmu.c#L33

const struct file_operations ramfs_file_operations = 
    .read_iter  = generic_file_read_iter,
    .write_iter = generic_file_write_iter,
    .mmap       = generic_file_mmap,
    .fsync      = noop_fsync,
    .splice_read    = generic_file_splice_read,
    .splice_write   = iter_file_splice_write,
    .llseek     = generic_file_llseek,
;

simple_ / generic_file_ 操作在 libfs/ 或 mm/ 中定义(对于 elixir/lxr 网站,您只需单击函数即可找到其定义和用法)http://elixir.free-electrons.com/linux/v4.7.4/source/fs/libfs.c#L409,它们还用于更多linux FS 实现,因此无条件跟踪它们可能是不安全的。

你可以尝试重写 ramfs 的实现;只需在具有不同名称的变体中定义类似的 simple_ / generic_file_ 操作即可。您将只能追踪它们。

    获取正在执行该函数的线程的节点号

我认为,还有另一种方法。检测到访问时获取进程/线程的pid/tid;但不要做任何事情来查找 NUMA 节点(您可能会修改 ramfs 实现并添加您自己的 aops 变体,读取 current ptr 并从 struct task_struct 找到 NUMA 节点;但是在哪里写它?)。

当有高级跟踪框架时更容易 - 是记录调度程序的所有操作 - 何时以及为每个 CPU 计划了哪个 pid(如在kernelshark 或在sched_ 函数的 perf/stap/lttng 跟踪中 - sched_switch 可能带有参数;甚至 ftrace 也允许您在单个过滤器中组合两个跟踪,io 和 sched)。

您将有一些后处理来对输出进行排序和组合信息,但这应该可以完成任务

    将该节点号存储到某处(例如 a.txt 的 inode 或其他内容)

不要重新发明***,使用跟踪框架。

【讨论】:

对于真实磁盘也可以使用 blktrace:cse.unsw.edu.au/~aaronc/iosched/doc/blktrace.html(每 CPU 跟踪到转储文件中,可以使用 blkparse 查看)

以上是关于在 ramfs 中,如何根据 NUMA 节点跟踪文件访问模式?的主要内容,如果未能解决你的问题,请参考以下文章

如何在特定的 NUMA 内存节点上实例化 C++ 对象?

如何计算对远程 NUMA 内存节点的内存访问?

在 linux(CentOS)/多处理器设置中,如何将 CPU 内核分配给 NUMA 节点?

如何将所有内存分配限制到一个 NUMA 节点

如何在 Windows 上将 c++11 线程关联设置为 NUMA 节点?

如何在 NUMA 机器上的不同节点上分配数组的一部分?