【ArchSummit】如何通过AIOps推动可量化的业务价值增长和效率提升?>>> 了解详情
写点什么

Rubinius 全速调试器技术内幕

  • 2008-01-29
  • 本文字数:1534 字

    阅读完需:约 5 分钟

Ruby 的调试器支持早已有之——长久以来,Ruby 发行时都附带着一个命令行调试器。不过,调试器的速度一直是个问题。通常,Ruby 调试器使用诸如 Ruby 的回调(callback)块或通过在 Ruby 代码执行前调用函数来实现。回调会检查线程是否挂起或该行代码是否存在断点。

Ruby 的自带调试器使用 Ruby 实现,包含一个通过 set_trace_func 设置的 Ruby 块。这一方法的更快速版本则采用了 C( ruby-debug Cylon debugger )和 Java( jruby-debug ) 作为实现语言。然而,无论回调执行的多快,这种解决方案的问题都始终存在:只要 debugger 一启动,所调试 Ruby 程序的每一行代码都会承受额外的开销。

对于这一问题的理想解决方案应该是不引入 _ 额外开销 _,然后在遇到断点时将线程挂起。也就是在被触发前,断点不会带来(CPU 时钟周期方面的)任何代价。这正是 Rubinius 的全速调试器所采用的方案——这里的“全速”意指程序即便是在被调试时,也能保持正常的运行速度。

如下的特性使得Rubinius调试器的全速成为可能:

  • 将所有的 Ruby 代码转换成 shotgun 虚拟机所执行的指令(op_codes)——目前通过op_code 解释器执行

  • 全速调试功能引入了一条名为 yield_debugger 的新指令——当该指令执行时会通知位于一个已定义 channel 之上的调试器线程(channels 是一种管道,也就是说从一端放入其中的数据可以在另一端接收到)

  • 方法的字节码可以被访问——实际上这一做法通常比较细微。这里示例一个String 类的``to_s方法: m = "".method(:to_s) cm = b.compiled_method<br></br># this yields an array of InstructionSet::Opcode objects cm.bytecodes.decode

  • 多种工具方法为将指令偏移对应到行号提供帮助,例如 CompiledMethod 的 first_ip_on_line 方法等。

有了这个功能之后,可以非常简单地在某个方法的特定行中设置断点

  • 获取这个方法的 Method 对象和对应的 CompiledMethod 对象
  • 指出这个断点行的第一条指令的位置
  • 把该位置的指令变成yield_debugger。原先的指令会被保存在一个用于管理的数据结构中
  • 在到达这个断点并且用户选择继续执行之后,原先的指令会被执行,而后会按正常的序列执行代码

这个功能已经存在一段时间了(参见 InfoQ: Evan Phoenix 访谈 - 深入 Rubinius:线程、对象空间、调试)。不过因为Adam Gardinerd 的工作,这个全速调试器现在可以被一般用户使用了。Adam Gardiner 为 Rubinius debugger 增加了基于命令行的用户界面以 及一些必要的命令。不仅如此,他编写的功能允许用户进行逐行单步调试。要使用这个功能只需要把当前断点的下一行也设为断点即可。当然,这个功能还需要了解 当前行是不是方法中的最后一行。不过在 Rubinius 中通过获取调用当前断点方法的句柄,这个信息也是可以得到的。因为上下文对象,例如方法活动栈,拥 有一个 sender 方法实现了这个功能。

调试器的使用很简单。在您装好了 Rubinius 后(查看如何检出并编译Rubinius ),通过如下方式启动 irb

shotgun/rubinius 然后执行: Rubinius::VM::debugger(注意:对于目前版本,输入debugger也同样可以工作)。然后您将会进入到调试器的文本界面 - 可用的命令列表可以通过"?"命令获得,包括管理断点和诸如查看 op_codes 和其他方法中的 Ruby 源代码这样的特性。

比起那些依靠 trace 方式调试的 Ruby 实现(不论这些实现的速度有多快),全速调试器都使得 Rubinius 具有了独特的优势。同样值得注意的是:除了整个 yield_debugger 指令使用了一些 C 代码,绝大多数 Rubinius 调试功能都是内建的。

您尝试过 Rubinius 了吗?您是否了解应如何有效利用 Rubinius 清晰可见的内部结构,例如可以在运行时刻访问并修改字节码、查看调用栈?

另:查阅 InfoQ 之前关于 Rubinius 的相关报道

查看英文原文: Inside the full speed Rubinius debugger

2008-01-29 23:11681
用户头像

发布了 24 篇内容, 共 27395 次阅读, 收获喜欢 0 次。

关注

评论

发布
暂无评论
发现更多内容

PHP程序员如何简单的开展服务治理架构(一)

CrazyCodes

php 服务治理

直播预告 | 数据操作加速器,CloudQuery v1.3.5 发布

BinTools图尔兹

sql 编辑器 数据治理 数据安全 数据库管理工具

分而治之——D&C

Kylin

3月日更 21天挑战 分而治之

Spring-Retry重试实现原理,有点东西哈

Java小咖秀

Java spring 源码 原理 开发

云原生技术及其未来发展趋势展望 | 趋势解读

浪潮云

云原生

PostgreSQL 集群宕机后恢复

桜喵ノねこ

区块链技术或加速企业“碳中和”战略落地

CECBC

区块

【LeetCode】132模式Java题解

Albert

算法 LeetCode 3月日更

Python SMTP 发送邮件方法

HoneyMoose

“刷脸”日益泛滥,“掌经脉”开辟生物识别新路

E科讯

智慧公安重点人员管控系统大数据分析平台的搭建

13828808769

智慧城市 智慧交通

带你了解数据库的“吸尘器”:VACUUM

华为云开发者联盟

数据库 数据 GaussDB(DWS) VACUUM

网络连接总超时?从四层模型上解析网络是怎么连接的

京东科技开发者

计算机网络 服务器 域名

情指勤指挥调度平台搭建,公安局情报指挥系统

翻译:《实用的Python编程》07_04_Function_decorators

codists

Python PEP

《Redis 核心技术与实战》学习笔记 08:GEO数据类型和时间序列数据

escray

redis 学习 极客时间 3月日更 Redis 核心技术与实战

k8s(Kubernetes)中Pod,Deployment,ReplicaSet,Service之间关系分析

ucsheep

Kubernetes k8s pod Deployment ReplicaSet

自媒体平台数据统计分析爬虫之【趣头条】模拟登陆分析详解及数据统计接口详解

ucsheep

接口 爬虫 趣头条 模拟登录

量化策略软件搭建,马丁策略交易软件开发

云原生数据库风起云涌,华为云GaussDB破浪前行

华为云开发者联盟

数据库 架构 云原生 华为云 GaussDB

终于知道为啥网页不让我复制粘贴了!

华为云开发者联盟

js 代码 button事件 复制粘贴 输入框

“英特尔‘IDM2.0’的疯狂”

E科讯

“数字云南”建设成效逐渐显现 区块链财政电子票据带来民生与环保效益

CECBC

区块链

超详细!手把手带你快速入门 GitHub!

JackTian

git GitHub 开源

技术杂谈 | Flutter 的性能分析、工程架构与细节处理

有道技术团队

flutter

神策大数据技术直播系列课第二季,开讲啦

神策技术社区

大数据 性能优化 大前端 工程师 事件分析

IAP:物联网终端软件升级技术

华为云开发者联盟

IoT LiteOS iap 物联网终端 OTA

区块链BaaS应用服务平台的搭建

13828808769

区块链+ #区块链#

商品溯源之痛,区块链对商品假冒的解决方案

13828808769

区块链+ 区块链应用 区块链发展 #区块链#

用 WebRTC 打造一个音乐教育 App,要解决哪些音质难题?

阿里云视频云

音视频 WebRTC 在线教育 RTC

力扣(LeetCode)刷题,简单题(第14期)

不脱发的程序猿

面试 LeetCode 28天写作 算法攻关 3月日更

Rubinius全速调试器技术内幕_Ruby_Werner Schuster_InfoQ精选文章