c++ - code - Lua vs Embedded Lisp y otros candidatos potenciales. para el procesamiento de datos basado en conjunto
code lua (4)
Elección actual: lua-jit. Impresionantes puntos de referencia, me estoy acostumbrando a la sintaxis. Escribir un ABI de alto rendimiento requerirá una cuidadosa consideración sobre cómo estructuraré mi C ++.
Otras preguntas de interés
- Gambit-C y Guile como lenguajes integrables
- Sugerencias de rendimiento de Lua (tiene la opción de ejecutarse con un recopilador deshabilitado y llamar al recopilador al final de una o varias ejecuciones de procesamiento siempre es una opción).
Fondo
Estoy trabajando en un sistema de procesamiento de eventos de gran volumen (complejo) en tiempo real. Tengo un DSL que representa el esquema de la estructura de eventos en la fuente, el formato de almacenamiento, ciertas construcciones específicas del dominio, la activación de eventos internos (para estructurar y controlar el procesamiento de propósito general) y la codificación de ciertos pasos de procesamiento que siempre suceden.
El DSL se ve bastante similar al SQL, de hecho, estoy usando berkeley db (a través de la interfaz sqlite3) para el almacenamiento a largo plazo de eventos. La parte importante aquí es que el procesamiento de eventos se realiza en base a conjuntos, como SQL . Sin embargo, he llegado a la conclusión de que no debo agregar lógica de procesamiento de propósito general al DSL, y más bien incrustar lua o lisp para cuidar de esto.
El núcleo de procesamiento se construye alrededor de boost :: asio, es multiproceso, rpc se realiza a través de búferes de protocolo, los eventos se codifican utilizando la biblioteca de E / S del búfer de protocolo, es decir, los eventos no se estructuran utilizando el objeto de búfer de protocolo, solo usan la misma codificación / biblioteca de decodificación. Crearé un objeto de conjunto de datos que contiene filas, bastante similar a cómo un motor de base de datos almacena en conjuntos de memoria. los pasos de procesamiento en el DSL serán atendidos primero y luego presentados a la lógica de procesamiento de propósito general.
Independientemente de qué entorno de secuencias de comandos integrable use, cada subproceso en mi núcleo de procesamiento probablemente necesitará su propio entorno de lenguaje incrustado (así es como lua requiere que sea al menos si está trabajando en múltiples subprocesos).
Las preguntas)
La elección en este momento es entre lisp ECL y lua. Teniendo en cuenta que el rendimiento y el rendimiento es un requisito importante, esto significa que minimizar las asignaciones de memoria es altamente deseado:
Si estuvieras en mi posición, ¿qué idioma elegirías?
¿Hay alguna alternativa que deba considerar (no sugiera idiomas que no tengan una implementación incorporable)? Javascript v8 tal vez?
¿Lisp se ajusta mejor al dominio? No creo que lua y lisp sean tan diferentes en términos de lo que proporcionan. Llamame: D
¿Hay otras propiedades (como las de abajo) en las que debería estar pensando?
Afirmo que cualquier forma de IO de base de datos incrustada (vea el ejemplo de DSL a continuación para el contexto) empequeñece la llamada del lenguaje de scripting en órdenes de magnitud, y que la selección tampoco agregará mucha sobrecarga al rendimiento general. ¿Estoy en el camino correcto? :RE
Propiedades deseadas
Me gustaría asignar mi conjunto de datos en una lista clara o tabla lua y me gustaría minimizar las copias de datos redundantes. Por ejemplo, agregar una fila de un conjunto de datos a otro debe tratar de usar la semántica de referencia si ambas tablas tienen la misma forma.
Puedo garantizar que el conjunto de datos que se pasa como entrada no cambiará mientras haya realizado la llamada lua / lisp. Quiero que lua y lisp hagan cumplir, sin alterar el conjunto de datos, si es posible.
Después de que el final de la llamada incrustada se destruyan los conjuntos de datos, cualquier referencia creada deberá reemplazarse con copias (supongo).
Ejemplo de DSL
Adjunto un DSL para su placer de visualización para que pueda hacerse una idea de lo que estoy tratando de lograr. Nota: El DSL no muestra el procesamiento de propósito general.
// 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);
}
}
Este proyecto es un componente de un proyecto de investigación Ph.D. y es / será software libre. Si está interesado en trabajar conmigo (o contribuir) en este proyecto, deje un comentario: D
Estoy totalmente de acuerdo con los puntos de @ jpjacobs. Lua es una excelente opción para incrustación, a menos que haya algo muy específico sobre el ceceo que necesite (por ejemplo, si sus datos se corresponden especialmente con celdas cons).
He usado lisp durante muchos años, por cierto, y me gusta bastante la sintaxis de Lisp, pero en estos días generalmente elegía a Lua. Aunque me gusta el lenguaje lisp, aún no he encontrado una implementación de lisp que capture el maravilloso equilibrio de características / pequeñez / usabilidad para uso integrado como lo hace Lua.
Lua :
Es muy pequeño, tanto fuente como binario, un orden de magnitud o más pequeño que muchos lenguajes más populares (Python, etc.). Debido a que el código fuente de Lua es tan pequeño y simple, es perfectamente razonable incluir toda la implementación de Lua en su árbol fuente, si desea evitar agregar una dependencia externa.
Es bien rapido. El intérprete de Lua es mucho más rápido que la mayoría de los lenguajes de scripting (una vez más, un orden de magnitud no es raro), y LuaJIT2 es un muy buen compilador de JIT para algunas arquitecturas populares de CPU (x86, arm, mips, ppc). El uso de LuaJIT a menudo puede acelerar las cosas en otro orden de magnitud, y en muchos casos, el resultado se aproxima a la velocidad de C. LuaJIT también es un reemplazo "de reemplazo" para Lua 5.1 estándar: no se requieren cambios de aplicación o código de usuario para usarlo
Tiene LPEG . LPEG es una biblioteca de "Gramática de expresión de análisis" para Lua, que permite un análisis muy fácil, potente y rápido, adecuado tanto para tareas grandes como pequeñas; es un gran reemplazo para yacc / lex / hairy-regexps. [Escribí un analizador usando LPEG y LuaJIT, que es mucho más rápido que el analizador yacc / lex que estaba intentando emular, y fue muy fácil y directo de crear.] LPEG es un paquete adicional para Lua, pero está bien -decidiendo (es un archivo fuente).
Tiene una gran interfaz C, lo que hace un placer llamar a Lua desde C, o llamar a C desde Lua. Para la interconexión de bibliotecas C ++ grandes / complejas, se puede usar SWIG, o cualquiera de una serie de generadores de interfaz (también se puede usar la interfaz C simple de Lua con C ++, por supuesto).
Tiene licencias liberales ("similar a BSD"), lo que significa que Lua puede integrarse en proyectos propietarios si así lo desea, y es compatible con GPL para proyectos de software libre.
Es muy, muy elegante. No es lisp, ya que no se basa en cons-cells, pero muestra claras influencias de lenguajes como esquema, con una sintaxis directa y atractiva. Al igual que el esquema (al menos en sus encarnaciones anteriores), tiende a ser "mínimo" pero hace un buen trabajo al equilibrar eso con la usabilidad. Para alguien con un historial de lisp (¡como yo!), Muchas cosas sobre Lua le parecerán familiares y "tendrán sentido", a pesar de las diferencias.
Es muy flexible, y características como los metatables permiten integrar fácilmente tipos y operaciones específicas de dominio.
Tiene una sintaxis simple, atractiva y accesible. Esto podría no ser una ventaja sobre el lisp para los usuarios de lisp existentes, pero podría ser relevante si pretendes que los usuarios finales escriban scripts.
Está diseñado para incrustación, y además de su pequeño tamaño y velocidad, tiene varias características tales como un GC incremental que hace que el uso de un lenguaje de guiones sea más viable en dichos contextos.
Tiene una larga historia, y desarrolladores responsables y profesionales, que han demostrado buen juicio sobre cómo han evolucionado el lenguaje en las últimas 2 décadas.
Tiene una comunidad de usuarios vibrante y amigable.
Hay una serie de opciones para implementar compiladores integrados de alto rendimiento. Uno es Mono VM, que naturalmente viene con docenas de lenguajes de alta calidad ya implementados encima y es bastante incrustable (vea cómo lo está usando Second Life). También es posible usar LLVM: parece que su DSL no es complicado, por lo que implementar un compilador ad hoc no sería un gran problema.
No dices qué plataforma estás usando, pero si fuera capaz de usar LuaJIT 2 , ciertamente lo conseguiría, ya que las velocidades de ejecución se aproximan a las del código compilado, y la interfaz con el código C es mucho más fácil con La biblioteca FFI.
No dejo de conocer otros lenguajes de scripts incrustables, así que no puedo comparar lo que pueden hacer y cómo funcionan con las tablas.
Lua trabaja principalmente con referencias: todas las funciones, datos de usuario, tablas se usan por referencia, y se recopilan en la próxima ejecución de gc cuando no quedan referencias a los datos. Las cadenas se internalizan, por lo que una determinada cadena está en la memoria solo una vez. Lo que hay que tener en cuenta es que debes evitar crear y, posteriormente, descartar muchas tablas, ya que esto puede ralentizar el ciclo de GC (como se explica en la gema de Lua que has citado)
Para analizar su muestra de código, eche un vistazo a la LPEG
Resulta que trabajé en un proyecto que tiene partes que son similares a su proyecto. Es un sistema multiplataforma que se ejecuta en Win-CE, Android, iOS, necesito maximizar el código multiplataforma, C / C ++ se combina con un lenguaje incrustable es una buena opción. aquí está mi solución relacionada con sus preguntas.
- Si estuvieras en mi posición, ¿qué idioma elegirías?
El DSL en mi proyecto es similar al tuyo. para el rendimiento, escribí un compilador con Yacc / Lex para compilar el DSL en binario para el tiempo de ejecución y un montón de API para obtener información del binario, pero es molesto cuando hay algo modificado en la sintaxis de DSL, necesito modificar tanto el compilador como las API , por lo que dejé de lado el DSL, lo convertí en XML (no escriba XML directamente, vale un esquema bien definido), escribí un compilador general que convierte XML a lua table, reimplemento las API con lua. Al hacer esto obtuve dos beneficios: legibilidad y flexibilidad, sin una degradación perceptible del rendimiento.
- ¿Hay alguna alternativa que deba considerar (no sugiera idiomas que no tienen una implementación incrustable). Javascript v8 tal vez?
Antes de elegir lua, consideré Ch Embedded (usado principalmente en el sistema de control industrial), lisp y lua incrustados, por último lua se destacan, porque lua está bien integrada con C, lua tiene una comunidad próspera, y lua es fácil de aprender para otro miembro del equipo. con respecto a Javascript v8, es como usar un martillo de vapor para romper nueces, si se usa en un sistema embebido en tiempo real.
- ¿Lisp se ajusta mejor al dominio? No creo que lua y lisp sean tan diferentes en términos de lo que ofrecen. Llámame: D
Para mi dominio, lisp y lua tienen la misma capacidad en semántico, ambos pueden manejar DSL basado en XML fácilmente, o incluso podría escribir un compilador simple que convierte XML a lisp list o lua table. ambos pueden manejar la lógica de dominio fácilmente. pero lua está mejor integrada con C / C ++, esto es a lo que apunta lua.
- ¿Hay otras propiedades (como las de abajo) en las que debería estar pensando?
Trabajar solo o con miembros del equipo también es un factor de ponderación en la selección de soluciones. hoy en día no hay tantos programadores que estén familiarizados con el lenguaje similar a lisp.
- Afirmo que cualquier forma de IO de base de datos incrustada (vea el ejemplo de DSL a continuación para el contexto) empequeñece la llamada del lenguaje de scripting en órdenes de magnitud, y que la selección tampoco agregará mucha sobrecarga al rendimiento general. ¿Estoy en el camino correcto? :RE
here hay una lista del rendimiento de los lenguajes de programación, here está una lista del tiempo de acceso de los componentes de la computadora. si su sistema está vinculado a IO, la sobrecarga del script no es un punto clave. Mi sistema es un sistema de operación y mantenimiento (Operación y mantenimiento), el rendimiento del script es insignificante.