- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个嵌入式 ARM Linux 机器,其 RAM 量有限(512MB)且没有交换空间,我需要在其上创建然后操作一个相当大的文件(~200MB)。将整个文件加载到 RAM 中,修改 RAM 中的内容,然后再次将其写回,有时会调用 OOM-killer,我想避免这种情况。
我解决这个问题的想法是使用 mmap()
将此文件映射到我的进程的虚拟地址空间;这样,对映射内存区域的读取和写入将转到本地闪存文件系统,并且可以避免 OOM 杀手,因为如果内存不足,Linux 可以只刷新一些 mmap() 的内存页回到磁盘以释放一些 RAM。 (这可能会使我的程序变慢,但对于这个用例来说慢是可以的)
但是,即使使用 mmap()
调用,我仍然偶尔看到进程在执行上述操作时被 OOM-killer 杀死。
我的问题是,我是否对 Linux 在同时存在大型 mmap() 和有限 RAM 的情况下的行为过于乐观? (即 mmap()-ing 一个 200MB 的文件,然后读/写到 mmap() 的内存仍然需要 200MB 的可用 RAM 才能可靠地完成?)或者 mmap() 是否应该足够聪明以分页出 mmap 的页面当内存不足时,但我在使用它时做错了什么?
FWIW我做映射的代码在这里:
void FixedSizeDataBuffer :: TryMapToFile(const std::string & filePath, bool createIfNotPresent, bool autoDelete)
{
const int fd = open(filePath.c_str(), (createIfNotPresent?(O_CREAT|O_EXCL|O_RDWR):O_RDONLY)|O_CLOEXEC, S_IRUSR|(createIfNotPresent?S_IWUSR:0));
if (fd >= 0)
{
if ((autoDelete == false)||(unlink(filePath.c_str()) == 0)) // so the file will automatically go away when we're done with it, even if we crash
{
const int fallocRet = createIfNotPresent ? posix_fallocate(fd, 0, _numBytes) : 0;
if (fallocRet == 0)
{
void * mappedArea = mmap(NULL, _numBytes, PROT_READ|(createIfNotPresent?PROT_WRITE:0), MAP_SHARED, fd, 0);
if (mappedArea)
{
printf("FixedSizeDataBuffer %p: Using backing-store file [%s] for %zu bytes of data\n", this, filePath.c_str(), _numBytes);
_buffer = (uint8_t *) mappedArea;
_isMappedToFile = true;
}
else printf("FixedSizeDataBuffer %p: Unable to mmap backing-store file [%s] to %zu bytes (%s)\n", this, filePath.c_str(), _numBytes, strerror(errno));
}
else printf("FixedSizeDataBuffer %p: Unable to pad backing-store file [%s] out to %zu bytes (%s)\n", this, filePath.c_str(), _numBytes, strerror(fallocRet));
}
else printf("FixedSizeDataBuffer %p: Unable to unlink backing-store file [%s] (%s)\n", this, filePath.c_str(), strerror(errno));
close(fd); // no need to hold this anymore AFAIK, the memory-mapping itself will keep the backing store around
}
else printf("FixedSizeDataBuffer %p: Unable to create backing-store file [%s] (%s)\n", this, filePath.c_str(), strerror(errno));
}
mmap()
会更好可以完成这项工作(或者如果不能,我至少想了解为什么不这样做)。
最佳答案
经过大量进一步的实验,我确定 OOM 杀手正在访问我并不是因为系统内存不足,而是因为内存偶尔会变得非常碎片化,以至于内核无法找到一组足够大的物理连续内存页面以满足其迫切需要。当这种情况发生时,内核会调用 OOM-killer 来释放一些 RAM 以避免内核 panic ,这对内核来说一切都很好,但当它杀死用户依赖的进程时就不那么好了完成工作。 :/
在尝试并未能找到说服 Linux 不这样做的方法之后(我认为启用交换分区可以避免 OOM 杀手,但在这些特定机器上这样做对我来说不是一个选择),我想出了一个 hack解决办法;我在我的程序中添加了一些代码,它会定期检查 Linux 内核报告的内存碎片量,如果内存碎片看起来太严重,则先发制人地命令进行内存碎片整理,以便 OOM 杀手(希望如此)没有必要。如果内存碎片整理过程似乎没有任何改善,那么在连续尝试 20 次之后,我们还会删除 VM 页面缓存,以此作为释放连续物理 RAM 的一种方式。这一切都非常丑陋,但并不像凌晨 3 点接到一个想知道他们的服务器程序为什么崩溃的用户的电话那么丑陋。 :/
变通方案实现的要点如下;请注意 DefragTick(Milliseconds)
预计会被定期调用(最好每秒调用一次)。
// Returns how safe we are from the fragmentation-based-OOM-killer visits.
// Returns -1 if we can't read the data for some reason.
static int GetFragmentationSafetyLevel()
{
int ret = -1;
FILE * fpIn = fopen("/sys/kernel/debug/extfrag/extfrag_index", "r");
if (fpIn)
{
char buf[512];
while(fgets(buf, sizeof(buf), fpIn))
{
const char * dma = (strncmp(buf, "Node 0, zone", 12) == 0) ? strstr(buf+12, "DMA") : NULL;
if (dma)
{
// dma= e.g.: "DMA -1.000 -1.000 -1.000 -1.000 0.852 0.926 0.963 0.982 0.991 0.996 0.998 0.999 1.000 1.000"
const char * s = dma+4; // skip past "DMA ";
ret = 0; // ret now becomes a count of "safe values in a row"; a safe value is any number less than 0.500, per me
while((s)&&((*s == '-')||(*s == '.')||(isdigit(*s))))
{
const float fVal = atof(s);
if (fVal < 0.500f)
{
ret++;
// Advance (s) to the next number in the list
const char * space = strchr(s, ' '); // to the next space
s = space ? (space+1) : NULL;
}
else break; // oops, a dangerous value! Run away!
}
}
}
fclose(fpIn);
}
return ret;
}
// should be called periodically (e.g. once per second)
void DefragTick(Milliseconds current_time_in_milliseconds)
{
if ((current_time_in_milliseconds-m_last_fragmentation_check_time) >= Milliseconds(1000))
{
m_last_fragmentation_check_time = current_time_in_milliseconds;
const int fragmentationSafetyLevel = GetFragmentationSafetyLevel();
if (fragmentationSafetyLevel < 9)
{
m_defrag_pending = true; // trouble seems to start at level 8
m_fragged_count++; // note that we still seem fragmented
}
else m_fragged_count = 0; // we're in the clear!
if ((m_defrag_pending)&&((current_time_in_milliseconds-m_last_defrag_time) >= Milliseconds(5000)))
{
if (m_fragged_count >= 20)
{
// FogBugz #17882
FILE * fpOut = fopen("/proc/sys/vm/drop_caches", "w");
if (fpOut)
{
const char * warningText = "Persistent Memory fragmentation detected -- dropping filesystem PageCache to improve defragmentation.";
printf("%s (fragged count is %i)\n", warningText, m_fragged_count);
fprintf(fpOut, "3");
fclose(fpOut);
m_fragged_count = 0;
}
else
{
const char * errorText = "Couldn't open /proc/sys/vm/drop_caches to drop filesystem PageCache!";
printf("%s\n", errorText);
}
}
FILE * fpOut = fopen("/proc/sys/vm/compact_memory", "w");
if (fpOut)
{
const char * warningText = "Memory fragmentation detected -- ordering a defragmentation to avoid the OOM-killer.";
printf("%s (fragged count is %i)\n", warningText, m_fragged_count);
fprintf(fpOut, "1");
fclose(fpOut);
m_defrag_pending = false;
m_last_defrag_time = current_time_in_milliseconds;
}
else
{
const char * errorText = "Couldn't open /proc/sys/vm/compact_memory to trigger a memory-defragmentation!";
printf("%s\n", errorText);
}
}
}
}
关于linux - 如何在不冒 OOM killer 的风险的情况下 mmap() 大文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60079327/
这里就涉及到一个问题,到底Kill掉谁呢?一般稍微了解一些Linux内核的同学第一反应是谁用的最多,就Kill掉谁。这当然是Linux内核首先考虑的一种重要因素,但是也不完全是这样的,我们查一些Li
这个问题在这里已经有了答案: Set a JVM to dump heap when OutOfMemoryError is thrown (2 个答案) 关闭 5 年前。 我是JAVA新手。我在用
我们正在使用 Fitnesse 对复杂的基于 Web 的应用程序进行验收测试。全套流程需要几个小时才能通过,因此我们使用多个流程。设置如下: maven fork Fitnesse 服务器进程 mav
我正在Tensorflow的LSTM-RNN上训练一些音乐数据,并且遇到了我不明白的一些GPU内存分配问题:当实际上似乎还有足够的VRAM可用时,我遇到了OOM。 一些背景: 我正在使用6GB的GTX
我正在使用 tf 运行 seq2seq 模型,当使用 tf.train.Saver 从检查点文件加载参数时,推理程序运行良好。但是在使用 freeze_graph.py(使用 tf.framework
我有一个问题需要用 JS 中的某种继承来解决。 我设置了一个小的 jsfiddle 来解释,看: V1 http://jsfiddle.net/FFTj4/5/ function Vehicule(n
这里是 JS 的新手,所以如果我遗漏了一些明显的东西,我深表歉意。尝试构建一个随机数生成器(它以嵌套方式工作,所以有点像随机数元组列表),但我收到此代码的 OOM 错误。 (比如,如果我尝试做类似 g
我有一个需要显示全屏图像的应用程序,我从可绘制文件夹中获取图像,它们大约为 150-250 kb,但它仍然崩溃并出现 OutOfMemory 错误。当然不是第一张图片,但每次用户启动应用程序时我都会加
我正在使用 spark 从 postgres 表中读取并将其作为 json 转储到 Google 云存储。该表很大,有数百个 GB。该代码相对简单(请参见下文)但因 OOM 而失败。似乎 spark
即使系统中有足够的内存并且正确提供了所有必需的内存设置,Tomcat 仍无法启动并出现 OOM。这种情况并没有持续发生,证明 tomact 配置没有问题。 15-Jan-2019 20:17:31.0
我在高负载多线程Java项目中遇到OOM异常问题。 我很感激你能给我任何帮助。 德莱尔斯: 项目是建立在Java+Mysql作为存储。 没有证据表明在应用程序崩溃时会使用额外的RAM(任何监控工具都不
我使用 Android P-OS。内核版本为msm-4.14 自启动以来,oom 被调用并终止进程。不过内存还是很丰富的。我的内存大小是8GByte,Swap是1GByte。我什至没有使用交换。 [
所有的一切, 我正在使用 openjdk 1.8.0_212-b04、Tomcat 8.0.21 和 Red Hat 6.4。 并且我已经调整了测试web应用程序,确保重新部署后不会有没有这样的消息:
所以我在 Crashlytics 中看到我们有很多崩溃是由位图的 OOM 引起的。似乎其中 60% 来自 6.0.1 上的 Galaxy S7 Edge 设备。我们拥有的是一个包含 2 个图像的着陆屏
最近我们在 Docker 容器中遇到了 Ruby 的问题。尽管负载非常低,但应用程序往往会消耗大量内存,并且在提到的一段时间后会出现 OOM。 经过一番调查,我们将问题缩小到单线 docker run
Snakemake 工作流可以在任何类型的失败后重新尝试每次重启,包括如果错误是内存不足(OOM),例如 def get_mem_mb(wildcards, attempt): return
我有一个有趣的问题。我想我发现了一个无限请求循环,它导致我的 istio-proxy 在特定情况下因 OOM 错误而崩溃。 当我直接从应用程序容器内部将请求本地提交到应用程序时,它似乎工作正常,并且在
我使用的是 ActiveMQ 5.2,我的应用程序需要大量主题,大约 500,000 个。当我运行我的应用程序时,仅创建大约 1000 个主题后,ActiveMQ 会抛出 OutOfMemoryExc
我在 k8s 运算符上部署了一个结构化流作业,它只是从 kafka 读取数据,反序列化,添加 2 列并将结果存储在数据湖中(尝试了 delta 和 parquet),几天后执行程序增加了内存,最终我得
我的Mac上的Minikube中有一个本地Kubernetes集群。我将Minio独立服务器部署为具有指定资源限制的单个容器。当我上载大于容器内存限制的文件时,容器因OOMKilled原因终止。在Ub
我是一名优秀的程序员,十分优秀!