Has*_*yed 30 c++ lisp lua data-processing system-design
当前选择: lua-jit.令人印象深刻的基准测试,我已经习惯了语法.编写高性能ABI需要仔细考虑如何构建我的C++.
其他感兴趣的问题
背景
我正在研究一个实时高容量(复杂)事件处理系统.我有一个DSL,代表源的事件结构的模式,存储格式,某些特定于域的构造,触发内部事件(构造和驱动通用处理),以及编码始终发生的某些处理步骤.
DSL看起来非常类似于SQL,事实上我使用berkeley db(通过sqlite3接口)来长期存储事件.这里的重要部分是事件处理是基于集合完成的,就像SQL一样.然而,我得出结论,我不应该在DSL中添加通用处理逻辑,而是嵌入lua或lisp来处理这个问题.
处理核心是arround boost :: asio,它是多线程的,rpc是通过协议缓冲区完成的,事件是使用协议缓冲区IO库编码的 - 事件不是使用协议缓冲区对象构建的,它们只使用相同的编码/解码库.我将创建一个包含行的数据集对象,与数据库引擎在内存集中的存储方式非常相似.首先处理DSL中的处理步骤,然后将其呈现给通用处理逻辑.
无论我使用哪种可嵌入的脚本环境,我的处理核心中的每个线程都可能需要它自己的嵌入式语言环境(这就是lua至少在你做多线程工作时需要它的方式).
问题
目前的选择是在lisp ECL和lua之间.请记住,性能和吞吐量是一个强烈要求,这意味着非常需要最小化内存分配:
如果你在我的位置,你会选择哪种语言?
有没有我应该考虑的替代方案(不建议没有可嵌入实现的语言).Javascript v8也许吧?
lisp更适合这个领域吗?我不认为lua和lisp在它们提供的方面有所不同.叫我出去:D
我应该考虑其他任何属性(如下所示)吗?
我断言任何形式的嵌入式数据库IO(请参阅下面的示例DSL以获取上下文)使脚本语言调用在数量级上相形见绌,并且选择这两者不会给总体吞吐量增加太多开销.我是在正确的轨道上吗?:d
期望的属性
我想将我的数据集映射到lisp列表或lua表,我想最小化冗余数据副本.例如,如果两个表具有相同的形状,则从一个数据集向另一个数据集添加行应尝试使用引用语义.
我可以保证在我进行lua/lisp调用时,作为输入传递的数据集不会改变.我希望lua和lisp在可能的情况下强制不改变数据集.
在嵌入式调用结束后,应该销毁数据集,创建的任何引用都需要用副本替换(我猜).
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);
}
}
Run Code Online (Sandbox Code Playgroud)
该项目是博士研究项目的一个组成部分,是/将是自由软件.如果您有兴趣与我合作(或参与)此项目,请发表评论:D
sno*_*rpe 32
我非常同意@ jpjacobs的观点. Lua是嵌入的绝佳选择,除非你需要一些非常具体的lisp(例如,如果你的数据特别好地映射到cons-cells).
我已经使用lisp很多年了,BTW,我非常喜欢lisp语法,但是现在我通常会选择Lua.虽然我喜欢lisp 语言,但我还没有找到一个lisp 实现,它以Lua的方式捕获嵌入式使用的功能/小/可用性的完美平衡.
Lua:
非常小,源和二进制,比许多更流行的语言(Python等)小一个数量级或更小.因为Lua源代码非常简单,所以如果要避免添加外部依赖项,只需在源代码树中包含整个Lua实现是完全合理的.
很快.Lua解释器比大多数脚本语言快得多(同样,一个数量级并不罕见),LuaJIT2是一个非常好的JIT编译器,适用于一些流行的CPU架构(x86,arm,mips,ppc).使用LuaJIT通常可以将速度提高一个数量级,并且在许多情况下,结果接近C的速度.LaaJIT也是标准Lua 5.1的"插入式"替代品:不需要应用程序或用户代码更改用它.
有LPEG.LPEG是Lua的"解析表达式语法"库,它允许非常简单,强大和快速的解析,适用于大型和小型任务; 它是yacc/lex/hairy-regexps的绝佳替代品.[我使用LPEG和LuaJIT编写了一个解析器,它比我尝试模拟的yacc/lex解析器快得多,并且非常容易和直接创建.] LPEG是Lua的附加包,但很好-worth getting(这是一个源文件).
有一个很棒的 C接口,很高兴从C调用Lua,或者从Lua调用C语言.对于大型/复杂C++库的接口,可以使用SWIG或许多接口生成器中的任何一个(当然也可以使用Lua的简单C接口和C++).
拥有自由许可("BSD-like"),这意味着如果您愿意,Lua可以嵌入到专有项目中,并且与FOSS项目的GPL兼容.
非常,非常优雅.它不是lisp,因为它不是基于cons-cells,但它显示了来自方案等语言的明显影响,具有直接且有吸引力的语法.就像方案一样(至少在它的早期版本中),它倾向于"最小化",但在可用性方面做得很好.对于那些具有lisp背景的人(像我一样!),尽管存在差异,但很多关于Lua的内容似乎很熟悉,并且"有意义".
非常灵活,metatables等功能可以轻松集成特定于域的类型和操作.
具有简单,有吸引力且易于理解的语法.对于现有的lisp用户而言,这可能不是lisp的优势,但如果您打算让最终用户编写脚本,则可能是相关的.
专为嵌入而设计,除了体积小,速度快外,还具有各种功能,例如增量GC,使得在这种情况下使用脚本语言更加可行.
拥有悠久的历史,以及负责任和专业的开发人员,他们在过去二十年中如何演变语言方面表现出良好的判断力.
拥有一个充满活力和友好的用户社区.