最新发布《数智时代的AI人才粮仓模型解读白皮书(2024版)》,立即领取! 了解详情
写点什么

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:11677
用户头像

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

关注

评论

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

我也创业了!

Serverless Devs

人工智能 Serverless 云原生

Nautilus Chain 主网上线,Zepoch 持有者将获第三轮 POSE 空投

威廉META

容灾切换时间减少 99%,“云边协同”如何提升影演服务效率与稳定性

阿里巴巴云原生

阿里云 云原生

3种常见的测试自动化类型

汽车之家客户端前端团队

前端 单元测试 集成测试 自动化测试 端到端

记一次容器环境下出现 Address not available

阿里巴巴云原生

阿里云 容器 云原生

从单元测试到性能测试:41款工具满足所有的软件测试需求

PingCode

软件测试 PingCode 软件测试工具

LeaRun快速开发框架如何解决低代码劣势?

力软低代码开发平台

NFTScan | 07.17~07.23 NFT 市场热点汇总

NFT Research

NFT\

可视化逻辑编排工具——低代码/无代码平台

互联网工科生

软件开发 低代码 无代码 JNPF

MobPush Android SDK 厂商推送限制

MobTech袤博科技

消息推送 Android; 智能推送 推送 推送系统

10 个处理 JavaScript 对象的实用技巧!

这我可不懂

JavaScript 前端 开发语言

别再说调试器不好用了!

高端章鱼哥

前端 调试器

数字孪生搭高台,温控节能唱新戏

鲸品堂

数字孪生 建模 智慧机房

程序化广告还有未来么?——程序化领域变化的底层逻辑和反思

不在线第一只蜗牛

系统架构 系统搭建 程序化

搭建 OpenTiny 组件库的 Playground 指导手册

OpenTiny社区

开源 Vue 前端 UI组件库

深入理解 Serverless 计算的并发度

阿里巴巴云原生

阿里云 Serverless 云原生

云和恩墨大讲堂 x 长江鲲鹏 x openGauss Meetup(武汉站)圆满落幕!

daydayup

opengauss

2023年秋招最新版牛客网Java面试题及答案整理(持续更新)

架构师之道

Java 面试

香港中文大学携手PingCode打造运维管理解决方案

PingCode

PingCode 香港中文大学

MySQL能用OFFSET分页查询吗

fm

MySQL

安卓快速启动,启动速度 285 毫秒的实时安卓操作系统(RTAndroid)或 实时 Linux

winfredy

android Linux 快速启动

低代码是怎么火起来的?

这我可不懂

软件开发 低代码 JNPF

openGauss 5.0.0支持用户级全量审计解密

daydayup

opengauss

和鲸 ModelWhale 与麒麟系统适配认证,打造自主安全、性能可靠的信创 AI 基础软件

ModelWhale

人工智能 信创 国产 麒麟软件 数据科学平台

活动回顾丨云原生技术实践营广州站回放 & PPT 下载

阿里巴巴云原生

阿里云 云原生

第二届粤港澳大湾区(黄埔)国际算法算例大赛正式开启报名

ModelWhale

算法大赛 琶洲 院士 数据科学竞赛 算法赛

网关改造正当时,跟学 HigressOps 夏季营

阿里巴巴云原生

一文了解 MySQL 全新版本模型

爱可生开源社区

可视化开发工具:让软件应用开发变得更轻松

高端章鱼哥

编程 低代码 JNPF

第一批AIGC独角兽开始裁员了

Openlab_cosmoplat

人工智能

Docker的架构与安装

timerring

Docker

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