【发布时间】:2022-01-04 00:40:24
【问题描述】:
Dart 允许循环导入。
我的一般理解是循环导入(文件 a 导入文件 b,文件 b 导入文件 a)是一种不好的做法,通常是放手资源和垃圾收集。然而,飞镖甚至没有警告,所以我想知道它是否会导致不良行为。
是否对垃圾回收有影响。会导致问题吗?
【问题讨论】:
标签: dart
Dart 允许循环导入。
我的一般理解是循环导入(文件 a 导入文件 b,文件 b 导入文件 a)是一种不好的做法,通常是放手资源和垃圾收集。然而,飞镖甚至没有警告,所以我想知道它是否会导致不良行为。
是否对垃圾回收有影响。会导致问题吗?
【问题讨论】:
标签: dart
循环导入还不错。
Dart 的循环导入与垃圾回收无关。这一切都是为了让 names 在编译时对其他库可用。
运行时数据结构中的循环可以使对象保持活动状态(但是,与其他一些语言不同,只要循环中没有对任何对象的外部引用,Dart 的垃圾收集就可以收集整个循环)。
库在运行时不是数据结构,它们只在编译时才真正存在。
无论如何,所有导入的库都存在于程序中。如果程序使用库 A,而库 A 导入库 B,那么这两个库都将成为程序的一部分(它们的各个成员可能会或可能不会被树摇晃,具体取决于它们是否实际使用,但这与库依赖项。)
如果库 B 也导入库 A,则不会有任何改变。这两个库仍然是该计划的一部分。它所做的只是允许库 B 的成员引用库 A 的成员声明。
循环依赖确实会影响高效的模块化编译。 为了编译一个库,你还需要编译它的所有依赖项(至少在某种程度上,包括类型推断),否则你无法检查该库是否正确使用了它的依赖项。
如果您有一个单向依赖项,那么您可以(可能)在开始查看导入它的库之前完全编译该依赖项。有时构建系统甚至允许一个库被编译一次,然后在依赖它的多个其他程序中重用。
如果你在库依赖中有一个循环,那么模块化编译器需要在同一个编译步骤中编译该循环的所有库,因为它们中的任何一个都不能先于其他编译。 因此,对于模块化的 Ahead-of-Time 编译器,周期会影响模块化编译的粒度。 我建议避免跨越多个包的循环。 在一个单独的包装内,完全没问题。
在运行时仍然没有区别。
【讨论】:
Dart 使用循环导入来支持多次处理源代码以创建中间代码的多通道编译器。 Dart VM 还支持使用此中间代码的即时编译和提前编译。
JIT 编译器在执行前将源代码转换为本机机器码,以提高性能速度和运行时间。它也用于 Java。
AOT 编译器强制执行 Dart 使用的类型系统,并使用快速对象分配和支持这些循环导入的分代垃圾收集器来管理内存。当您的应用程序准备好部署到生产环境时使用它。它在将代码交付到任何运行它的运行时环境之前对其进行编译。
【讨论】:
实际上我经常这样做,但从未引起任何问题。
编辑:这很好地回答了这个问题: Dart - Circular imports
【讨论】: