125

Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

  • Upload
    ontico

  • View
    97

  • Download
    3

Embed Size (px)

Citation preview

Page 1: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)
Page 2: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Что такое Rspamd

• Система фильтрации спама с ориентацией на производительность

• OpenSource проект

• Плагины и правила написаны на языке Lua

• Ядро написано на plain (old) C

Page 3: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Lua и C В Rspamd

Lua

C

Page 4: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Соотношение Lua и C По строкам кода

0

35000

70000

105000

140000

Plain C

LuaAssembly Other

Perl

Page 5: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Соотношение Lua и C По количеству плагинов

0

8

15

23

30

6

26

Lua C

Page 6: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Что написано на Lua• Правила, а также комбинации регулярных выражений

• Большая часть плагинов:

• Проверка DNS списков

• Взаимодействие с Redis (репутация, “серые” списки, динамические настройки, список ответов, динамические лимиты)

• Работа с внешними сервисами (антивирусы, запись в ClickHouse итд)

• Контент-фильтрация

• Работа с нейросетями и классификацией текстов

• Работа с SpamAssassin правилами

Page 7: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Почему Lua?

Page 8: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Экскурс в историю

Page 9: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

K&R определение функции

Странный синтаксис переменных

Что это?

Надо больше макросов!

Page 10: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Похоже, это обычный C

Page 11: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Правило на Lua

Page 12: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Встраиваемый язык Каким он должен быть

Page 13: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Встраиваемый язык Каким он должен быть

• Минимум внешних зависимостей (JavaScript)

Page 14: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Встраиваемый язык Каким он должен быть

• Минимум внешних зависимостей (JavaScript)

• Простота синтаксиса (Perl)

Page 15: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Встраиваемый язык Каким он должен быть

• Минимум внешних зависимостей (JavaScript)

• Простота синтаксиса (Perl)

• Скорость работы (Python, Guile, TCL)

Page 16: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Встраиваемый язык Каким он должен быть

• Минимум внешних зависимостей (JavaScript)

• Простота синтаксиса (Perl)

• Скорость работы (Python, Guile, TCL)

• Скорость переключения между C и встраиваемым языком

Page 17: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Что дал переход на Lua

Page 18: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Что дал переход на Lua

• Появилось несколько активных авторов плагинов и правил на Lua

Page 19: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Что дал переход на Lua

• Появилось несколько активных авторов плагинов и правил на Lua

• Появились юнит-тесты на Lua

Page 20: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Что дал переход на Lua

• Появилось несколько активных авторов плагинов и правил на Lua

• Появились юнит-тесты на Lua

• Текущий подход к разработке: писать Lua биндинги на Си, а основную логику на Lua

Page 21: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Что дал переход на Lua

• Появилось несколько активных авторов плагинов и правил на Lua

• Появились юнит-тесты на Lua

• Текущий подход к разработке: писать Lua биндинги на Си, а основную логику на Lua

• Упростилось написание утилит командной строки

Page 22: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Особенности Lua

Page 23: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Кривая обучения Lua

Начал писать на Lua

Page 24: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Обучение LuaThat was my first ever attempt at Lua, I asked you to add halfOpen support to your lua_tcp module, which you did within about 30 mins and I had the plugin written an working within an hour or so.

Page 25: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Обучение Lua

• Плагин опроса внешнего сервиса DCC:

That was my first ever attempt at Lua, I asked you to add halfOpen support to your lua_tcp module, which you did within about 30 mins and I had the plugin written an working within an hour or so.

Page 26: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Обучение Lua

• Плагин опроса внешнего сервиса DCC:

• написан за час времени

That was my first ever attempt at Lua, I asked you to add halfOpen support to your lua_tcp module, which you did within about 30 mins and I had the plugin written an working within an hour or so.

Page 27: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Обучение Lua

• Плагин опроса внешнего сервиса DCC:

• написан за час времени

• человеком, без знаний Lua

That was my first ever attempt at Lua, I asked you to add halfOpen support to your lua_tcp module, which you did within about 30 mins and I had the plugin written an working within an hour or so.

Page 28: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Обучение Lua

• Плагин опроса внешнего сервиса DCC:

• написан за час времени

• человеком, без знаний Lua

• еще 30 минут заняла адаптация биндингов на C

That was my first ever attempt at Lua, I asked you to add halfOpen support to your lua_tcp module, which you did within about 30 mins and I had the plugin written an working within an hour or so.

Page 29: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Обучение Lua

• Плагин опроса внешнего сервиса DCC:

• написан за час времени

• человеком, без знаний Lua

• еще 30 минут заняла адаптация биндингов на C

• аналог на перле - больше 1k строк кода

That was my first ever attempt at Lua, I asked you to add halfOpen support to your lua_tcp module, which you did within about 30 mins and I had the plugin written an working within an hour or so.

Page 30: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Некоторые особенности Lua Общие характеристики языка

Page 31: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Некоторые особенности Lua Общие характеристики языка

• Крайне простой синтаксис (20 правил в BNF грамматике)

Page 32: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Некоторые особенности Lua Общие характеристики языка

• Крайне простой синтаксис (20 правил в BNF грамматике)

• Таблицы - универсальный инструмент работы с данными

Page 33: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Некоторые особенности Lua Общие характеристики языка

• Крайне простой синтаксис (20 правил в BNF грамматике)

• Таблицы - универсальный инструмент работы с данными

• Функции - объекты первого рода (возможны функциональные конструкции и замыкания)

Page 34: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Некоторые особенности Lua Общие характеристики языка

• Крайне простой синтаксис (20 правил в BNF грамматике)

• Таблицы - универсальный инструмент работы с данными

• Функции - объекты первого рода (возможны функциональные конструкции и замыкания)

• Стандартная библиотека содержит только необходимый минимум функций

Page 35: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Некоторые особенности Lua Общие характеристики языка

• Крайне простой синтаксис (20 правил в BNF грамматике)

• Таблицы - универсальный инструмент работы с данными

• Функции - объекты первого рода (возможны функциональные конструкции и замыкания)

• Стандартная библиотека содержит только необходимый минимум функций

• Динамическая строгая типизация

Page 36: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Синтаксис Lua Основные элементы

Page 37: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Синтаксис Lua Основные элементы

• Переменные:

Page 38: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Синтаксис Lua Основные элементы

• Переменные: local ret = false -- Generic variablelocal rules = {} -- Empty tablelocal rspamd_logger = require “rspamd_logger" -- Load rspamd module

Page 39: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Синтаксис Lua Основные элементы

• Переменные:

• Условия:

local ret = false -- Generic variablelocal rules = {} -- Empty tablelocal rspamd_logger = require “rspamd_logger" -- Load rspamd module

Page 40: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Синтаксис Lua Основные элементы

• Переменные:

• Условия:

local ret = false -- Generic variablelocal rules = {} -- Empty tablelocal rspamd_logger = require “rspamd_logger" -- Load rspamd module

if not ret then -- can use ‘not’, ‘and’, ‘or’ here…elseif ret ~= 10 then -- note ~= for ‘not equal’ operatorend

Page 41: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Синтаксис Lua Основные элементы

• Переменные:

• Условия:

• Циклы:

local ret = false -- Generic variablelocal rules = {} -- Empty tablelocal rspamd_logger = require “rspamd_logger" -- Load rspamd module

if not ret then -- can use ‘not’, ‘and’, ‘or’ here…elseif ret ~= 10 then -- note ~= for ‘not equal’ operatorend

Page 42: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Синтаксис Lua Основные элементы

• Переменные:

• Условия:

• Циклы:

local ret = false -- Generic variablelocal rules = {} -- Empty tablelocal rspamd_logger = require “rspamd_logger" -- Load rspamd module

if not ret then -- can use ‘not’, ‘and’, ‘or’ here…elseif ret ~= 10 then -- note ~= for ‘not equal’ operatorend

for k,m in pairs(opts) do … end -- Iterate over keyed table a[‘key’] = valuefor _,i in ipairs(images) do … end -- Iterate over array table a[1] = valuefor i=1,10 do … end -- Count from 1 to 10

Page 43: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Синтаксис Lua Основные элементы

• Переменные:

• Условия:

• Циклы:

• Таблицы:

local ret = false -- Generic variablelocal rules = {} -- Empty tablelocal rspamd_logger = require “rspamd_logger" -- Load rspamd module

if not ret then -- can use ‘not’, ‘and’, ‘or’ here…elseif ret ~= 10 then -- note ~= for ‘not equal’ operatorend

for k,m in pairs(opts) do … end -- Iterate over keyed table a[‘key’] = valuefor _,i in ipairs(images) do … end -- Iterate over array table a[1] = valuefor i=1,10 do … end -- Count from 1 to 10

Page 44: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Синтаксис Lua Основные элементы

• Переменные:

• Условия:

• Циклы:

• Таблицы:

local ret = false -- Generic variablelocal rules = {} -- Empty tablelocal rspamd_logger = require “rspamd_logger" -- Load rspamd module

if not ret then -- can use ‘not’, ‘and’, ‘or’ here…elseif ret ~= 10 then -- note ~= for ‘not equal’ operatorend

for k,m in pairs(opts) do … end -- Iterate over keyed table a[‘key’] = valuefor _,i in ipairs(images) do … end -- Iterate over array table a[1] = valuefor i=1,10 do … end -- Count from 1 to 10

local options = { [1] = ‘value’, [‘key’] = 1, -- Numbers starts from 1 another_key = function(task) … end, -- Functions can be values [2] = {} -- Other tables can be values} -- Can have both numbers and strings as key and anything as values

Page 45: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Синтаксис Lua Основные элементы

• Переменные:

• Условия:

• Циклы:

• Таблицы:

• Функции:

local ret = false -- Generic variablelocal rules = {} -- Empty tablelocal rspamd_logger = require “rspamd_logger" -- Load rspamd module

if not ret then -- can use ‘not’, ‘and’, ‘or’ here…elseif ret ~= 10 then -- note ~= for ‘not equal’ operatorend

for k,m in pairs(opts) do … end -- Iterate over keyed table a[‘key’] = valuefor _,i in ipairs(images) do … end -- Iterate over array table a[1] = valuefor i=1,10 do … end -- Count from 1 to 10

local options = { [1] = ‘value’, [‘key’] = 1, -- Numbers starts from 1 another_key = function(task) … end, -- Functions can be values [2] = {} -- Other tables can be values} -- Can have both numbers and strings as key and anything as values

Page 46: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Синтаксис Lua Основные элементы

• Переменные:

• Условия:

• Циклы:

• Таблицы:

• Функции:

local ret = false -- Generic variablelocal rules = {} -- Empty tablelocal rspamd_logger = require “rspamd_logger" -- Load rspamd module

if not ret then -- can use ‘not’, ‘and’, ‘or’ here…elseif ret ~= 10 then -- note ~= for ‘not equal’ operatorend

for k,m in pairs(opts) do … end -- Iterate over keyed table a[‘key’] = valuefor _,i in ipairs(images) do … end -- Iterate over array table a[1] = valuefor i=1,10 do … end -- Count from 1 to 10

local options = { [1] = ‘value’, [‘key’] = 1, -- Numbers starts from 1 another_key = function(task) … end, -- Functions can be values [2] = {} -- Other tables can be values} -- Can have both numbers and strings as key and anything as values

local function something(task) -- Normal definition local cb = function(data) -- Functions can be nested … endend

Page 47: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Таблицы в Lua

Page 48: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Таблицы в Lua Основные определения

Page 49: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Таблицы в Lua Основные определения

• Значения - все, кроме nil:

Page 50: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Таблицы в Lua Основные определения

• Значения - все, кроме nil: local t = { 1, -- number 'test', -- string function() end, -- function {1, 2, 3} -- another table task:get_mempool(), -- userdata}

Page 51: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Таблицы в Lua Основные определения

• Значения - все, кроме nil: local t = { 1, -- number 'test', -- string function() end, -- function {1, 2, 3} -- another table task:get_mempool(), -- userdata}

• Ключи - строки и числа:

Page 52: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Таблицы в Lua Основные определения

• Значения - все, кроме nil: local t = { 1, -- number 'test', -- string function() end, -- function {1, 2, 3} -- another table task:get_mempool(), -- userdata}

local t = { 1, -- 1 [3] = {1,2}, test = function() end, ['spaces in key'] = 'abc', [1.2] = 3, [-1] = 4,}

• Ключи - строки и числа:

Page 53: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Таблицы в Lua

table

local table = { a = 1, b = 2, [1] = 3, [2] = function() end, [0] = true }

3

function() end

true

1

2

12

0‘a’‘b’

Массив Хеш таблица!

Page 54: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Таблицы в Lua Итерация

local t = { a = 1, b = 2, [1] = 3, [2] = function() end, [0] = true }

Массив

Таблица целиком

1..2

Page 55: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Метатаблицы Когда просто таблиц недостаточно

• Задают общие свойства для других таблиц

• Примерно соответствуют Prototype в JavaScript

• Позволяют задавать функции-методы для таблиц (через __newindex или __index)

• Могут также задавать операторы над таблицами (например, через __eq или __sum)

• Можно задавать метатаблицы для стандартных Lua типов (например, строк)

• Используются в C API для определения методов для типа userdata

Page 56: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua

Page 57: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Основные элементы

Page 58: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Основные элементы

• Могут быть вложенными:

Page 59: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Основные элементы

• Могут быть вложенными: function foo(n) -- global function local var = function(m) -- function in var return m + n -- n is from `foo` end local function bar() -- another form of var return var(2) end return bar()end

Page 60: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Основные элементы

• Могут быть вложенными: function foo(n) -- global function local var = function(m) -- function in var return m + n -- n is from `foo` end local function bar() -- another form of var return var(2) end return bar()end

• Могут быть аргументами и

возвращаться из функций:

Page 61: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Основные элементы

• Могут быть вложенными: function foo(n) -- global function local var = function(m) -- function in var return m + n -- n is from `foo` end local function bar() -- another form of var return var(2) end return bar()end

local function f(cb) -- accepts callback function return function(args) -- accepts some args return cb(args) -- return callback function from args (decorator like) endend

• Могут быть аргументами и

возвращаться из функций:

Page 62: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Замыкания

function test(n) local f = function() return n + 1 -- n is captured end

n = n + 1 -- n in f is also modified return а end

test(1) -- Returns function closure test(1)() -- Returns 3

Page 63: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Замыкания

function test(n) local f = function() return n + 1 -- n is captured end

n = n + 1 -- n in f is also modified return а end

test(1) -- Returns function closure test(1)() -- Returns 3

Замыкание

Page 64: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Замыкания

function test(n) local f = function() return n + 1 -- n is captured end

n = n + 1 -- n in f is also modified return а end

test(1) -- Returns function closure test(1)() -- Returns 3

Замыкание

Page 65: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Замыкания

function test(n) local f = function() return n + 1 -- n is captured end

n = n + 1 -- n in f is also modified return а end

test(1) -- Returns function closure test(1)() -- Returns 3

Замыкание

Переменные входят по ссылке

Page 66: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Замыкания

function test(n) local f = function() return n + 1 -- n is captured end

n = n + 1 -- n in f is also modified return а end

test(1) -- Returns function closure test(1)() -- Returns 3

Замыкание

Переменные входят по ссылкеМожно возвращать функцию

Page 67: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Замыкания

function test(n) local f = function() return n + 1 -- n is captured end

n = n + 1 -- n in f is also modified return а end

test(1) -- Returns function closure test(1)() -- Returns 3

Замыкание

Переменные входят по ссылке

Функция-замыкание

Можно возвращать функцию

Page 68: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua Замыкания

function test(n) local f = function() return n + 1 -- n is captured end

n = n + 1 -- n in f is also modified return а end

test(1) -- Returns function closure test(1)() -- Returns 3

Замыкание

Переменные входят по ссылке

Функция-замыканиеНепосредственно вызов

Можно возвращать функцию

Page 69: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Функции в Lua

• Позволяют писать в функциональном стиле (библиотека lua-fun)

• Замыкания работают также для C функций

• Передача по ссылке несколько необычна, но эффективна

• Время жизни замыкания ассоциируется с переменной, в которой оно хранится

Page 70: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Строки в Lua

Page 71: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Строки в Lua Передача строки из C

Глобальный хеш строк

s1s2s3

lua_pushstring (L, "hello");

hello

Копия

Хеш

hash(hello)

Поиск

Page 72: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Строки в Lua Передача строки из C

Глобальный хеш строк

s1s2s3

lua_pushstring (L, "hello");

hello

Вставкаhello

Page 73: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Строки в Lua

• Строки в Lua неизменяемы

• Сравнение строк - просто сравнение указателей: O(1)

• Создание и передача строк - дорогая операция

• Если нужно делать строку из кусков, то нужно использовать таблицу и table.concat

Page 74: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Строки в LuaСекунды

(меньше

- лучше)

0

75

150

225

300

Naive concat Table.concat

6.7c

274c

40x

Page 75: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Строки в Lua Передача текста

C C

Userdata

const char *ssize_t lenrefcounter

Page 76: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Взаимодействие Lua и C

Page 77: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Виртуальный стек Общий вид

1234

-4-3-2-1 lua_gettop() ⟹4

PushPop

Page 78: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Виртуальный стек Добавление значений

1234

-6-5-4-3

lua_pushnumbernumber

string

56

-2-1 lua_pushstring

Push

Page 79: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Виртуальный стек Извлечение значений

1234

-3-2-1

lua_pop(L, 3);number

string

56

Pop

Page 80: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Виртуальный стек Вызов функции

1234

-3-2-1

56

Внутренние переменые

number

string

45

-2-1

Аргументы

Возвращаемые значения

Page 81: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы работы со стеком

Page 82: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы работы со стеком

• Скорость: переключение занимает около сотни CPU cycles

Page 83: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы работы со стеком

• Скорость: переключение занимает около сотни CPU cycles

• Проблемы контроля: без специальных ключей компиляции легко получить низкоуровневые ошибки (вплоть до полного падения)

Page 84: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы работы со стеком

• Скорость: переключение занимает около сотни CPU cycles

• Проблемы контроля: без специальных ключей компиляции легко получить низкоуровневые ошибки (вплоть до полного падения)

Page 85: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы работы со стеком

• Скорость: переключение занимает около сотни CPU cycles

• Проблемы контроля: без специальных ключей компиляции легко получить низкоуровневые ошибки (вплоть до полного падения)

• Крайне неочевидный код

Page 86: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы работы со стеком

• Скорость: переключение занимает около сотни CPU cycles

• Проблемы контроля: без специальных ключей компиляции легко получить низкоуровневые ошибки (вплоть до полного падения)

• Крайне неочевидный код

• Есть ряд сложных моментов (итерация по таблице)

Page 87: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Пример из практики Итерация по таблице

lua_pushvalue (L, i); /* Push table on top */ lua_pushnil (L); /* Push nil to start iterate */

while (lua_next (L, -2)) { lua_pushvalue (L, -2); /* Copy key as it is special */

key = luaL_checkstring (L, -1); value = luaL_checkstring (L, -2);

lua_pop (L, 2); /* Remove key and value leaving original key */ }

lua_pop (L, 1); /* Remove table */

Page 88: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Пример из практики Итерация по таблице

lua_pushvalue (L, i); tabletop -1

Page 89: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Пример из практики Итерация по таблице

lua_pushvalue (L, i); lua_pushnil (L);

tabletop -2nil -1

Page 90: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Пример из практики Итерация по таблице

table -2nil -1

while (lua_next (L, -2))

table -3key -2

value -1

Предыдущий ключ

Новый ключ

Page 91: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Пример из практики Итерация по таблице

lua_pushvalue (L, -2); key = luaL_checkstring (L, -1); value = luaL_checkstring (L, -2);

table

-2key

-1value

key copy

-3-4

Page 92: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Пример из практики Итерация по таблице

lua_pop (L, 2);

table

-2key

-1value

key copy

-3-4

table

key -1-2

while (lua_next (L, -2))

Используется для следующей итерации

Page 93: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

FFI вызовы кода на C

Page 94: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Плюсы FFI

• Очень быстро работают для простых типов (десяток циклов)

• Поддерживают все конструкции C99

• Поддерживают типы-обертки (boxed types), например 64-х битные целые

• Проще поддерживать

Page 95: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

FFI вызовы Синтетические тесты

Секунды

(меньше

- лучше)

0

10

20

30

40

tanh(x) strcmp(s1, s2)Plain call FFI Plain call FFI

5.97c3.13c 4.38c

30.07c

10x

Page 96: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Пример из практики Оптимизация узких мест

local ffi if type(jit) == 'table' then ffi = require("ffi") ffi.cdef[[ int rspamd_re_cache_type_from_string (const char *str); int rspamd_re_cache_process_ffi (void *ptask, void *pre, int type, const char *type_data, int is_strong); ]] end

local function process_regexp_opt(re, task, re_type, header, strong) if type(jit) == 'table' then -- Use ffi call local itype = ffi.C.rspamd_re_cache_type_from_string(re_type)

if not strong then strong = 0 else string = 1 end local iret = ffi.C.rspamd_re_cache_process_ffi (task, re, itype, header, strong)

return tonumber(iret) else return task:process_regexp(re, re_type, header, strong) end end

Проверка LuaJIT

Page 97: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

local ffi if type(jit) == 'table' then ffi = require("ffi") ffi.cdef[[ int rspamd_re_cache_type_from_string (const char *str); int rspamd_re_cache_process_ffi (void *ptask, void *pre, int type, const char *type_data, int is_strong); ]] end

local function process_regexp_opt(re, task, re_type, header, strong) if type(jit) == 'table' then -- Use ffi call local itype = ffi.C.rspamd_re_cache_type_from_string(re_type)

if not strong then strong = 0 else string = 1 end local iret = ffi.C.rspamd_re_cache_process_ffi (task, re, itype, header, strong)

return tonumber(iret) else return task:process_regexp(re, re_type, header, strong) end end

Определение С функций

Пример из практики Оптимизация узких мест

Page 98: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

local ffi if type(jit) == 'table' then ffi = require("ffi") ffi.cdef[[ int rspamd_re_cache_type_from_string (const char *str); int rspamd_re_cache_process_ffi (void *ptask, void *pre, int type, const char *type_data, int is_strong); ]] end

local function process_regexp_opt(re, task, re_type, header, strong) if type(jit) == 'table' then -- Use ffi call local itype = ffi.C.rspamd_re_cache_type_from_string(re_type)

if not strong then strong = 0 else string = 1 end local iret = ffi.C.rspamd_re_cache_process_ffi (task, re, itype, header, strong)

return tonumber(iret) else return task:process_regexp(re, re_type, header, strong) end end

FFI call

Userdata to C pointer

bool -> int

Пример из практики Оптимизация узких мест

Page 99: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

local ffi if type(jit) == 'table' then ffi = require("ffi") ffi.cdef[[ int rspamd_re_cache_type_from_string (const char *str); int rspamd_re_cache_process_ffi (void *ptask, void *pre, int type, const char *type_data, int is_strong); ]] end

local function process_regexp_opt(re, task, re_type, header, strong) if type(jit) == 'table' then -- Use ffi call local itype = ffi.C.rspamd_re_cache_type_from_string(re_type)

if not strong then strong = 0 else string = 1 end local iret = ffi.C.rspamd_re_cache_process_ffi (task, re, itype, header, strong)

return tonumber(iret) else return task:process_regexp(re, re_type, header, strong) end end

Plain call

Пример из практики Оптимизация узких мест

Page 100: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Оптимизация FFI вызововLua вызов

FFI вызов

Page 101: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы FFI

Page 102: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы FFI• Поддерживаются на ограниченном количестве архитектур (Sparc64)

Page 103: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы FFI• Поддерживаются на ограниченном количестве архитектур (Sparc64)

• В plain Lua требуют отдельного модуля FFI, LuaJIT поддерживает “из коробки”

Page 104: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы FFI• Поддерживаются на ограниченном количестве архитектур (Sparc64)

• В plain Lua требуют отдельного модуля FFI, LuaJIT поддерживает “из коробки”

• Нет проверки типов, нет контроля целостности памяти

Page 105: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы FFI• Поддерживаются на ограниченном количестве архитектур (Sparc64)

• В plain Lua требуют отдельного модуля FFI, LuaJIT поддерживает “из коробки”

• Нет проверки типов, нет контроля целостности памяти

Page 106: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы FFI• Поддерживаются на ограниченном количестве архитектур (Sparc64)

• В plain Lua требуют отдельного модуля FFI, LuaJIT поддерживает “из коробки”

• Нет проверки типов, нет контроля целостности памяти

Page 107: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы FFI• Поддерживаются на ограниченном количестве архитектур (Sparc64)

• В plain Lua требуют отдельного модуля FFI, LuaJIT поддерживает “из коробки”

• Нет проверки типов, нет контроля целостности памяти

• Не всегда быстрее

Page 108: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Проблемы FFI• Поддерживаются на ограниченном количестве архитектур (Sparc64)

• В plain Lua требуют отдельного модуля FFI, LuaJIT поддерживает “из коробки”

• Нет проверки типов, нет контроля целостности памяти

• Не всегда быстрее

• Очень сложно сделать sandbox

Page 109: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы

Page 110: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы

Page 111: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Lua простой для изучения

Page 112: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Lua простой для изучения

Page 113: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Lua простой для изучения

• Lua удобен для встраивания

Page 114: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Lua простой для изучения

• Lua удобен для встраивания

Page 115: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы

Page 116: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Основной инструмент - таблицы

Page 117: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Основной инструмент - таблицы

Page 118: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Основной инструмент - таблицы

• Основной инструмент - функции

Page 119: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Основной инструмент - таблицы

• Основной инструмент - функции

Page 120: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы

Page 121: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Lua - быстрый язык (особенно LuaJIT)

Page 122: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Lua - быстрый язык (особенно LuaJIT)

Page 123: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Lua - быстрый язык (особенно LuaJIT)

• Некоторые оптимизации бывают опасны

Page 124: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Выводы• Lua - быстрый язык (особенно LuaJIT)

• Некоторые оптимизации бывают опасны

Page 125: Практика совместного использования Lua и C в opensource спам-фильтре Rspamd / Всеволод Стахов (University of Cambridge, Mimecast)

Всеволод Стахов [email protected]

Вопросы