Bright 和 Manas 合作创建 Crystal 开发工具

在最近的 Crystal 1.10 版本发布 中,引入了两个新的编译器工具:crystal tool dependencies
和 crystal tool unreachable
。同时,Crystal 团队还发布了 perf-tools,这是一个用于跟踪内存使用情况和纤程的 shard。在本文中,我们将深入探讨这些工具的开发故事。
这些工具的开发得到了 Bright 的赞助,Bright 是一个用于保护网站的智能漏洞利用工具的制造商。漏洞利用工具通过搜索端点并使用大量潜在的安全威胁来攻击它们。作为一个成熟的产品,它多年来一直有机地发展,需要专门的工具来改进它。因此,Bright 要求 Manas 在两个主要方面提供帮助:应用程序重构和查找内存泄漏。
重构
该应用程序有两个鲜明的特点:发现端点和攻击它们。从架构的角度来看,将它们拆分为两个不同的应用程序是有意义的。这是一个主要的重构,需要确定源代码树的哪些部分属于哪个应用程序。为了简化此过程,我们构建了 crystal tool dependencies
,它显示了 require
依赖项的树。遵循 require 图,拆分应用程序变得更容易。
此外,crystal tool dependencies
有助于理解由 require
顺序引起的冲突。例如,如果两个文件 a.cr
和 b.cr
为一个类定义了相同的方法,Crystal 将使用来自最后被 require 的文件的定义。使用此工具,我们可以观察 a.cr
和 b.cr
被 require 的顺序,从而了解 Crystal 为什么调用其中一个定义而不是另一个定义。
为了完成分离,我们需要识别每个 require 树中的死代码。为此,我们构建了 crystal tool unreachable
来显示 defs
,这些代码定义但从未被调用。
内存泄漏查找
在某些情况下,应用程序的内存消耗可能会无限增长,直到耗尽全局内存。为了检查内存使用情况并捕获泄漏的纤程,我们在 perf-tools shard 中创建了两个工具。第一个工具是 mem_prof
,它在导入后会跟踪内存分配,允许按位置或类型列出内存分配。例如,可以跟踪某个类实例是否保存了大量数据。如果该实例应该在某一点后被垃圾回收以释放内存,而它没有,那么这可能会导致泄漏。
第二个工具是 fiber_trace
,它列出了正在运行的纤程,以及它们的分配点和 yield 点——纤程将执行返回给调度程序的位置。一个使用示例是跟踪纤程是否仍然存活,如果是,那么它执行的最后一个操作是什么。
这两个工具共同帮助我们和 Bright 团队修复了几个泄漏。
结论
在一个大型生产应用程序上工作是一次丰富的体验,构建必要的工具帮助我们改进了编译器及其生态系统。我们非常感谢 Bright 的支持。
如果您在使用 Crystal 应用程序时遇到困难,欢迎您联系 crystal@manas.tech。Manas 可以帮助您解决难题,解决方案最终可能会通过新的或改进的工具进一步丰富 Crystal 生态系统。