Lua vs Embedded Lisp y otros posibles candidatos. para el procesamiento de datos basado en conjuntos


Opció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 Cuestiones de interés

  1. Gambito-C y Guile como lenguajes embebibles
  2. Consejos de rendimiento de Lua (tener la opción de ejecutar con un recopilador deshabilitado, y llamar al recopilador al final de una(s) ejecución (es) de procesamiento siempre es un opcion).

Antecedentes

Estoy trabajando en un sistema de procesamiento de eventos de alto volumen (complejo) en tiempo real. Tengo un DSL que representa el esquema de la estructura de eventos en el origen, el formato de almacenamiento, ciertas construcciones específicas de dominio, activando eventos internos (para estructurar y conducir el procesamiento de propósito general) y codificando ciertos pasos de procesamiento que siempre ocurren.

El DSL se ve bastante similar a 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 basado en conjuntos, como SQL. Sin embargo, he llegado a la conclusión de que no debería 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 IO de búfer de protocolo i es decir, los eventos no están estructurados usando protocol buffer object solo usan la misma biblioteca de codificación / decodificación. Crearé un objeto de conjunto de datos que contenga filas, bastante similar a cómo un motor de base de datos almacena en conjuntos de memoria. los pasos de procesamiento en el DSL se cuidarán primero y luego se presentarán a la lógica de procesamiento de propósito general.

Independientemente del entorno de scripting embebible que use, cada subproceso en mi núcleo de procesamiento probablemente necesitará su propio entorno de lenguaje embebido (así es como lua requiere que sea por lo menos si usted está haciendo el trabajo multi-threaded).

La(s) Pregunta (s)

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 se desea minimizar las asignaciones de memoria:

  1. Si estuvieras en mi posición, ¿qué idioma elegirías ?

  2. ¿Hay alguna alternativa que debería considerar (no sugiera idiomas que no tengan un embeddable aplicación). Javascript v8 tal vez ?

  3. ¿Lisp se ajusta mejor al dominio ? No creo que lua y Lisp sean tan diferentes en términos de lo que proporcionan. Llámame: D

  4. ¿Hay otras propiedades (como las de abajo) en las que debería estar pensando ?

  5. Afirmo que cualquier forma de E / s de base de datos incrustada (vea el ejemplo DSL a continuación para el contexto) empequeñece la llamada al lenguaje de scripting en órdenes de magnitud, y que elegir cualquiera de los dos no agregue mucha sobrecarga al rendimiento general. Estoy en el camino correcto ? : D

Propiedades Deseadas

  1. Me gustaría asignar mi conjunto de datos a una lista lisp 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 debería intentar usar semántica de referencia si ambas tablas tienen la misma forma.

  2. Puedo garantizar que el conjunto de datos que se pasa como entrada no cambiará mientras han hecho la llamada lua / lisp. Quiero que lua y lisp no alteren el conjunto de datos también si es posible.

  3. Después de que el final de la llamada incrustada de los conjuntos de datos debe ser destruido, cualquier referencia creada tendría que ser reemplazado con copias (supongo).

Ejemplo de DSL

Adjunto un DSL para su placer visual para que pueda tener 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);
  } 
}

Esto el proyecto es un componente de un proyecto de investigación de doctorado y es / será software libre. Si está interesado en trabajar conmigo (o contribuir) en este proyecto, por favor deje un comentario: D

Author: Community, 2011-10-27

4 answers

Estoy totalmente de acuerdo con los puntos de @jpjacobs. Lua es una excelente opción para incrustar, a menos que haya algo muy específico sobre lisp que necesite (por ejemplo, si sus datos se asignan particularmente bien a cons-cells).

He usado lisp durante muchos muchos años, por cierto, y me gusta bastante la sintaxis lisp, pero en estos días generalmente elegiría Lua. Aunque me gusta el lenguaje lisp , todavía tengo que encontrar una implementación lisp que capture el maravilloso equilibrio de características / pequeñez / usabilidad para el uso integrado de la manera que lo hace Lua.

Lua:

  1. 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 de fuentes, si desea evitar agregar una dependencia externa.

  2. Es muy rápido. El intérprete de Lua es mucho más rápido que la mayoría de los lenguajes de scripting (de nuevo, un orden de magnitud no es raro), y LuaJIT2 es un muy buen compilador JIT para algunas arquitecturas de CPU populares (x86, arm, mips, ppc). El uso de LuaJIT a menudo puede acelerar las cosas por otro orden de magnitud, y en muchos casos, el resultado se acerca a la velocidad de C. LuaJIT también es un reemplazo "drop-in" para el estándar Lua 5.1: no se requieren cambios en la aplicación o el código de usuario para usarlo.

  3. Ha 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 para tareas grandes y 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 tratando de emular, y fue muy fácil y directo de crear.] LPEG es un paquete adicional para Lua, pero vale la pena obtenerlo (es una fuente file).

  4. Tiene una gran interfaz C, lo que hace que sea un placer llamar a Lua desde C, o llamar a C desde Lua. Para interconectar bibliotecas de C++ grandes/complejas, uno puede usar SWIG, o cualquiera de una serie de generadores de interfaces (uno también puede usar la sencilla interfaz de C de Lua con C++, por supuesto).

  5. Tiene licencia liberal ("similar a BSD"), lo que significa que Lua se puede incrustar en proyectos propietarios si lo desea, y es compatible con la GPL para software libre proyecto.

  6. Es muy, muy elegante. No es lisp, ya que no se basa en cons-cells, pero muestra claras influencias de lenguajes como scheme, con una sintaxis directa y atractiva. Al igual que scheme (al menos en sus encarnaciones anteriores), tiende hacia "mínimo", pero hace un buen trabajo de equilibrio con la usabilidad. Para alguien con un fondo de ceceo(como yo!), mucho sobre Lua parecerá familiar ,y "tendrá sentido", a pesar de la diferencia.

  7. Es muy flexible, y características tales como metatables permiten integrar fácilmente tipos y operaciones específicos del dominio.

  8. Tiene una sintaxis simple, atractiva y accesible. Esto podría no ser una ventaja sobre lisp para los usuarios existentes de lisp, pero podría ser relevante si desea que los usuarios finales escriban scripts.

  9. Está diseñado para incrustar, y además de su pequeño tamaño y velocidad rápida, tiene varias características como un incremental GC que hacen que el uso de un lenguaje de scripting sea más viable en tales contextos.

  10. Tiene una larga historia, y desarrolladores responsables y profesionales, que han demostrado buen juicio en cómo han evolucionado el lenguaje en las últimas 2 décadas.

  11. Tiene una comunidad de usuarios vibrante y amigable.

 32
Author: snogglethorpe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-18 22:57:24

No se indica qué plataforma se está utilizando, pero si fuera capaz de usar LuaJIT 2 Ciertamente iría por eso, ya que las velocidades de ejecución se acercan a las del código compilado, y la interfaz con el código C se ha vuelto mucho más fácil con la biblioteca FFI.

No dejo de conocer otros lenguajes de scripting embebibles, así que no puedo comparar realmente lo que pueden hacer y cómo funcionan con las tablas.

Lua trabaja principalmente con referencias: todas las funciones, datos de usuario, tablas son utilizadas por referencia, y se recopilan en la siguiente ejecución de gc cuando no quedan referencias a los datos. Las cadenas están internalizadas, 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 cargas de tablas, ya que esto puede ralentizar el ciclo de GC (como se explica en la gema de Lua que citaste)

Para analizar tu ejemplo de código, echaría un vistazo a la biblioteca LPEG

 6
Author: jpjacobs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-28 08:05:21

Hay varias opciones para implementar compiladores embebidos de alto rendimiento. Uno es Mono VM, naturalmente viene con docenas de lenguajes de alta calidad ya hechos implementados en la parte superior, y es bastante incrustable (vea cómo lo usa 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.

 2
Author: SK-logic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-28 09:17:35

Me pasó a trabajar en un proyecto que tienen algunas partes que es similar a su proyecto, Es un sistema multiplataforma que se ejecuta en Win-CE,Android,iOS, necesito maximizar el código compatible con multiplataforma, C/C++ combinar con un lenguaje incrustable es una buena opción. aquí está mi solución relacionada con sus preguntas.

  1. 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 a 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 DSL, necesito modificar tanto el compilador como las API, así que abandoné el DSL, me convertí en XML(no escriba XML directamente, vale la pena un esquema bien definido), escribí un compilador general convirtiendo XML a tabla lua, reimplemente las API con lua. al hacer esto obtuve dos beneficios: Legibilidad y flexibilidad, sin percibir degradación del rendimiento.

  1. Hay alguna alternativa que debería considerar (no sugiera lenguajes que no tengan una implementación incrustable). Javascript v8 tal vez ?

Antes de elegir lua, considered Embedded Ch (utilizado principalmente en sistemas de control industrial) , embedded lisp y lua, por fin lua se destacan, porque lua está bien integrado con C, lua tiene una comunidad próspera y lua es fácil de aprender para otro miembro del equipo. considerar Javascript v8, es como usar un martillo de vapor para romper tuercas, si se usa en un sistema embebido en tiempo real.

  1. ¿Lisp se ajusta mejor al dominio ? No creo que lua y Lisp sean tan diferentes en términos de lo que proporcionan. Llámame: D

Para mi dominio, lisp y lua tienen la misma capacidad en semántica, ambos pueden manejar DSL basado en XML fácilmente, o incluso podría escribir un compilador simple convirtiendo XML a lista lisp o tabla lua. ambos pueden manejar el dominio lógica fácilmente. pero lua está mejor integrado con C / C++, este es el objetivo de lua.

  1. ¿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 de la selección de la solución. hoy en día no muchos programadores están familiarizados con el lenguaje lisp.

  1. Afirmo que cualquier forma de IO de base de datos incrustada (ver el ejemplo DSL a continuación para el contexto) empequeñece la la llamada al lenguaje de scripting en órdenes de magnitud, y esa selección no agregará mucha sobrecarga al rendimiento general. Estoy en el camino correcto ? : D

Aquí es una lista de rendimiento de los lenguajes de programación, aquí es una lista de tiempo de acceso de los componentes de la computadora. si su sistema está limitado por IO, la sobrecarga del script no es un punto clave. mi sistema es un sistema de O & M (Operación y Mantenimiento), el rendimiento del script es insignificante.

 1
Author: Jimmy Zhang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-27 22:50:27