代码之家  ›  专栏  ›  技术社区  ›  Chandu

DSL或Java Fluent API设计是否影响应用程序性能?

  •  2
  • Chandu  · 技术社区  · 10 年前

    如果我使用内部DSL(特定领域语言)或外部DSL(特定域语言)或流畅的API设计模式设计应用程序,是否会降低应用程序性能?

    2 回复  |  直到 10 年前
        1
  •  2
  •   Ira Baxter    10 年前

    外部DSL可以带来比内部DSL更好的性能和可用性。

    DSL的目的是让工程师简洁明了地指定问题或解决方案,这样他就能更快、更有效地解决问题。

    在某种程度上,问题不需要高性能,人们可以从一组子程序中构建一个内部DSL,并简单地调用它们来实现所需的效果。有理由注意到,大多数计算并不昂贵,因此是关于“过早优化”的标准警告。

    然而,许多DSL 需要高性能(SQL、专家系统、lexer和解析器生成器)。这些解决方案通常需要复杂的算法(解析、名称解析、流分析、布尔方程构造/简化)来分析工程师提供的DSL规范实例,然后应用特殊的算法(模式匹配、FSA构造、Rete网络),也许还有复杂的代码生成和优化(查询优化、特殊情况处理、代码运动、代数简化),以产生有效的答案。在这种情况下,内部DSL在很大程度上是一场灾难,因为很难仅对API调用进行推理,而不对与过程相关的其他语言进行推理。也很难找到DSL规范实例的边界;它在哪里结束,而仅仅是普通的编程结束?

    总的来说,我认为“外部”DSL,那些具有特殊符号(无论是文本还是图形)的DSL更容易编写(然后阅读)。在某些情况下,如果没有符号,就无法实现DSL(考虑LR解析器生成器或Rete网络;手工编写代码并不实用,您必须拥有外部DSL和支持工具)。如果目的是让工程师能够多次解决问题,我相信可读性和表达力是您应该优化的,而不是易于实现的。SQL比任何一堆数据库表访问过程都容易读取。这也是维护的胜利;如果DSL取得任何成功,人们将希望更改他们指定的内容。外部DSL的缺点是必须为其设计一个像样的规范符号,这可能不容易做到,或者在领域设计者的技能范围内,并且支持DSL的构建工具通常被认为是困难的。(查看我的简历,我有后者的答案)。

    内部DSL的唯一好理由是它不会被使用很多次,因此设计相应的规范语言或支持工具并不值得。这让我对所提出的DSL的实际效用感到疑惑。

        2
  •  0
  •   Joop Eggen    10 年前

    一个小参数_内部DSL (如果进展太快,请投票。)

    内部DSL

    内部DSL以类型安全的方式解释模型,并且通常使用语义检查。自动完成也有帮助。因此,如果不是应用程序性能,它有利于软件质量,也就是开发性能。

    现在,一个好的DSL由构建器类组成,这些类构造单独定义的模型。最终的评估结果可以“汇编”

    Java在正则表达式Pattern/Matcher中使用了这一点 Pattern.compile/matcher 。在没有真正的DSL的地方,还需要内部正则表达式模型的构建器。

    概括地说,模型是从哪里构建的,它也可以“编译”。有时热点编译器也会出现。

    外部DSL

    但是外部DSL可以预编译为更直接的代码,从而省去了内部DSL的编译和优化。你不能那么容易地遵循代码、数据模型和优化。DSL的一些工作必须涉及语法着色/语法错误/自动完成。此外,外部DSL编译器的产生可能更多的是数据而不是代码。“装载机”部分也必须很快。

    内部DSL的开销: 以及需要考虑的问题。

    流畅的API和立即构建模型之间的开销不大。经常 return this; 对于链式调用,最好在 final (不可重写)方法,因此编译器可以立即进行优化,而不是依赖于热点编译器的检测。语义检查是不可避免的开销:错误是有问题的,无需隐藏。如果它们导致代码迭代,则您正在构建的数据结构可能是错误的(=使用映射)。所以开销应该足够小。

    我个人的结论是DSL对开发有益,而且速度足够快。通常下一步是有问题的一步。jOOQ罚款,JPA标准API罚款,ORM有一些问题。与Java 8相同,lambdas。看到它们被用作DSL,很有意思,但这可能太过间接、过度。

    目前,DSL只应用于两个领域:技术接口,如java+SQL,但实际上并不需要它。以及业务逻辑,开发人员有时会将编程、版本控制、登台等方面的责任转移给最终客户。(更改了对生命系统、表单编辑器立即生效的业务规则。)这些业务DSL的效率取决于系统背后有一个复杂的语义模型,如数据库引擎。效率低下是由于声明性/程序性不匹配造成的。

    这个 合一 跨代码语言的复杂性可能会部分加深;Java+SQL:Java将Java存储过程传递给SQL。也许向量处理也是如此。

    附笔。

    .NET有一些跨/混合语言编译器的努力(我认为讽刺)来生成令牌流、AST并从那里开始。