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

时间:2017-05-09 16:46:35

标签: filesystems numa

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

例如,如果 4个NUMA 节点及其本地内存,则访问a.txt的节点列表可能为a.txt

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

  1. 查找低级0 0 0 1 1 0 2 2 2 0 3 3 3 3 3文件操作功能(如ramfsread
  2. 获取正在执行该功能的线程的节点号
  3. 将该节点号存储到某处(如a.txt的write或其他)
  4. 但我没能找到ramfs的这种低级功能,我无法继续。

    有没有办法实现这个目标?

1 个答案:

答案 0 :(得分: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在他的presentationssite中列出了更多工具,两者都是经典的(包含VFS的小列表)https://www.slideshare.net/brendangregg/linux-systems-performance-2016#slide=7;和bcc / 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中一样):

  
      
  1. 找到低级ramfs文件操作函数(如读或写)
  2.   

不幸的是,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_操作。您将只能跟踪它们。

  
      
  1. 获取正在执行该功能的线程的节点号
  2.   

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

有高级跟踪框架时更容易 - 记录调度程序的所有操作 - 何时以及计划到每个CPU的pid(例如struct task_struct中的kernelshark或者{{1}的perf / stap / lttng跟踪函数 - sched_可能包含参数;甚至ftrace都允许你在单个过滤器中组合两个跟踪,包括io和sched。)

您将有一些后处理来排序输出并组合信息,但这应该执行任务

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

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