知识【7.2 进程写文件时,进程发生了崩溃,已写入的数据会丢失吗? | 小林coding】
固态硬盘跟机械硬盘
Direct I/O(Direct Input/Output)
Direct I/O(Direct Input/Output)是一种数据传输方式,它允许应用程序直接在应用程序地址空间和设备之间进行数据传输,绕过操作系统的文件系统缓存。
在传统的 I/O 操作中,数据通常首先被读取到操作系统的文件系统缓存中,然后再从缓存中传输到应用程序中,或者反之。这种方式可以提高读写操作的性能,因为读取和写入可以在内存中进行,而不必每次都涉及到磁盘的物理访问。然而,对于某些应用场景,绕过文件系统缓存进行直接 I/O 操作可能更为适合。
Direct I/O 的主要特点包括:
-
- 绕过文件系统缓存:数据直接在应用程序地址空间和设备之间传输,不经过操作系统的文件系统缓存。这意味着数据读取和写入会直接操作磁盘或其他设备,而不会发生额外的数据复制。
- 可控内存缓冲区:应用程序可以使用自己的内存缓冲区来进行数据读取和写入。这允许应用程序更精确地控制数据的位置和大小,以满足特定的需求。
- 适用性较窄:Direct I/O 通常适用于特定的应用场景,如大型数据库系统、高性能计算等。它可以提供更低的读写延迟和更高的吞吐量,但需要应用程序自己管理数据的一致性和并发访问。
需要注意的是,Direct I/O 也有一些限制和注意事项:
-
- 对于某些操作系统和文件系统,Direct I/O 可能需要特定的系统调用或标志来启用。
- Direct I/O 需要应用程序自行处理数据的一致性和并发访问问题,因此需要更加谨慎地编写代码。
- 在某些情况下,操作系统的文件系统缓存可能会提供更好的性能,因此在选择使用 Direct I/O 时需要仔细权衡。
总而言之,Direct I/O 是一种通过绕过文件系统缓存实现应用程序和设备之间直接数据传输的方式,适用于特定的高性能或特定需求的应用场景。
perftrace抓取的sync接口调用耗时情况,可以发现极端情况耗时还是很高
原因如下图:
SYNC接口耗时高的原因很可能是一次sync数据量的问题(一次sync是全刷,可能把别人的数据也刷了)所以调整到50MB再观察耗时相对ok。
磁盘碎片(持续使用不可避免)
1. 首先使用上要保证写入数据前空间量足(下电前删除不用的大文件)
!!!希望大家每天在bag包拷贝、上传等操作结束后, 车辆下电前, 用脚本删除(已经支持同时删除所有域控) 自己所关心的目录的bag包;
目前发现存在很多bag包 "使用" 完不删除的情况,持续写入数据量累积会造成:1. 录包代码同时循环写入跟删除包 2. 磁盘占用空间余量到达阈值;
若基于如上两种情况, 继续持续写入数据会导致磁盘碎片增多,影响磁盘持续写入性能,成为影响录包稳定性的一个重要因素。
2. 碎片监控与整理策略(比如上电前10分钟开启磁盘整理)
3. 文件系统优化---磁盘格式化:mount -t ext4 -oremount,writeback,journal_async_commit,noatime,nodiratime,nobarrier /dev/nvme0n1p1 ext4 反复断电可能容易导致文件系统损坏;磁盘接近打满会导致磁盘碎片率高
通过预分配磁盘空间(文件系统ext4已经支持预分配)的形式这个问题
// pre-apply for disk space for each task
long pre_allocate_count = 0;
if(hostname_ == "rosmaster") {
pre_allocate_count = 2.5 * 1024 * 1024 * 1024 / static_cast<long>(pre_allocate_pice_size_);
}
else {
pre_allocate_count = 4 * 1024 * 1024 * 1024 / static_cast<long>(pre_allocate_pice_size_);
}
int fd;
double now_timestamp_start = mogo::TimeHelper::to_sec(mogo::Time::now());
for (int i = 0; i < pre_allocate_count; ++i) {
fd = open(absoluteBagPath.string().c_str(), O_CREAT | O_RDWR, 0777);
if (fd == -1) {
MOGO_ERROR_STREAM("open " << absoluteBagPath.string() << " error");
break;
}
if(fallocate(fd, 0, 0, pre_allocate_pice_size_) != 0) {
MOGO_ERROR_STREAM("fallocate disk space " << pre_allocate_pice_size_ << " error");
break;
}
}
double now_timestamp_end = mogo::TimeHelper::to_sec(mogo::Time::now());
MOGO_INFO_STREAM("pre allocate use timestamp: " << now_timestamp_end - now_timestamp_start);
close(fd);