Lua vs Embedded Lisp и потенциальные другие кандидаты. для обработки данных

Нынешний Выбор: в Lua-JIT-компилятором. Впечатляющие ориентиры, я привыкаю к синтаксису. Написание высокопроизводительного ABI потребует тщательного рассмотрения того, как я буду структурировать свой C++.

другие вопросы, представляющие интерес

  1. Gambit-C и коварство как встраиваемые языки
  2. Lua Советы По Производительности (есть возможность запуска с отключенным сборщиком и вызова сборщика на конец выполнения (ов) обработки всегда является опцией).

фон

Я работаю над высокообъемной (сложной) системой обработки событий в реальном времени. У меня есть DSL, который представляет схему структуры событий в источнике, формат хранения, определенные доменные конструкции, запуск внутренних событий (для структурирования и обработки общего назначения) и кодирование определенных шагов обработки, которые всегда происходят.

DSL выглядит очень похоже на SQL, infact я использую berkeley db (через интерфейс sqlite3) для долгосрочного хранения событий. важной частью здесь является то, что обработка событий выполняется на основе набора, например SQL. Однако я пришел к выводу, что я не должен добавлять логику обработки общего назначения в DSL, а скорее вставлять lua или lisp, чтобы позаботиться об этом.

обработка ядра строится вокруг буст::асио, это многопоточный, ЭКП осуществляется через буферы протокола событий кодируются с использованием библиотеки IO буфера протокола-т. е. события не структурированы с использованием объекта буфера протокола, они просто используют ту же библиотеку кодирования/декодирования. Я создам объект dataset, содержащий строки, очень похожие на то, как компонент database engine хранит в наборах памяти. этапы обработки в DSL будут сначала рассмотрены, а затем представлены логике обработки общего назначения.

независимо от того, какую встраиваемую среду сценариев я использую, каждый поток в моем ядро обработки, вероятно, нуждается в собственной среде embedded-language-environment (именно так lua требует, чтобы это было, по крайней мере, если вы выполняете многопоточную работу).

вопрос(ы)

на данный момент выбор между lisp ECL и lua. Имея в виду, что производительность и пропускная способность являются сильным требованием, это означает, что очень желательно минимизировать выделение памяти:

  1. Если бы Вы были в моем положении, какой язык вы бы выбрал ?

  2. есть ли какие-либо альтернативы, которые я должен рассмотреть (не предлагайте языки, которые не имеют встраиваемой реализации). Возможно, Javascript v8 ?

  3. подходит ли lisp для домена лучше ? Я не думаю, что lua и lisp настолько отличаются с точки зрения того, что они предоставляют. Позовите меня: D

  4. есть ли другие свойства (например, приведенные ниже), о которых я должен думать ?

  5. I утверждайте, что любая форма встроенного ввода-вывода базы данных (см. Пример 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);
  } 
}

этот проект является компонентом исследовательского проекта PH. D и является / будет свободным программным обеспечением. Если вы заинтересованы в работе со мной (или содействии) в этом проекте, пожалуйста, оставьте комментарий: D

4 ответов


Я полностью согласен с пунктами @jpjacobs. Lua это отлично выбор для встраивания, если нет чего-то очень конкретного о lisp, что вам нужно (например, если ваши данные особенно хорошо сопоставляются с минусами-ячейками).

Я использовал lisp в течение многих лет, кстати, и мне очень нравится синтаксис lisp, но в эти дни я обычно выбираю Lua. Пока мне нравится шепелявить язык, Я еще не нашел шепелявость реализация что захватывает чудесный баланс особенностей / малости / практичности для врезанной пользы путь Lua делает.

Lua:

  1. очень мал, как исходный, так и двоичный, на порядок или более меньше, чем многие более популярные языки (Python и т. д.). Поскольку исходный код Lua настолько мал и прост, вполне разумно просто включить всю реализацию Lua в исходное дерево, если вы хотите избежать добавления внешней зависимости.

  2. очень быстро. Интерпретатор Lua намного быстрее, чем большинство языков сценариев (опять же, порядок величины не редкость), и LuaJIT2 это очень хороший JIT-компилятор для некоторых популярных архитектур ЦП (x86, arm, mips, ppc). Использование LuaJIT часто может ускорить процесс другое порядок величины, и во многих случаях результат приближается к скорости C. LuaJIT также является" падающей " заменой для стандартного Lua 5.1: нет применение или изменение кода пользователя необходимо использовать его.

  3. и LPEG. LPEG-это библиотека "синтаксического анализа выражения" для Lua, которая позволяет очень легко, мощно и быстро анализировать, подходит как для больших, так и для малых задач; это отличная замена для yacc/lex/hairy-regexps. [Я написал парсер с использованием LPEG и LuaJIT, что очень быстрее чем парсер yacc / lex, который я пытался эмулировать, и был очень легким и прямым, чтобы создавать.] LPEG-это дополнительный пакет для Lua, но его стоит получить (это один исходный файл).

  4. есть большой C-интерфейс, который делает его удовольствие вызвать Lua от C, или вызвать C от Lua. Для сопряжения больших / сложных библиотек c++ можно использовать SWIG или любой из нескольких генераторов интерфейса (можно также использовать простой интерфейс Lua с C++, конечно).

  5. имеет либеральное лицензирование ("BSD-like"), что означает Lua может быть встроен в проприетарные проекты, если вы хотите, и совместим с GPL для проектов FOSS.

  6. очень, очень элегантный. Это не lisp, поскольку он не основан на cons-ячейках, но он показывает четкие влияния таких языков, как scheme, с прямым и привлекательным синтаксисом. Как и схема (по крайней мере, в ее ранних воплощениях), она имеет тенденцию к "минимальному", но хорошо справляется с балансировкой этого с удобством использования. Для кого-то с фоном lisp (например, я!), многое о Lua будет казаться знакомым и" иметь смысл", несмотря на различия.

  7. очень гибко, и такие характеристики как metatables позволяют легко интегрировать домен-специфические типы и деятельности.

  8. имеет простой, привлекательный, и доступный синтаксис. Это может быть не таким преимуществом перед lisp для существующих пользователей lisp, но может иметь значение, если вы хотите, чтобы конечные пользователи писали сценарии.

  9. Is разработанный для встраивания, помимо небольшого размера и быстрой скорости, имеет различные функции, такие как инкрементный GC, которые делают использование языка сценариев более жизнеспособным в таких контекстах.

  10. имеет долгую историю и ответственных и профессиональных разработчиков, которые показали хорошее суждение о том, как они развили язык за последние 2 десятилетия.

  11. имеет яркое и дружелюбное пользовательское сообщество.


вы не указываете, какую платформу вы используете, но если бы она была способна использовать LuaJIT 2 Я бы, конечно, пошел на это, так как скорость выполнения приближается к скорости скомпилированного кода, а взаимодействие с кодом C стало намного проще с библиотекой FFI.

Я не перестаю знать другие встраиваемые языки сценариев, поэтому я не могу сравнить, что они могут делать и как они работают с таблицами.

Lua в основном работает со ссылками: все функции, userdata, таблицы используются по ссылке и собираются при следующем запуске gc, когда ссылки на данные не остаются. Строки интернализированы, поэтому определенная строка находится в памяти только один раз. Дело в том, что вы должны избегать создания и последующего отбрасывания нагрузок таблиц, так как это может замедлить цикл GC (как объяснено в Lua gem, который вы процитировали)

для разбора вашего образца кода я бы взглянул на библиотека LPEG


существует несколько вариантов реализации высокопроизводительных встроенных компиляторов. Один из них-Mono VM, он, естественно, поставляется с десятками уже сделанных высококачественных языков, реализованных поверх него, и он довольно встраиваемый (см., как Second Life использует его). Также можно использовать LLVM-похоже, ваш DSL не сложен, поэтому реализация специального компилятора не будет большой проблемой.


Мне довелось работать над проектом, который имеет некоторые части,похожие на ваш проект,это кросс-платформенная система, работающая на Win-CE, Android, iOS, мне нужно максимизировать кросс-платформенный код, C/C++ в сочетании с встраиваемым языком-хороший выбор. вот мое решение, связанное с вашими вопросами.

  1. если бы Вы были на моем месте, какой язык вы бы выбрали ?

на DSL в моем проекте похож на твой. по производительности, я написал компилятор с Yacc/Lex в компиляции DSL для бинарных для выполнения и кучу API, чтобы получить информацию из двоичного файла, но это раздражает, когда там что-то изменено в DSL синтаксис, мне нужно изменить как компилятор и API, так что я abondoned в DSL, превращаются в XML(не писать XML непосредственно, четко определенной схеме достоин), я написал общие компилятор преобразования XML для Lua таблице, реализовать API с помощью Lua. сделав это, я получил два преимущества: читаемость и гибкость, без заметного снижения производительности.

  1. есть ли какие-либо альтернативы, которые я должен рассмотреть (не предлагайте языки, которые не имеют встраиваемой реализации). Возможно, Javascript v8 ?

прежде чем выбрать lua, я считаю Встроенный Ch(главным образом использованный в промышленной системе управления), врезанный lisp и lua, наконец lua стоят вне, потому что lua хорошо интегрировано с C, lua имеют зажиточную общину, и Lua легко узнать для другого члена команды. что касается Javascript v8, это похоже на использование парового молота для взлома орехов, если он используется во встроенной системе реального времени.

  1. подходит ли lisp для домена лучше ? Я не думаю, что lua и lisp настолько отличаются с точки зрения того, что они предоставляют. Позовите меня: D

для моего домена lisp и lua имеют одинаковую способность в семантике, они оба могут легко обрабатывать DSL на основе XML, или вы можете даже написать простой компилятор, преобразующий XML в список lisp или таблицу lua. они оба могут легко обрабатывать логику домена. но lua лучше интегрирован с C/C++, это то, к чему стремится lua.

  1. есть ли какие-либо другие свойства (например, ниже), о которых я должен думать ?

работа в одиночку или с членами команды также является весовым фактором выбора решения. в настоящее время не так много программистов знакомы с lisp-подобным языком.

  1. Я утверждаю, что любая форма встроенного ввода-вывода базы данных (см. Пример DSL ниже для контекста) затмевает вызов языка сценариев на порядки величины, и что выбор либо не добавит много накладных расходов к общей пропускной способности. Я на правильном пути ? : D

здесь список производительности языков программирования,здесь список времени доступа компонентов компьютера. если ваша система связана с IO, накладные расходы сценарий не является ключевым моментом. моя система-это система O&M (Operation & Maintenance), производительность скрипта незначительна.