我到处都在寻找答案,但我认为我已经达到了所能找到的极限。我的问题似乎与这个问题有点相关:Android NDK mmap call broken on 32-bit devices after upgrading to Lollipop 但没有提供答案。
我的问题是我尝试通过 mmap 调用从文件中内存映射 457232384 字节。在装有 Android 5.1.1 的两个不同设备(三星 Galaxy Note 3 和 OnePlus One,每个 3GB RAM)上,该调用失败并显示错误号 12“内存不足”。实际上,当我尝试分配超过 300MB 的内存时,调用失败了。 313524224 字节 (299MB) 有效,314572800 (300MB) 无效。
事实是,同一个调用适用于仍然使用 Android 4.4.2 的第三台设备。更奇怪的是,此调用适用于带有 SDK 21 (Android 5.0) 的 Android ARM 模拟器。不用说,可以毫无问题地加载相同数量的数据(未映射)。
dmesg 向我报告:
<3>[ 1137.488411] [0:Thread-298: 4267] arch_get_unmapped_area (TASK_SIZE - len < addr) len=457232384 task size=3204448256 pid=4267 do_align=0 addr=3034054656 mmap_base=3069939712
尝试映射文件的函数(来自 openfst)如下:
MappedFile* MappedFile::Map(istream* s, const FstReadOptions &opts,
size_t size) {
size_t pos = s->tellg();
if (opts.mode == FstReadOptions::MAP && pos >= 0 &&
pos % kArchAlignment == 0) {
int fd = open(opts.source.c_str(), O_RDONLY);
if (fd != -1) {
int pagesize = getpagesize();
off_t offset = pos % pagesize;
off_t upsize = size + offset;
void *map = mmap(NULL, upsize, PROT_READ, MAP_SHARED, fd, pos - offset);
char *data = reinterpret_cast<char*>(map);
if (close(fd) == 0 && map != MAP_FAILED) {
MemoryRegion region;
region.mmap = map;
region.size = upsize;
region.data = reinterpret_cast<void*>(data + offset);
MappedFile *mmf = new MappedFile(region);
s->seekg(pos + size, ios::beg);
if (s) {
VLOG(1) << "mmap'ed region of " << size << " at offset " << pos
<< " from " << opts.source.c_str() << " to addr " << map;
return mmf;
}
delete mmf;
} else {
LOG(INFO) << "Mapping of file failed: " << strerror(errno);
}
}
}
// If all else fails resort to reading from file into allocated buffer.
if (opts.mode != FstReadOptions::READ) {
LOG(WARNING) << "File mapping at offset " << pos << " of file "
<< opts.source << " could not be honored, reading instead.";
}
MappedFile* mf = Allocate(size);
if (!s->read(reinterpret_cast<char*>(mf->mutable_data()), size)) {
delete mf;
return NULL;
}
return mf;
}
每次从 mmap 返回都是 MAP_FAILED。
有人对我在哪里可以解决我的问题有建议吗? 谢谢!
编辑:
这是臭名昭著的 mmap 调用之后/proc/self/maps 的内容:http://pastebin.com/1864jZC2
一点差距分析:
Gap between 00000000 and 12c00000 (diff = 314572800 bytes, 300 MB)
Gap between 42c00000 and 55281000 (diff = 308809728 bytes, 294.50390625 MB)
Gap between 67e80000 and 67ea4000 (diff = 147456 bytes, 0.140625 MB)
Gap between 7778b000 and 77800000 (diff = 479232 bytes, 0.45703125 MB)
Gap between 77a80000 and 77a82000 (diff = 8192 bytes, 0.0078125 MB)
Gap between 77c00000 and 77c04000 (diff = 16384 bytes, 0.015625 MB)
Gap between 78080000 and 780b7000 (diff = 225280 bytes, 0.21484375 MB)
Gap between 79ac1000 and 79ac2000 (diff = 4096 bytes, 0.00390625 MB)
Gap between 7db70000 and 7db71000 (diff = 4096 bytes, 0.00390625 MB)
Gap between 7e000000 and 7e001000 (diff = 4096 bytes, 0.00390625 MB)
Gap between 7e0fe000 and 7e0ff000 (diff = 4096 bytes, 0.00390625 MB)
Gap between 7e145000 and 7e146000 (diff = 4096 bytes, 0.00390625 MB)
Gap between b6fb9000 and be6ff000 (diff = 125067264 bytes, 119.2734375 MB)
Gap between beeff000 and ffff0000 (diff = 1091506176 bytes, 1040.94140625 MB)
编辑:
@fadden 回答的评论中对我有用的解决方案。
TL;DR:将 dalvik.vm.heapsize 设置为 512m。
最佳答案
在 mmap() 失败后转储 /proc/self/maps 的副本(只需从代码中打开文件并将内容复制到临时文件)。由于 ASLR,您可能无法获得较大的连续虚拟地址范围。 .
Android 中的一些 Zip 文件处理代码使用 mmap() 映射整个文件,并在内存中对其进行操作。有一天,有人创建了一个 1GB 的 Zip 文件,但无法打开它。虽然进程的虚拟地址空间有足够的空闲页面,但没有足够的连续 页面来创建单个线性映射。 (IIRC,解决方案是 mmap() 只是中央目录。)
maps 输出将向您展示进程的地址空间是什么样的。 300MB 对于 ASLR/fragment 问题来说似乎有点低,但它是开始寻找的好地方,并且可能解释不一致的行为。
关于android mmap 因内存不足而失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33897711/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf
我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束
我正在尝试在配备ARMv7处理器的SynologyDS215j上安装ruby2.2.4或2.3.0。我用了optware-ng安装gcc、make、openssl、openssl-dev和zlib。我根据README中的说明安装了rbenv(版本1.0.0-19-g29b4da7)和ruby-build插件。.这些是随optware-ng安装的软件包及其版本binutils-2.25.1-1gcc-5.3.0-6gconv-modules-2.21-3glibc-opt-2.21-4libc-dev-2.21-1libgmp-6.0.0a-1libmpc-1.0.2-1libm
你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p
一段时间以来,我一直在使用open_uri下拉ftp路径作为数据源,但突然发现我几乎连续不断地收到“530抱歉,允许的最大客户端数(95)已经连接。”我不确定我的代码是否有问题,或者是否是其他人在访问服务器,不幸的是,我无法真正确定谁有问题。本质上,我正在读取FTPURI:defself.read_uri(uri)beginuri=open(uri).readuri=="Error"?nil:urirescueOpenURI::HTTPErrornilendend我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,这样我的连接就不是问题所在,但是我
我在思考流量控制的最佳实践。我应该走哪条路?1)不要检查任何东西并让程序失败(更清晰的代码,自然的错误消息):defself.fetch(feed_id)feed=Feed.find(feed_id)feed.fetchend2)通过返回nil静默失败(但是,“CleanCode”说,你永远不应该返回null):defself.fetch(feed_id)returnunlessfeed_idfeed=Feed.find(feed_id)returnunlessfeedfeed.fetchend3)抛出异常(因为不按id查找feed是异常的):defself.fetch(feed_id
我正在为毕业设计开发GEM,TravisCI构建不断失败。这是我在Travis上的链接:https://travis-ci.org/ricardobond/perpetuus/builds/8709218构建错误是:$bundleexecrakerakeaborted!Don'tknowhowtobuildtask'default'/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_wrapper:14:in`eval'/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_