3

比如说,如果我有一个 Lisp 程序,它使用(eval 'sym)并在其符号表中查找它,它实际上是否比aClass.getField("sym", anInstance)“静态”语言中的性能更好?

4

3 回答 3

2

一般来说(模实现问题,如字节码与本机代码或代码生成质量),具有元语言抽象的语言提供了更多的能力来创建程序,这些程序的性能优于可以在可比时间范围内创建的程序,而缺乏这种抽象的语言。情况是,当您为自己的语言编写实现时,您有更多信息可以进行比基础语言编译器更强大的优化。在实践中有很多这样的例子。

此外,您似乎将反射(作为“开放实现”的特例)和元语言抽象混合在一起。元语言抽象是关于在基础语言之上构建新语言,反射(或“开放实现”)是将程序的内部暴露给程序本身。

在您的特定示例中(当然,模块实现问题,如字节码与本机代码或代码生成质量),(eval 'sym)可能更快。原因是它'sum是一个符号对象而不是字符串。评估符号意味着获取其值单元格。所以 eval 只需要做几件事:

  1. 在对象类型上调度(在这种情况下 - 一个符号)(例如,通过使用值标签来遍历跳转表)
  2. 提取符号的值(通过取消引用符号结构)

但 Java 示例还有更多工作要做:

  1. 查找给定名称的字段。这需要例如计算字符串的哈希值并使用哈希表
  2. 提取字段的值(通过在特定于字段的偏移量处取消引用实例指针)
  3. 将值装箱(如果它不是参考)

特别昂贵的部分是计算哈希并通过哈希表。

于 2009-10-13T18:34:53.533 回答
2

这个问题没有很好地提出,部分原因是这两种方法并不相互排斥。

举个例子,Common Lisp 提供EVAL.

Common Lisp 还提供了许多反射功能,允许您查看包中的符号、按名称查找(全局)变量的值、按名称构造类的实例、查找或设置类中槽的值或调用函数根据他们的名字。通过广泛实施(尽管非 ANSI 标准)的 CLOS 元对象协议,您可以根据它们的名称找到更多关于类和泛型函数的信息。

当然,比较语言性能而不是实现的问题仍然存在。自然地,被编译为本机代码的 Common Lisp 将与被解释的 Common Lisp 执行完全不同,并且大多数 CL 实现允许您混合编译和解释代码(尽管少数只提供编译器)。

于 2009-10-13T16:16:42.477 回答
2

这取决于语言的实现。

绝对没有理由说明 aClass.getField("sym", anInstance) 不应该与 eval 完全一样。

另一方面,即使在实际实现中,速度也有很大不同。例如,在 .Net 中有慢反射方法和快速反射方法(通常快 100 倍甚至更多)。您需要哪一个在很大程度上取决于您实际想要使用该方法做什么。您只想读取一个值吗?改变一个值?安全相关吗?

于 2009-10-13T13:38:22.140 回答