JVM 战士请教一个问题,各种语言都是怎样控制内存上限的?
类似于 java heap(-Xmx1024m)的设置,各种语言都是怎样设置的?
比较想知道 .net go swift rust node php haskell 等等
Rust: 你创建多少变量 /结构体就占用多少内存,变量出了作用域立马释放就不占内存了,没有虚拟机,也不存在 GC ,更没有内存上限的问题
C : 内存上限?老子说什么是上限什么就是上限!
C C++的内存上限只和操作系统和硬件有关吧
cgroups 大法好
楼上几位能不能看清题再答。题主是“主观需要上限功能”而不是“被上限所困扰”。
远古时代可以用 ulimit ,现在主要是在内存分配器上动手脚,比如可以 hook 一下 malloc 啥的。
如果 Java 里面已占用内存超过这个最大值但是又不能 GC 怎么办?
PHP 如果是 FPM 的话,脚本执行完毕就释放全部内存了。可以在 php.ini 中设置 memory_limit ,如果不限制,将 memory_limit 设置为-1 ,也可以在代码里使用 ini_set('memory_limit', '1G') 来设置
据我所知,好像这些语言写的 90%的东西都不需要限制内存,简单搜了下 CLR 好像没有限制内存的选项,剩下 10%可能就是上 cgroups 了吧
语言没有办法控制内存上限,就好像加法不能限制最大数一样,能限制内存上限的是 runtime
就是说非 vm 语言都需要在系统中控制吗?
像 dart 这种就可以通过虚拟机控制?
假如说用 rust 或者 go 开发了一个 web 服务,想控制他的内存上限在 200m,只能用系统限制,二进制文件是无法限制的
这样?
clr 也不能限制么?
jvm 会根据 score ,kill 掉占用内存最大的,👴的服务刚被系统干掉
Swift 貌似没有参数可以控制内存上限,本来就是指针引用计数来控制内存,该用多少就用多少。我的 Swift 后台服务长时间在 32m 以内。
CLR 可以限制内存
docs.microsoft .com/en-us/dotnet/core/runtime-config/garbage-collector#heap-limit
丢进 Docker 然后 limit ?
或者使用本身 Docker 所利用的 cgroups ?
node 的 [--max-old-space-size=] 应该能起到类似功能,比如
node --max-old-space-size=5120 app.js # Increase limit to 5GB
会在分配内存的时候(如 new XXX)弹出 OOM 异常。
这里有个巨坑,A 线程分配占用大内存并保持不动,然后可能会 B 线程分配新内存弹出 OOM 异常,然后 B 线程捕获异常打日志,然后打日志的代码也 OOM ,最后整个线程挂掉并且日志文件没日志。完全失去控制。
生产环境一般会加-XX:+ExitOnOutOfMemoryError 使其 OOM 就直接干掉整个进程直接重启完事。
#5 比起 hook malloc 啥的,直接启一个 docker ,然后限制 docker 容器的内存更合适一点吧。自己 hook 稍不注意就出问题了
语言层面本身没法限制吧,如果要实现的话可以用虚拟机或者容器,不过如果 OOM 会被 KILL 。
其实如果一定要从语言层面限制也是可以的,比如 rust 或 c++可以自己实现一个超过指定内存就 panic 的内存分配器然后指定为全局内存分配器
有虚拟机的语言在虚拟机层面控制,其它的在操作系统层面
内存上限是系统(或虚拟机)控制的不是语言自身
JVM 的内存上限是由 VM 而不是又运行程序控制的,严格的说它也是由操作系统(只不过是个 VM )而非应用控制的。另外,JVM 能精确控制的只有堆内存,整个 VM 的内存(即 java.exe 进程占用的内存),它也是不精确控制的。
你好歹讲点别的吧,加法?明显语言的语义上不限制上限的麻烦得多以至于几乎没什么语言不限制。只要你用的数据类型明确限制了最大元素,加法还能绕出去?就是任意精度数值,内部表示也受到空间的限制而不可能表示任意大的数;真正没限制最大数的怕就是只有 lazy list 之类的模拟了,你倒是统计下有几个语言这么做了?
最简单的,C 无符号数直接钦定不溢出,内部表示占用固定大小。只要语言残废到都是类似的玩意儿再在超出实例时禁止翻译就能静态证明不可超出限制了。阉掉了动态分配和递归的 C 类似物也是这样,只不过不方便算出具体上限是多少,一般要凑。
C:可以自己实现 malloc ,给你多少就只能用多少
应用->内存分配库->系统调用
从内存分配库的角度看,需要分配库追踪分配的数量,才能做到控制内存上限
从操作系统角度看,ulimit 可以限制分配虚拟地址的大小,实际物理的占用可能要 cgroup 来做
不管是什么语言,最终都会调到这两个来,vm 类的语言可能在内存分配库之上还有自己的限制(比如你说的 jvm)
graalvm 利用 native-image 构建的二进制文件依然可以用-Xmx 来设置程序运行时的堆内存大小
那么就表示这个二进制文件仍然包含了一层 jvm,由 jvm 来管理实际程序?
搜了一下看到 go 有 SetMaxHeap 函数来对堆内存进行设置,这是自带 gc 的语言的标准库实现
www.jianshu.com/p/4069d1e3d716
groups.google.com/g/golang-codereviews/c/brkajcJ0mhI/m/VyXYtel4BgAJ
那么 rust 有没有类似功能呢?
rust 不带 gc ,运行的时候二进制里面只有你的代码。
你不写一个那就是没有
你先搞清楚什么是语言,什么是数据类型吧。如果 Int 的最大值为 255 是因为一个 Int 只用了 8 个字节,和语言没关系,就好像你定义了 a[10],语言也不会限制你写 a[100],只是这样写会报错,同理你想访问 a[10^100000],一点问题都没有,语言不会也不应该考虑去帮你考虑内存够不够的问题
#27 jvm 回收的内存也是程序不用的内存,jvm 大部分情况是定时检测有没有可以回收的内存,而 Rust 不需要 GC 就可以释放这些内存,一旦程序不用就会立即释放。你既然创建了变量申请了内存,又不想让它申请内存,为什么会有这种需求呢
python 可以使用 resources.setrlimit (为啥大家都不提这个 setrlimit ,不会是我审错题了吧?)
当然它实际就是 ulimit ,不过在语言中我们总要对应到方法吧...
cgroups +1 ,如果嫌麻烦,可以用 docker 或者 podman
不带 gc 的语言 在编译期就确定了 内存占用了
了解一下 new malloc 是什么?
人工控制内存使用上限
报错不是限制?
没兴趣浪费金币仔细科普什么叫 ill-formedness 了。
8 字节,嗯嗯……
要不是你这典中典回复成了几个群里的乱窜的表情包,我还真差不多忘了我有回复这楼了……
报错是编译器行为……你不想报错完全可以强行编译,和语言没有关系。计算机理论里内存是无限的就好像数学世界里数是无限的一样。无论用什么语言,本质上都只是再控制指针操作内存,这是计算机的基本原理,如果语言能限制内存使用,就好像说数学坐标轴最大值只能到 1024 一样
?我甚至还要在这科普什么叫 conformance 和数学常识了吗?
该报错的不报错,不该报错的报错了,那叫 bug ,不管是编译器还是运行时的。决定什么该报错,该报什么错的是 spec 里的规则。写编译器一般没什么能力同时做整个 spec ,所以直接用的语言的 spec ;就算自己写 spec ,不是照抄的,实际上就发明了语言出来。
内存无限和数学如何明显是你 yy 。都玩那种玩具 model ,那早搞体系结构的就破产了。数学不好请自己补课。数无限?抽象代数我实在不想教,要不你还是先搞清楚比如 C 的无符号数折腾的就是数学上的 modular arithmetic 那套这样的入门经验再说吧。
有的语言没有 gc 不需要设置
你扯的什么乱七八糟的东西啊,来来来,最简单的,写一段程序,只要输入一个字符,立刻申请 1gb 的内存放着,别管我用来干什么,你举个例子,哪一门语言的编译器这么牛逼不给过?
不好意思,刚才不小心敲错了。。。。
实际上我没太看明白你的意思,可以详细解释下吗?或者指明一些资料?我内存这块的很多认识都是原先从实际工程现看的,可能已经和现在的发展脱节了?
原先做性能优化,使用 linux 的 hugepage 直接在用户态内存管理的时候就是类似 slab 来做操作,这个控制是算 runtime 做的吗? C 应该不限制这个?另外目前 x64 虚拟内虽然保存了一些高位,但是基本可以认为是无限的?
忽然想起来一个,你是说 /proc/pid/limit 下面的资源限制吗?
最近在整理我学习过的应用层的开发技术,发现大多数技术其实没有什么深度,我们学习的大多数技术其实就是步骤记录,操作指南,也正因为如此,培训班可以将 0 基础的人培养为一个初级程序…
在下给自己的家庭个人服务器装 Linux ,希望稳定三年吧,绝大多数时间不会时常更新系统 日常软件对 rh 的兼容性强所以首选 rh 系的 Linux CentOS 的故事大家…
(感谢网友 @我的上铺叫路遥 投稿) 在网上搜到的Cox大叔于1998年在开源社区写的一篇文章,当时很轰动,明眼人一看就知道是针对ESR那篇《大教堂与市集》,从中可见Alan在…