写点什么

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

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

关注

评论

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

Github百万收藏!这部《从零开始写分布式服务框架》称霸榜首!

Java你猿哥

Java 架构 分布式 ssm 分布式框架

阿里人都在死磕的全彩版"并发编程笔记",面试大厂必备!

Java 并发编程 高并发

互联网工程师Java面试八股文及答案整理(2023最新版)

Java java面试 Java八股文 Java面试题 Java面试八股文

Nautilus Chain:独特且纯粹的创新型 Layer3

股市老人

Nautilus Chain上首个DEX PoseiSwap即将开启IDO,潜力几何?

BlockChain先知

开源字节 考研集训营小程序

源字节1号

开源 软件开发 前端开发 后端开发 小程序开发

模块七作业 - 王者荣耀商城异地多活架构设计

🐢先生

架构实战营

Github标星78k,Alibaba最新发布的Spring Boot项目实战文档!太强了

Java你猿哥

Java spring Spring Boot mybatis ssm

硬核!靠这套MySQL笔记轻松过了阿里二面,基础架构调优齐全了

Java MySQL 数据库

炸了!力扣官方首发了这套1568页LeetCode算法刷题笔记(彩页版)

Java你猿哥

面试 算法 LeetCode 力扣 左程云

kafka消费者那些事儿

Java kafka 消费者

绝了!阿里大佬的"Redis深度核心笔记",从基础到源码,全是精华

Java 数据库 redis 缓存

熬了一个月肝完这份阿里架构师的Java面试手册,我从20K变成了30K

Java java面试 Java八股文 Java面试题 Java面试八股文

阿里大佬带你一周刷完Java面试八股文,比刷视频效果好多了!

Java你猿哥

Java 分布式 微服务 JVM ssm

一种适用于大量租户大量角色的权限系统设计

Java你猿哥

Java ssm 权限管理

Java 容器详解:使用与案例

小万哥

Java 程序员 容器 面试 后端

【1对1咨询】前端和后端,哪个更简单?转行程序员的捷径

程序员晚枫

前端 后端 转行

流批一体数据交换 etl-engine 融合查询语法

weigeonlyyou

数据迁移 ETL 云数据迁移 Kafka ETL 流批一体化

程序员的私人助理:Amazon CodeWhisperer

申屠鹏会

AI Codec

Nautilus Chain:独特且纯粹的创新型 Layer3

西柚子

阿里资深架构师总结的春招Java岗核心笔记,GitHub标星20k

Java java面试 Java八股文 Java面试题 Java面试八股文

2023年互联网Java工程师高级面试八股文汇总(1260道题目附解析)

Java你猿哥

Java MySQL zookeeper JVM java面试

浅析 Redis 数据结构 List 及其底层编码方式

Java你猿哥

Java redis List ssm

面试官问:kafka为什么如此之快?

Java kafka 面试

数字化转型应该如何去做?(4A架构篇)

数字随行

数字化转型

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