我有一个Linux应用程序,并行读取150-200个文件(4-10GB).每个文件依次以小的,可变大小的块读取,每个块通常小于2K.
我目前需要从文件集中保持超过200 MB/s的读取速率.磁盘处理这个很好.预计需要超过1 GB/s(目前不在磁盘范围内).
我们已经实现了两个不同的读取系统,它们都大量使用posix_advise:首先是mmaped读取,其中我们映射整个数据集并按需读取.第二个是基于read()/ seek()的系统.
两者都运行良好但仅适用于中等情况,该read()方法更好地管理我们的整体文件缓存并且可以很好地处理100 GB的文件,但是速率受限,mmap能够预先缓存数据使得持续数据速率超过200MB/s易于维护,但无法处理较大的总数据集大小.
所以我的问题来自于:
答:可以在Linux read()上posix_advise调用之外进一步优化类型文件i/o ,或者调整磁盘调度程序,VMM和posix_advise调用是否符合我们的预期?
B:有没有系统的方法让mmap更好地处理非常大的映射数据?
Mmap-vs-reading-blocks 与我正在工作的问题类似,并且提供了一个关于这个问题的良好起点,以及mmap-vs-read中的讨论.
说得客气一点,我有一个小内存问题,并且没有工具和想法来隔离原因.
我有一个高度多线程(pthreads)的C/C++程序,在4.4.4之后和4.7.1之前的GCC优化编译下开发了堆栈粉碎问题.
症状是在创建其中一个线程期间,我获得了完整的堆栈粉碎,而不仅仅是%RIP,但是所有父帧和大多数寄存器都是0x00或其他非感知地址.哪个线程导致问题似乎是随机的,但是通过日志消息判断它似乎被隔离到相同的Hunk代码,并且似乎在创建新线程时处于半可重复的点.
这使得很难将有问题的代码陷入和隔离,而不是单个编译单元可能数千行,因为在违规文件中print()在尝试缩小活动部分时证明是不可靠的. .
导致最终破坏堆栈的线程的线程创建是:
extern "C"
{
static ThreadReturnVal ThreadAPI WriterThread(void *act)
{
Recorder *rec = reinterpret_cast (act);
xuint64 writebytes;
LoggerHandle m_logger = XXGetLogger("WriterThread");
if (SetThreadAffinity(rec->m_cpu_mask))
{ ... }
SetThreadPrio((xint32)rec->m_thread_priority);
while (true)
{
... poll a ring buffer ... Hard Spin 100% use on a single core, this is that sort of crazy code.
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试过调试版本,但症状只存在于优化版本中,-O2或更好.我已经尝试过Valgrind/memcheck和DRD,但是在堆栈被吹走之前都没有找到任何问题(并且需要大约12小时来达到失败)
使用-O2 -Wstack-protector进行编译时没有看到任何错误,但使用-fstack-protector-all进行构建确实可以保护我免受错误的影响,但不会发出任何错误.
电围栏也陷阱,但只有在堆栈消失后才会陷阱.
问题:还有哪些其他工具或技术可用于缩小违规部分?
非常感谢, - 比尔
我知道这已经过了很多次,但是我今天遇到了一个案例,震惊了我对指针数学/数组索引的理解.
正如我总是理解的那样,&mybuff [10]和(&mybuff + 10)是重新记忆相同记忆的方法.
但是我花了一个上午打架的案例:
memcpy(&mybuff+10,&in,8);
Run Code Online (Sandbox Code Playgroud)
当使用优化编译时,溢出缓冲区,并且在编译用于调试时工作正常.
而在同一时间,
memcpy(&mybuff[10],&in,8);
Run Code Online (Sandbox Code Playgroud)
在这两种情况下工作得很好.
非常感谢任何想法或指针.