Lua与嵌入式Lisp以及其他可能的候选方案相比较,用于集合数据处理。

当前选择:lua-jit。令人印象深刻的基准测试,我已经习惯了语法。编写高性能ABI将需要谨慎考虑如何构建我的C++。

其他感兴趣的问题

  1. Gambit-C和Guile作为可嵌入的语言
  2. Lua性能技巧(有禁用收集器的选项,并且始终可以在处理运行结束时调用收集器)。

背景

我正在开发一个实时高容量(复杂)事件处理系统。我有一个DSL,表示事件结构的模式,存储格式,某些特定于域的结构,发射内部事件(以结构和驱动通用处理为例),以及编码始终发生的某些处理步骤。

DSL看起来与SQL非常相似,事实上,我使用berkeley db(通过sqlite3接口)长期存储事件。_这里重要的是事件处理是基于集合的,就像SQL一样。_但是,我得出结论,不应将通用处理逻辑添加到DSL中,而是嵌入lua或lisp来处理此问题。

处理核心基于boost::asio构建,支持多线程,rpc通过协议缓冲区完成,事件使用协议缓冲器IO库进行编码 - 即事件不使用协议缓冲器对象进行结构化,只是使用相同的编码/解码库。我将创建一个包含行的数据集对象,与数据库引擎类似,将在内存中存储集合。DSL中的处理步骤将首先由通用处理逻辑处理,然后再呈现。

无论我使用什么可嵌入脚本环境,我的处理核心中的每个线程都可能需要自己的嵌入式语言环境(如果您正在执行多线程工作,那就是lua要求的)。

问题

目前的选择是lisp ECL和lua。牢记性能和吞吐量是一个强烈的要求,这意味着尽可能减少内存分配是非常希望的:

  1. 如果您处于我的位置,您会选择哪种语言?

  2. 是否有其他选择要考虑(不建议没有可嵌入实现的语言)。Javascript v8呢?

  3. lisp是否更适合该域?我认为lua和lisp在提供什么方面方面不太相同。叫我出去:D

  4. 还应考虑其他属性(例如下面提到的属性)吗?

  5. 我断言,任何形式的嵌入式数据库IO(请参见下面的DSL示例以获取上下文)都是脚本语言呼叫的数量级,选择任何一个都不会对总吞吐量添加太多开销。我走在正确的道路上吗? :D

期望的属性

  1. 我希望将我的数据集映射到lisp列表或lua表中,我希望最小化冗余数据拷贝。例如,如果两个表具有相同的形状,则将一行从一个数据集添加到另一个数据集应尝试使用引用语义。

  2. 我可以保证传递作为输入的数据集在我进行lua/lisp调用时不会更改。如果可能,我希望lua和lisp也强制不更改数据集。

  3. 嵌入式调用结束后,数据集应该被销毁,创建的任何引用都需要被替换为拷贝(我猜)。

DSL示例

我附上DSL供您观看,以便您了解我正在努力实现的内容。注意:DSL不显示通用处理。

// Derived Events : NewSession EndSession
NAMESPACE WebEvents
{
  SYMBOLTABLE DomainName(TEXT) AS INT4;
  SYMBOLTABLE STPageHitId(GUID) AS INT8;
  SYMBOLTABLE UrlPair(TEXT hostname ,TEXT scriptname) AS INT4;
  SYMBOLTABLE UserAgent(TEXT UserAgent) AS INT4;

  EVENT 3:PageInput
  {
    //------------------------------------------------------------//
    REQUIRED 1:PagehitId              GUID
    REQUIRED 2:Attribute              TEXT;
    REQUIRED 3:Value                  TEXT;

    FABRRICATED 4:PagehitIdSymbol     INT8;
    //------------------------------------------------------------//

    PagehitIdSymbol AS PROVIDED(INT8 ph_symbol)
                    OR Symbolise(PagehitId) USING STPagehitId;
  }

  // Derived Event : Pagehit
  EVENT 2:PageHit
  {
    //------------------------------------------------------------//
    REQUIRED 1:PageHitId              GUID;
    REQUIRED 2:SessionId              GUID;
    REQUIRED 3:DateHit                DATETIME;
    REQUIRED 4:Hostname               TEXT;
    REQUIRED 5:ScriptName             TEXT;
    REQUIRED 6:HttpRefererDomain      TEXT;
    REQUIRED 7:HttpRefererPath        TEXT;
    REQUIRED 8:HttpRefererQuery       TEXT;
    REQUIRED 9:RequestMethod          TEXT; // or int4
    REQUIRED 10:Https                 BOOL;
    REQUIRED 11:Ipv4Client            IPV4;
    OPTIONAL 12:PageInput             EVENT(PageInput)[];

    FABRRICATED 13:PagehitIdSymbol    INT8;
    //------------------------------------------------------------//
    PagehitIdSymbol AS  PROVIDED(INT8 ph_symbol)
                    OR  Symbolise(PagehitId) USING STPagehitId;

    FIRE INTERNAL EVENT PageInput PROVIDE(PageHitIdSymbol);
  }

  EVENT 1:SessionGeneration
  {
    //------------------------------------------------------------//
        REQUIRED    1:BinarySessionId   GUID;
    REQUIRED    2:Domain            STRING;
    REQUIRED    3:MachineId         GUID;
    REQUIRED    4:DateCreated       DATETIME;
    REQUIRED    5:Ipv4Client        IPV4;
    REQUIRED    6:UserAgent         STRING;
    REQUIRED    7:Pagehit           EVENT(pagehit);

    FABRICATED  8:DomainId          INT4;
    FABRICATED  9:PagehitId         INT8;
    //-------------------------------------------------------------//

    DomainId  AS SYMBOLISE(domain)            USING DomainName;
    PagehitId AS SYMBOLISE(pagehit:PagehitId) USING STPagehitId;

    FIRE INTERNAL EVENT pagehit PROVIDE (PagehitId);
  }
}

此项目是博士研究项目的组成部分,是/将成为免费软件。如果您有兴趣与我一起(或为此项目做出贡献),请发表评论:D

原文链接 https://stackoverflow.com/questions/7919763

点赞
stackoverflow用户513763
stackoverflow用户513763

您没有提供使用的平台,但如果您的平台能够使用LuaJIT 2,我肯定会选择它,因为执行速度接近编译代码,并且使用FFI库与C代码的接口更容易。

我不知道其他可嵌入的脚本语言,所以我无法真正比较它们能做什么以及它们如何与表格一起工作。

Lua主要使用引用:所有函数、用户数据、表格都通过引用使用,并且在没有对数据的引用时,它们将在下一次gc运行时进行收集。 字符串被内部化,因此某个字符串仅在内存中出现一次。 需要考虑的一点是,应该避免创建并随后丢弃大量的表格,因为这可能会减慢GC循环(正如您引用的Lua gem中所解释的那样)。

对于解析您的代码示例,我建议看看LPEG库。

原文链接:https://stackoverflow.com/questions/20514957/fastest-and-secure-scripting-language-for-embedding-in-c-program

2011-10-28 08:05:21
stackoverflow用户293147
stackoverflow用户293147

有几种选项可供实现高性能的嵌入式编译器。其中一种是Mono VM,它自然地带有几十个已经实现在其之上的高质量语言,并且它相当可嵌入(看看Second Life如何使用它)。也可以使用LLVM-看起来你的DSL不太复杂,因此实现一个特制编译器不会是什么大问题。

2011-10-28 09:17:35
stackoverflow用户284969
stackoverflow用户284969

我非常赞同 @jpjacobs 的观点。Lua 是一个非常好的嵌入式语言选择,除非你有非常特殊的需要(例如,如果你的数据特别适合 cons-cell 映射)。

顺便说一下,我用 Lisp 已经很多年了,我非常喜欢 Lisp 的语法,但是现在我通常会选择 Lua。虽然我喜欢 Lisp 的语言,但是我还没有找到一个 Lisp 实现能够像 Lua 一样完美地平衡了功能、小巧和易用性。

Lua

  1. 非常小巧,无论是源代码还是二进制代码,都比许多更受欢迎的语言(例如 Python 等)要小一个数量级或更多。由于 Lua 的源代码非常小和简单,如果你想避免添加外部依赖,则完全可以将整个 Lua 实现包含在你的源代码树中。

  2. 非常快。Lua 解释器比大多数脚本语言快很多(再次提醒,常常会比其它脚本语言快一个数量级),LuaJIT2 是一个非常好的 JIT 编译器,可用于一些流行的CPU体系结构(例如 x86、arm、mips、ppc)。使用 LuaJIT 可以将速度提高一倍,而且在许多情况下,结果接近于 C 的速度。LuaJIT 也是标准 Lua 5.1 的 "drop-in" 替换:使用它不需要进行任何应用程序或用户代码的更改。

  3. LPEG。LPEG 是一个 "Parsing Expression Grammar" 库,适用于大型和小型任务,允许非常简单、强大和快速的解析;它是 yacc/lex/hairy-regexps 的很好替代品。[我使用 LPEG 和 LuaJIT 编写了一个解析器,比我试图模拟的 yacc/lex 解析器快得多,并且非常容易和直接进行创建。] LPEG 是 Lua 的一个附加包,但是值得获取(它只有一个源文件)。

  4. 有一个伟大的 C 接口,使得从 C 调用 Lua 或从 Lua 调用 C 更加愉快。为了接口大型/复杂的 C++ 库,可以使用 SWIG 或任何一个接口生成器(当然,也可以只使用 Lua 的简单 C 接口与 C++ 进行交互)。

  5. 拥有自由许可证("类似于 BSD"),这意味着如果你愿意,Lua 可以被嵌入专有项目中,并且对于 FOSS 项目,它与 GPL 兼容。

  6. 非常优雅。它并不是 Lisp,因为它不是基于 cons-cell,但是它展示了诸如 Scheme 等语言的明显影响,具有简单而具有吸引力的语法。与 Scheme (至少在早期版本中)类似,它趋向于 "极简主义",但是很好地平衡了可用性。对于有 Lisp 背景(像我一样!)的人来说,Lua 中的很多内容都会很熟悉,尽管存在差异。

  7. 非常灵活,例如元表等功能可以轻松地集成领域特定类型和操作。

  8. 有一个简单、具有吸引力和易于接近的语法。如果你打算让最终用户编写脚本,这可能并不比 Lisp 对现有 Lisp 用户有什么优势,但可能与他们相关。

  9. 专为嵌入式而设计,并且除了其小巧和快速的特点外,还具有各种功能,例如增量 GC,使得在这种上下文中使用脚本语言更加可行。

  10. 有着悠久的历史,并且有负责任和专业的开发人员,在过去的二十年中展示了良好的判断力。

  11. 拥有一个充满活力和友好的用户社区。

2011-10-28 09:54:48
stackoverflow用户1014082
stackoverflow用户1014082

我偶然地参与了一个类似于你的项目的开发,它是一个跨平台的系统,可以在Win-CE,Android和iOS上运行。我需要最大化交叉平台的代码,C / C ++结合可嵌入语言是一个很好的选择。这是我的解决方案,与你的问题有关。

  1. 如果你处于我的位置,你会选择哪种语言?

我项目中的DSL与你的相似。为了性能,我使用了Yacc / Lex编写了一个编译器,用于将DSL编译为二进制文件以供运行,并编写了一堆API来从二进制文件中获取信息。但是,当DSL语法中有任何修改时,修改编译器和API都非常麻烦。因此,我弃用了DSL,转而使用XML(不要直接编写XML,定义良好的模式是值得的),我编写了一个通用编译器将XML转换为lua表,使用lua重新实现了API。这样做可以获得两个好处:可读性和灵活性,而且没有明显的性能降低。

  1. 是否有其他备选方案需要考虑(不建议建议没有可嵌入实现的语言)。Javascript v8是个选择吗?

选择lua之前,我考虑了嵌入式Ch(主要用于工业控制系统)、嵌入式Lisp和lua,最终lua脱颖而出,因为lua与C很好地集成在一起,拥有繁荣的社区,对于其他团队成员学习也很容易。关于Javascript v8,如果在嵌入式实时系统中使用,就像用蒸汽锤打碳化的坚果,过于浪费。

  1. Lisp是否更适合该领域?我认为lua和lisp在提供的功能方面并没有多大区别。指出我的不足之处:D

对于我的领域,Lisp和lua在语义上具有相同的能力,它们都可以轻松处理基于XML的DSL,甚至可以编写一个简单的编译器将XML转换为lisp列表或lua表。它们都可以轻松处理领域逻辑。但是lua与C / C ++更好地集成在一起,这也是lua的目标。

  1. 是否有其他与以下属性类似的属性应该考虑?

独自工作或与团队成员合作也是解决方案选择的权重因素。如今,熟悉类似于Lisp的语言的程序员并不多。

  1. 我认为任何形式的嵌入式数据库IO(请参见下面的示例DSL以获取上下文)都会使脚本语言的调用远远超出,选择哪个将不会给整体吞吐量增加太多开销。我的想法正确吗?:D

这里是编程语言性能列表,这里是计算机组件访问时间列表。如果您的系统受IO限制,则脚本的开销不是关键因素。我的系统是一个O&M(运营和维护)系统,脚本性能微不足道。

2013-11-18 15:34:01