2024 基于 Rust 的 linter 工具速度很快

news2024/12/24 2:34:18

2024 年 Web 工具的一大趋势是使用 Rust 重写现有工具。Rust 是一种出色的编程语言,能生成运行速度惊人的二进制文件,且与其它 Web 工具的互操作性极佳,这得益于 WebAssembly 的帮助。swc 和 Turbopack 等工具的速度提升为快速开发体验带来了巨大变革。

Biome、deno lint、Oxc 和 RSLint 等项目都有一个用 Rust 编写的 JavaScript/TypeScript 代码检查器。对于那些对开发工具速度缓慢感到不满的开发人员来说,以Rust(本机代码)速度运行代码检查器,而非JavaScript(JIT脚本)速度,无疑是很有吸引力的。Prettier 甚至为 Biome 提供了 20,000 美元的奖金,以表彰其实现了与 Prettier 格式部分的 >95% 兼容性!

然而,基于 Rust 的 linters 是无法完全取代 ESLint 的。虽然性能优势明显,但也存在一个明显的缺陷:类型检查的 linting 功能缺失

回顾:类型检查的 Linting

传统上,像 ESLint 这样的 lint 工具一次只能检查一个源代码文件。这使得它们运行速度较快,理论上可以进行缓存和并行处理。

typescript-eslint 引入了使用类型信息的 linting 概念。通过调用 TypeScript 的类型检查 API,lint 规则可以根据项目中的其他文件提供的类型信息,对代码做出更加明智的决策。

类型检查的 lint 规则可能比传统的 lint 规则功能更强大。例如:

  • @typescript-eslint/await-thenable :禁止在非 Promise 值上使用不必要的 await 调用。

  • @typescript-eslint/no-floating-promises :可以提醒是否创建了一个 Promise 但忘记安全地处理它。

  • @typescript-eslint/no-for-in-array :用于标记对数组的不安全的 for...in 迭代(不是 for...of)。

这些规则只有在能够使用类型信息来确定何时报告问题时才有实际用处。没有类型信息,它们将无法理解从另一个模块导入的值的类型。

类型检查的 Linting 性能

类型检查的 linting 相比传统 linting 存在的主要劣势在于性能。这是因为类型化的 lint 规则需要调用 TypeScript 等 API 来获取类型信息,通常需要读取所有文件以确定哪些文件会影响其他文件的类型。因此,类型检查的 linting 性能通常会低于对整个项目运行 TypeScript 的性能。

TypeScript 本身也在不断优化性能。例如,项目引用可以显著帮助处理更大的项目。TypeScript 即将推出的独立声明模式看起来也可以显著提高处理更大项目的性能。

但即使所有这些加速都完美地工作,类型检查的 linting 设计上仍然比传统的 linting 慢几个数量级。因为从项目中推断类型的过程本质上比传统的 lint 规则一次只查看一个文件要慢得多。

大多数情况下,当看到类型检查的速度慢的项目时,根本原因要么是 typescript-eslint 配置错误,要么是 TypeScript 类型慢。

基于 Rust 的代码检查工具和类型检查

目前还没有基于 Rust 的代码检查器与 TypeScript 的类型检查 API 集成,这意味着基于 Rust 的代码检查器不能完全替代 ESLint + typescript-lint。

如果你不需要任何类型检查的 lint 规则,那么可以切换到基于 Rust 的 linter。但强烈建议你至少查看 typescript-lint 中推荐的类型检查规则,以了解缺少什么。

甚至可以同时运行这两种工具:首先使用原生速度的 linter 快速反馈,然后仅使用 typescript-eslint 查看包含类型信息的规则。这个想法得到了多个原生速度 linter 维护者的支持:

  • Biome 的 Emanuele 认为双重 linting 是一种合理的策略。

  • Oxc 的公告将 oxlint 描述为在 ESLint 过慢时的增强工具,而不是完全替代品。

这种互补而非取代的愿望部分源于这两种 lint 工具在运作方式上的重大结构性差异。原生速度的 lint 工具尚未在其 lint 规则中实现类型检查。下面来深入探讨这一奇怪的功能差距。

集成类型检查的 Linting 和基于 Rust 的 Linting

目前,TypeScript 的核心功能是为 TypeScript 编译器和语言服务提供支持的代码,它是唯一能够为 TypeScript 代码提供可靠类型检查的组件。由于TypeScript是用TypeScript编写的,因此其类型检查以JavaScript的速度运行。

为了实现与 TypeScript 的类型检查的集成,基于Rust的代码检查器面临几个选择:

  1. 承受性能损失,调用TypeScript的JavaScript速度类型检查API。

  2. 使用原生速度语言重新实现TypeScript的API。

  3. 将 TypeScript 的 API 提升到原生速度。

此外,基于 Rust 的 linter 不允许在 JavaScript 中编写自定义 lint 规则。虽然这对大多数 JavaScript 生态系统来说是一个贡献障碍,但这与本文的重点是两个独立的问题。

因此,将基于 Rust 的代码检查器与 TypeScript 的类型检查集成在一起有不同的选项。

降低 JavaScript 速度

选择这种性能影响方案可能会使基于 Rust 的 linter 速度降低到几乎与 ESLint 无明显性能优势的程度。

以原生速度重新实现 TypeScript

对于 TypeScript 用户来说,以原生速度重新实现 TypeScript 是一个极具吸引力的前景,而不仅仅是对于 linter。目前已有三个重要的尝试:

  • Ezno:一种类似于 TypeScript 的新语言,增加了依赖类型等特性。

  • stc:一个可以替代 TypeScript 类型检查的 Rust 编写项目。

  • TypeRunner:一个较早的尝试,使用 C++ 编写,但已不再积极开发。

需要注意的是,以新语言重新实现 TypeScript 是一项艰巨的任务。TypeScript 的类型推理需要处理泛型类型、协变、逆变等复杂边缘情况,这是一项极具挑战性的任务。这些项目目前都处于非常早期的阶段,可能需要很长时间才能准备投产。

那是否可以通过缩小项目的范围,只实现TypeScript的类型推理部分,从而降低这一选项的复杂性呢?对于 linters 来说,一个简化版的TypeScript,跳过源代码转换、类型检查可分配性错误等部分,只专注于编程类型检查API,或许更为实用。例如,Oxc 项目已经成功地实现了一个 TypeScript 类型推理的简化版,仅用几千行Rust代码就完成了这一任务。

然而,我们必须正视TypeScript背后有一个强大的开发团队和社区支持的现实。TypeScript团队由专业的编程语言专家组成,并且持续从社区中获得贡献。对于任何尝试重新实现TypeScript的项目来说,跟上TypeScript的更新步伐是一项几乎不可能完成的任务。尽管Ezno和stc等项目展现了令人印象深刻的成果,但它们作为独立项目的长期可行性仍然充满了不确定性。

将 TypeScript 的 API 提升到原生速度

为了提高TypeScript的性能,一个更具可行性的长期方案是优化其类型检查器的运行速度。目前有几种可能的解决方案:

  • 将TypeScript的类型检查器转换为更高效的编程语言,如Go或Rust。这可以通过编写一个转换工具来实现,将TypeScript源代码转换为这些更快的语言。

  • 对TypeScript进行预编译和优化,类似于将其转换为二进制格式。这种方法可以在编译时对代码进行优化,以提高运行时的性能。

  • 利用Node.js的用户快照技术来优化启动时间。通过在启动时预先优化代码,可以加快冷启动编译器的速度。

  • AssemblyScript和Static TypeScript是另外两个有趣的探索方向,它们通过使用TypeScript的子集或修改版本来关注低级性能。

这些方案都面临一定的挑战,需要投入时间和资源进行开发。然而,通过持续优化和改进,可以逐步提高TypeScript的性能,使其更加适应快速发展的开发需求。

虽然可以通过各种方法来加速TypeScript的运行,但其实TypeScript本身的架构是阻碍性能提升的主要因素。它的代码基于一种假设,即运行时环境将提供内置的垃圾回收、可变对象等功能,而这些功能往往会带来性能上的损耗。

为了真正提高TypeScript的性能,我们可能需要重新设计其架构,使其更加适应高性能场景:

  1. 隔离声明模式:这可能是最直接的方法,通过将类型声明与实际代码隔离,可以减少编译时的计算量,从而提高运行速度。

  2. 优化全局类型扩展:为了更好地支持并行化,我们需要限制全局类型扩展的使用,以减少潜在的性能瓶颈。

  3. 改进检查器运行方式:通过改变TypeScript检查器的运行方式,可以避免一些不必要的性能损耗,进一步提高运行速度。

然而,任何对TypeScript结构的重大更改都可能导致其API的重大变化,并可能引入新的问题。目前看来,除了可能在2024年推出的隔离声明模式外,其他的大规模改动短期内不太可能实现。

TypeScript 集成 Linting

另一个策略是将 linting 集成到现有的 TypeScript 语言服务器基础架构中。TypeScript 语言服务插件允许添加工具作为 TypeScript 编辑体验的一部分运行。

可以看到过两次尝试:

  • Quramy/typescript-🐴-language-service:ESLint 的通用 TypeScript 语言服务插件

  • johnsoncodehk/typescript-linter:基于 TypeScript 语言服务器构建的代码检查器的重新实现

两者似乎都有希望。为了与现有规则兼容,在短期内将 ESLint 作为 TypeScript 语言服务插件运行是更可行的。无论哪种方式,在不落后于其他语言的情况下,如何使 TypeScript 体验变得更好,尤其是考虑到 ESLint 打算拥抱其他 Web 语言,这将是一个关键挑战。

小结

基于 Rust 的 JavaScript/TypeScript 代码检查器,如 Biome、deno lint、Oxc 和 RSLint,都是非常快速的项目。但与 ESLint + typescript-ndrings 的类型检查代码规则相比,这种速度存在严重的功能差距。在决定使用哪个工具时,你应该了解这些权衡。Biome 和 oxlint 都表示在一定程度上建议先运行一个更快的原生速度代码检查器,而不是运行基于类型的 typescript-lint。

基于 Rust 的 linter 最终可能会以原生速度代码获得类型检查 linting 的好处。但要实现这一点还有很长的路要走。

当然也有好处和坏处,按照自己需求使用即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1389125.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营第24天 | 理论基础 77. 组合

目录 理论基础 什么是回溯法 回溯法的效率 回溯法解决的问题 如何理解回溯法 回溯法模板 77. 组合 💡解题思路 💻实现代码 理论基础 什么是回溯法 回溯法也可以叫做回溯搜索法,它是一种搜索的方式。 回溯法的效率 虽然回溯法很难&#xff…

Nestjs 笔记

一、模块添加版本 1、添加如下代码 2、访问方式 http://localhost:3000/v1/list 二、跨域处理 1、安装依赖 npm install corsnpm install types/cors -D 2、app.module.ts 添加代码 import { NestFactory } from nestjs/core; import { AppModule } from ./app.module; i…

QQ视频聊天怎么录制

虽然微信几乎成为主流的聊天工具,但是不可否认的是QQ视频聊天仍有他的趣味所在,多种特效在视频的时候增加乐趣,那么如果QQ视频聊天的时候可以录制聊天内容吗?当然是可以的。可以使用电脑自带的视频录制工具,或者QQ自带…

k8s的存储卷、数据卷---动态PV创建

当发布PVC之后可以生成PV,还可以在动态服务器上直接生成挂载目录。PVC直接绑定和使用PV。 动态PV需要两个组件 存储卷插件:Provisioner(存储分配器)根据定义的属性创建PV StorageClass:定义属性 存储卷插件 存储卷插件:k8s本…

电脑安装 Python提示“api-ms-win-crt-process-l1-1-0.dll文件丢失,程序无法启动”,快速修复方法,完美解决

在windows 10系统安装完python后,启动的时候,Windows会弹出错误提示框“无法启动此程序,因为计算机中丢失了api-ms-win-crt-process-l1-1-0.dll,尝试重新安装该程序以解决此问题。” api-ms-win-crt-process-l1-1-0.dll是一个动态…

SCSI/UFS储存 基础

一、UFS协议 UniPro 的上面就是 UTP 和 SCSI 命令集,由于涉及的 SCSI 命令是很大一块需要单独来讲,所以这里只简单两笔。正如最开始提到的,UTP 和 SCSI 是属于 SCSI 这部分,在 JEDEC 的标准里能找到它们的具体说明。 UTP&#xf…

仅用三张图片实现任意场景三维重建:ReconFusion

论文题目: ReconFusion: 3D Reconstruction with Diffusion Priors 论文作者: Rundi Wu, Ben Mildenhall, Philipp Henzler, Keunhong Park, Ruiqi Gao, Daniel Watson, Pratul P. Srinivasan, Dor Verbin, Jonathan T. Barron, Ben Poole, Aleksande…

Java - Lombok的添加和使用详解

目录 🐶6.1 lombok介绍 🐶6.2 lombok使用 1. 🥙添加方法一 2. 🥙添加方法2 3. 使用 🐶6.3 lombok常用注解 1. 🥙Getter和Setter 2. 🥙ToString 3. 🥙NoArgsConstructor和Al…

随笔03 笔记整理

图源:文心一言 关于我的考研与信息安全类博文整理~🥝🥝 第1版:整理考研类博文~🧩🧩 第2版:提前列出博文链接,以便小伙伴查阅~🧩🧩 第3版:整理We…

光彩耀新年,戴森美发科技品类,见证成长美一面

龙年将至,祥瑞满天,新年曙光寓意着好运从「头」开始,同时也承载着人们对新一年的期许。值此之际,戴森中国美发科技品类正式发布全新蓝彩朱红色系列产品,为新年注入活力与希望,携手消费者一起开启护发造型新…

力扣hot100 寻找重复数 二分 抽屉原理

Problem: 287. 寻找重复数 文章目录 思路复杂度🎈 Code 思路 👨‍🏫 参考题解 复杂度 时间复杂度: O ( N log ⁡ N ) O(N \log{N}) O(NlogN) 空间复杂度: O ( 1 ) O(1) O(1) 🎈 Code class Solution {public int findDu…

ASP.NET Core列表增删改查

前置要求&#xff1a; 1. vueelement-plus实现前端静态页面 HelloWorld.vue <template><h2>hello界面</h2><div class"tableList"><!-- 搜索框 --><el-row :gutter"20"><el-col :span"8"><!-- 搜…

【备战蓝桥杯】今天给大家整点解压的~

【备战蓝桥杯】今天给大家整点解压的~ 蓝桥杯备赛 | 洛谷做题打卡day8 文章目录 【备战蓝桥杯】今天给大家整点解压的~ 蓝桥杯备赛 | 洛谷做题打卡day8[NOIP2017 普及组] 成绩题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提…

【书生·浦语】大模型实战营——LMDeploy 大模型量化部署实战

大模型部署背景 大模型部署是指将训练好的模型在特定的软硬件环境中启动的过程&#xff0c;使模型能够接收输入并返回预测结果。大模型的内存开销巨大&#xff0c;7B模型仅权重需要14G内存。另外大模型是自回归生成&#xff0c;需要缓存Attention的 k/v。 LMDeploy 简介 推理性…

UE5 UE4 打包报错Failed to compile material 解决

参考&#xff1a;https://forums.unrealengine.com/t/failed-to-compile-material-for-pcd3d_sm5-warning/385087 https://forums.unrealengine.com/t/failed-to-compile-material-for-platform-pcd3d-sm4/436176 报错&#xff1a;Failed to compile Material for platform PC…

基于Java SSM框架实现学生寝室管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现学生寝室管理系统演示 摘要 寝室管理设计是高校为学生提供第二课堂&#xff0c;而我们所在学院多采用半手工管理学生寝室的方式&#xff0c;所以有必要开发寝室管理系统来对进行数字化管理。既可减轻学院宿舍长工作压力&#xff0c;比较系统地对宿舍通告…

【C#】面向对象的三大特性,还记得吗,简单代码举例回顾

欢迎来到《小5讲堂》 大家好&#xff0c;我是全栈小5。 这是《C#》序列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识点的理解和掌握。…

如何学习three.js

如何学习three.js 前言1. 基础概念场景&#xff08;Scene&#xff09;&#xff1a; three.js中所有物体的容器。你可以把它想象成一个舞台&#xff0c;在这里添加物体、光源等。相机&#xff08;Camera&#xff09;&#xff1a; 决定了哪部分场景会被渲染。最常用的是透视相机&…

Parallel patterns: convolution —— An introduction to stencil computation

在接下来的几章中&#xff0c;我们将讨论一组重要的并行计算模式。这些模式是许多并行应用中出现的广泛并行算法的基础。我们将从卷积开始&#xff0c;这是一种流行的阵列操作&#xff0c;以各种形式用于信号处理、数字记录、图像处理、视频处理和计算机视觉。在这些应用领域&a…

超简单的node爬虫小案例

同前端爬取参数一样&#xff0c;输入三个参数进行爬取 注意点也一样&#xff1a; 注意分页的字段需要在代码里面定制化修改&#xff0c;根据你爬取的接口&#xff0c;他的业务规则改代码中的字段。比如我这里总条数叫total&#xff0c;人家的不一定。返回的数据我这里是data.r…