37
Применение кодогенерации для оптимизации Игорь Чевдарь

Кодогенерация на службе оптимизации, Игорь Чевдарь, СКБ Контур

Embed Size (px)

Citation preview

Применение кодогенерациидля оптимизации

Игорь Чевдарь

Неасимптотическиеоптимизации

• Предположим, что асимптотика алгоритма уже наилучшая

• Но надо еще быстрее

Задача 1. Регулярные выражения

• Алгоритм по регулярному выражению строит какую-то автоматоподобную структуру

[\-+]?[0-9]+(\.[0-9]*)?

Принимает Отвергает

7 +0. -12 +00.15 + 0z --0.0 .0

public class Node{

public map<char, Node> jumps;public bool accepted;…

}

bool Match(string str){

Node current = start;for (int i = 0; i < str.Length; ++i){

current = current.jumps[str[i]];if (current == null)

return false;}return current.accepted;

}

public abstract class Node

{

public bool accepted;

public abstract Node Jump(char c);

}

public class NodeImpl : Node

{

private map<char, Node> jumps;

public override Node Jump(char c)

{

return jumps[c];

}

}

bool Match(string str)

{

Node current = start;

for (int i = 0; i < str.Length; ++i)

{

current = current.Jump(str[i]);

if (current == null)

return false;

}

return current.accepted;

}

public class NodeWithThreeChildren : Node

{

private Node child_a;

private Node child_b;

private Node child_c;

public override Node Jump(char c)

{

if (c == 'a')

return child_a;

if (c == 'b')

return child_b;

if (c == 'c')

return child_c;

return null;

}

}

public class NodeJumpByAZ : Node{

private Node child;

public override Node Jump(char c){

if (c >= 'a' && c <= 'z')return child;

if (c >= 'A' && c <= 'Z')return child;

return null;}

}

public class NodeJumpSegment : Node{

private Node[] children;private char start;private char finish;

public override Node Jump(char c){

if (c >= start && c <= finish)return children[c - start];

return null;}

}

bool Match(string str)

{

Node current = start;

for (int i = 0; i < str.Length; ++i)

{

current = current.Jump(str[i]);

if (current == null)

return false;

}

return current.accepted;

}

bool Match(string str){

Node current = start;for (int i = 0; i < str.Length; ++i){

if (current == s1){

// Реализация метода Jump для s1}else if (current == s2){

// Реализация метода Jump для s2}…else if (current == sn){

// Реализация метода Jump для sn}else

return false;}return current.accepted;

}

if (current == s1)

{

if (str[i] == 'a')

current = s2;

else if (str[i] == 'b')

current = s3;

else …

}

[\-+]?[0-9]+(\.[0-9]*)?

bool Match(string str){

int idx = 0;int len = str.Length;char c;

_1: if (idx >= len)return false;

c = str[idx++];if (c == '+' || c == '-')

goto _2;if (c >= '0' && c <= '9')

goto _3;return false;

_2: if (idx >= len)return false;

c = str[idx++];if (c >= '0' && c <= '9')

goto _3;return false;

_3: if (idx >= len)return true;

c = str[idx++];if (c >= '0' && c <= '9')

goto _3;if (c == '.')

goto _4;return false;

_4: if (idx >= len)return true;

c = str[idx++];if (c >= '0' && c <= '9')

goto _4;return false;

}

Способы кодогенерации

• Пишем текст в файл и вызываем компилятор

Способы кодогенерации

• Пишем текст в файл и вызываем компилятор

• Байткод (JASM, IL, ASM)

Способы кодогенерации

• Пишем текст в файл и вызываем компилятор

• Байткод (JASM, IL, ASM)

• Roslyn (.NET)

13.1

22.6

1

1.9

10.3

C# Regex compiled

C# Regex

Inlined автомат

Автомат без хэш-таблицы

Автомат с хэш-таблицей

Результаты

Время

Задача 2. Валидация xml

• На вход поступают xml-файлы

• Есть правила валидации, сложнее, чем xsd

Total = AttrA + AttrB – Abs(AttrC) – Abs(AttrD) + AttrE

/File

/Document

/Income

<Income Total="100" AttrA="1"

AttrB="2" AttrC="-3"

AttrD="4" AttrE="5" />

Алгоритм

• Парсим настройки в дерево:

• Данные кладем в map<>

Sum

AttrA

AttrB

Negate Abs AttrC

Negate Abs AttrD

AttrE

public abstract class Operation

{

public abstract decimal Exec(map<string, decimal> arguments);

}

public class ArgumentOperation : Operation

{

private string operand;

public override decimal Exec(map<string, decimal> arguments)

{

return arguments[operand];

}

}

public abstract class Operation

{

public abstract decimal Exec(map<string, decimal> arguments);

}

public class SumOperation : Operation

{

private Operation[] children;

public override decimal Exec(map<string, decimal> arguments)

{

decimal result = 0;

foreach (Operation child in children)

result = result + child.Exec(arguments);

return result;

}

}

// Чтение данных

arguments["Total"] = 100;

arguments["AttrA"] = 1;

arguments["AttrB"] = 2;

arguments["AttrC"] = -3;

arguments["AttrD"] = 4;

arguments["AttrE"] = 5;

// Проверка

void Check()

{

var expected = arguments["Total"];

var actual =

SumOperation.Exec(

ArgumentOperation.Exec("AttrA"),

ArgumentOperation.Exec("AttrB"),

NegateOperation.Exec(

AbsOperation.Exec(

ArgumentOperation.Exec("AttrC"))

),

NegateOperation.Exec(

AbsOperation.Exec(

ArgumentOperation.Exec("AttrD"))

),

ArgumentOperation.Exec("AttrE")

);

if(expected != actual)

RaiseError();

}

public class Closure{

public decimal Total;public decimal AttrA;public decimal AttrB;public decimal AttrC;public decimal AttrD;public decimal AttrE;

}

// Чтение данныхclosure.Total = 100;closure.AttrA = 1;closure.AttrB = 2;closure.AttrC = -3;closure.AttrD = 4;closure.AttrE = 5;…

// Проверкаvoid Check(){

var expected = closure.Total;var actual = closure.AttrA

+ closure.AttrB– Math.Abs(closure.AttrC)- Math.Abs(closure.AttrD)+ closure.AttrE;

if(expected != actual)RaiseError();

}

Результаты

• Этот пример взят из сервиса форм Контур Экстерна

• Нужно валидировать xml-файлы размером до нескольких гигабайт

Результаты

• Этот пример взят из сервиса форм Контур Экстерна

• Нужно валидировать xml-файлы размером до нескольких гигабайт

• После применения метода кодогенерациивалидация работает в 20 раз быстрее

Еще примеры

• Сериализация/десериализация данных

Еще примеры

• Сериализация/десериализация данных

• Выполнение SQL-запросов в in memory индексе

Вывод

Вывод

• Преимущества• Прирост производительности

Вывод

• Преимущества• Прирост производительности

• Код красивый и оптимальный

Вывод

• Преимущества• Прирост производительности

• Код красивый и оптимальный

• Недостатки• Технически сложная задача

Вывод

• Преимущества• Прирост производительности

• Код красивый и оптимальный

• Недостатки• Технически сложная задача

• Большее время разогрева

Вывод

• Преимущества• Прирост производительности

• Код красивый и оптимальный

• Недостатки• Технически сложная задача

• Большее время разогрева

• Возможен прирост использования памяти

Спасибо за внимание

e-mail: [email protected]

e-mail: [email protected]

Вопросы