具有元语言抽象的语言是否比仅使用反射 API 的语言表现更好?

发布于 2024-08-07 19:31:21 字数 143 浏览 7 评论 0原文

比如说,如果我有一个 Lisp 程序,它使用 (eval 'sym) 并在其符号表中查找它,它实际上比 aClass.getField("sym" 之类的东西执行得更好吗? , anInstance) 在“静态”语言中?

Say, if I have a Lisp program, which uses (eval 'sym) and looks it up in its symbol-table does it actually perform better than something like aClass.getField("sym", anInstance) in "static" languages?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

过潦 2024-08-14 19:31:21

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

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

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

  1. 分派对象类型(在本例中为符号)(例如,通过使用值标记来遍历跳转表)
  2. 提取符号的值(通过取消引用符号结构)

但是 Java 示例有更多要做的事情:

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

特别昂贵的部分是计算散列并遍历散列表。

In general (modulo implementation issues like bytecode vs native code or code generation quality), languages with metalinguistic abstraction provide more power to create programs that outperform programs that can be created in comparable timeframe with language that lacks such abstractions. The case is that when you write an implementation for your own language, you have more information to make much more powerful optimizations than compiler for base language can do. There are numerous examples of this in practice.

Also, you seem to mix together the reflection (being a particular case of 'open implementation') and metalinguistic abstraction. Metalinguistic abstraction is about building new languages on top of base languages and reflection (or 'open implementation') is about exposing program's internals to the program itself.

In your particular example (of course, module implementation issues like bytecode vs native code or code generation quality), (eval 'sym) is probably faster. The reason is that 'sum is a symbol object and not a string. Evaluating a symbol means taking its value cell. So eval has to do only several things:

  1. Dispatch on an object type (in this case - a symbol) (e.g., by using a value tag to go through jump table)
  2. Extract symbol's value (by dereferencing a symbol structure)

But Java example has more things to do:

  1. Find a field given its name. This requires e.g. calculating a hash of a string and using hashtable
  2. Extract the field's value (by dereferencing instance pointer at an offset specific to field)
  3. Box the value (if it's not a reference)

The particulary expensive part is calculating the hash and going through hashtable.

半世蒼涼 2024-08-14 19:31:21

这取决于语言的实现。

绝对没有理由为什么 aClass.getField("sym", anInstance) 不应该与 eval 完全相同。

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

It depends on the implementation of a language.

There is absolutely no reason why e.g. the aClass.getField("sym", anInstance) should not no exactly the same as an eval does.

On the other hand even WITHIN actual implementations the speed is hugely different. E.g. in .Net there are slow reflection methods and fast ones (often 100 times and more faster). And which one you need depends for the most part on what you actually want to do with the method. Do you want to just read a value? Change a value? Is security relevant?

凤舞天涯 2024-08-14 19:31:21

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

举个例子,Common Lisp 提供了EVAL

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

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

The question is not well posed, in part because the two approaches are not mutually exclusive.

Just as an example, Common Lisp provides EVAL.

Common Lisp also provides a number of reflective capabilities, allowing you to see what symbols are in a package, find values of (global) variables by name, construct instances of classes by name, find or set values of slots in classes, or call functions based on their name. With the widely implemented (though non-ANSI standard) CLOS Meta-Object Protocol, you can find out even more about classes and generic functions based on their names.

Of course, the problem of comparing the performance of languages instead of implementations remains. Naturally Common Lisp that has been compiled to native code will perform quite differently than Common Lisp that is being interpreted, and most CL implementations allow you to mix compiled and interpreted code (though a few only provide compilers).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文