H.S.Teoh为D的垃集辩护.与Ola的反驳.

地址在此

h.s.:
公平的说,这几年,dgc改进了许多.虽然比期望的慢,但确实改进了.
垃集引起的性能问题一般是局部化的.可以用小部分(核心)手动管理来修复.你可重写为不用垃集函数,或使用标准垃集优化:在热点减少加载垃集.当回收发生时,你可用GC.stop/GC.collect来更细粒化控制.
我写过计算密集程序,发现垃集瓶颈.
1)重构从内循环调用的函数来重用缓冲,而不是分配新的,消除大量小分配.
2)用GC.stop来调度并稍微降低频率的GC.回收.
结果是40-50%的运行时降低.大概2倍加速.
你可能会说,你可以不用垃集,就不用再干上面的活了.
但:
1),因为我有GC,我可以花c++1/5时间来写程序.
2),优化只是在2-3个函数中的几行代码.最多几天的工作.95%的优化没用,因为他们不是瓶颈.
3),非热点区代码仍可利用垃集来减少写程序的负担.不会有人工管理内存的问题.
你完全可以同dGC一起写高性能程序,只是分析热点,在热点减少/避免垃集.因为不像java,你可以控制垃集.
另一个例子是fastcsv,还是先用GC方式写,然后profile来找瓶颈.还是大量小分配,然后为字段/行数据用线性分配,而不是单独分配.并尽量用切片.通过减少加载垃集/最小化复制,大量提升性能.

构和值语言偏爱栈分配,更持久对象,用,为了重用缓冲,用切片,避免无意义复制,用编译时自省来生成代码.如果有瓶颈,重构瓶颈.


ola的反驳:
没有写障,全局垃集不可能改进多少.只在有很少要跟踪指针时精确收集才有用.不可能用5倍时间来写非垃集代码.你有很多带不清晰所有权小对象弱针很难打断的循环引用时.跟踪垃集很有用.但许多良好设计的程序更多树状结构/清晰所有权.则不适用垃集.有两个问题:
1,延迟.在交互式应用,无法容忍.在批处理时可接受,即使渐进回收,体验也不爽.
2,消耗内存.更少的回收,导致更大的内存.消耗资源.
交互式应用.操作系统级编程,嵌入式,系统编程都很有用.


welkam:
即使用malloc/free分配大量临时对象,性能也会受影响.而尽量用分配,不到处复制,重用缓冲,则要更快.


ola:
Chrome拥有垃集是因为js用奇怪的方式资源.他们最终细颗粒了,且仅当调用栈短的时候才调用它.
高质量游戏引擎有类似细颗粒回收,而并不是传统的锁线程大扫描.GC说的是跟踪垃集.
对 max的回复:
如果是堆分配,只需要用负偏移(常见策略)即可.你需要传递指针类型,只需要对支持ARC的库,加个标记.
给gui…:
对小游戏,垃集等可以,许多开源项目,小数据集没问题.大数据集就失败.切换至ARC更有吸引力,更易规模化,更平均分发负载.但很可能不会发生.
回复welkan:
我们需要让编译器知道要跟踪哪些指针,来避免冗余指针,加一个类型,指示冗余指针.这样就不必用写障.
或者有个开关.我们还可以:

序号动作
1使垃集分配所有类对象,对他们用写障,
2对象指针,允许冗余注解.
3使切片和动态数组引用计数的.
4使默认为独针,类似c++,rust.

然后,我们需要改进精确跟踪:

序号动作
1利用llvm的精确栈/寄存器信息.
2引入标签联,仅在非标签联中允许冗余指针.
3每个编译阶段,给GC发送信息.
4在链接前,编译器生成窄跟踪正确指针的代码.

则不必实时查找类型信息,不必昂贵计算指针是否为垃集内存.编译器可假定生成的回收代码是精确的.

对系统级语言,GC不是好开头,不用标准库,用自定义运行时,更常见.D垃集弱是语言/编译器对其支持不够,llvmd支持更多垃集特征.d垃集Boehm干得更活,而Boehm都不流行.
Oilpan,chrome用的干的是多数系统级语言想干的,局限于特定垃集类型,支持渐进回收,缺点是必须指定跟踪哪种指针.d不能这样,仍是缺点.
系统编程,我觉得d最好用Oilpan的方法,并混合引用计数,使其为语言/编译器特征,至少对大的交互式应用是已证明的方法.简单使垃集,而其他都为RC人工管理.

有个小的运行时是有价值的,如果GC解决得更好,但运行时很重,则对低级系统编程,仍然是个问题.透明是个问题,你必须在各种层面都清晰了解事情,你不能理解,则不能修复问题,简单运行时比复杂高特征更有价值.
系统级编程,你知道每个子系统,你可以预期性能/资源问题.与只需要实现抽象语义的高层次不一样.
回复Basile B:
全部用c++11风格比混合两个模型更简单.c风格是恐怖.而用标准c++11则未遇见各种问题.在标准c++内存管理外获取更多性能,则可能出错.手动原位,忘记调用析构器,但对d也一样,你很少需要那样.2-3个点,如图片/音频.

在系统级,你必须手动维护垃集收集算法需要的不变量.如果改为不同的回收模型,要改需要的不变量.
可能替代方式:
1,用共享来避免进入其他线程时垃集分配内存.并切换为线本垃集.
2,为不同GC模型重定义语言语义/类型系统,这会破坏已有代码.
3,对存在的代码用现在GC,全面对新代码ARC.加一个版本语句,这样用户可添加至库,来告诉编译器支持哪个模型.

不是写至对象,而是已修改指针,当你指针从一个对象切换到另一个对象时,调用写障,然后标记对象,你需要2位来标记对象.目标应该是通过静态分析尽量减少写障.d需要更细颗粒的不变.
库灵针,不易同D的垃集交流.
是的,所以最好编译器,自动完成特定垃集对象
ARC是个很好的替代.比垃集,实现更好的ARC需要更少的工作.
最好是每线程一个垃集.或ARC或只有垃集.
显式所有者,并不难,只要所有库都是这样.当可用库不支持时,手动管理更多工作.
是的,200k以下GC没问题.但以上就有问题.ARC更好.
我认为d标准库,比dmd易改进.因为心智模型.
开源项目应该是更简单心智模型,也许我们可以有对开源更友好.更易使其扩展仅影响本地的语言.或许dmd可以搞成线程池+无栈主动器.对开发和服务有用,但对音频插件无用.
没有破坏性改变,GC改进不了.目前的D不担心GC,否则,他们走了.不会停留.生态系统不会好.
ARC是个大的改变.依赖库作者支持.线程本地垃集更合理,回收时锁定所有线程,非常不合理.游戏内容依赖lua,js,但不是游戏引擎.d应该更好,通过修复关注的问题.不能吸引系统级人员,是个损失.
现在是,我们的方向在哪里?
c++20足够好了.对py新手,当然d够用了.
三个选项:

序号选项
1调整语义来改进垃集,并接受破坏性改变
2切换系统级所谓的高级.
3实现ARC

学rust太晚了,要5年才能到达.做c++的无用.否则为何不用c++.必须要选一个方向,没有方向,就没有进步.


Max Haughton:
我同意GC有用,但除了不知道界线的灵针和分配释放外,没有替代方式对语言是个障碍.我不介意用GC,但有时想避免它时,很难.
我认为方向应该是像rust这样的健壮移动语义和分析,我想应该有点隐藏ARC,但不知道它如何处理.


welkam:
java/c#gc搞了一大堆临时分配,如c#json解析器,每1G内容花8G内存.运行太慢.
dmd目前方法是分配一个大块内存如1M.然后使用时有个定位指针.这是个简单策略,但提升70%的性能.
不实现写障是因为其会伤害低级编程.我认为,如果d有个打开写障及更好的GC的开关,许多人会用它,并会接受.


tsbockman:
d运行时标准库有各种问题,我希望的改进有:

序号改进
1完成std.experimental.allocator
2标准库中好,安全,灵活引用计数模块,要求更一步完成dip1000等.
3升级core.thread来完整支持@无垃集.不应该因为垃集未监视线程,则不能访问线程.休息等.
4各种管理内存组件的单线程版.避免原子操作.

这些问题都可解决,d缺少的是高质量库,而不是特征.


Basile B:
手动管理让你觉得你是超人.而自动管理让你觉得你是二年级学生.

posted @   zjh6  阅读(13)  评论(0编辑  收藏  举报  
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示