SlideShare une entreprise Scribd logo
1  sur  25
ОПТИМИЗАЦИЯ ТРАССИРОВАНИЯ С
ИСПОЛЬЗОВАНИЕМ EXPRESSION TEMPLATES
Игорь Гусаров
Software Expert, Kaspersky Lab
БУДЕМ ГОВОРИТЬ О FRONT-END
2
СКОЛЬКО СТОИТ ОТЛАДОЧНЫЙ ВЫВОД
КТО ВИНОВАТ И ЧТО ДЕЛАТЬ
РЕЗУЛЬТАТЫ И ПЛАНЫ22
7
3
Ради большей наглядности фрагменты исходного текста C++ приведены на слайдах в упрощённом виде.
Или история про то, как маленькая функция раздулась до десяти
килобайт кода.
СКОЛЬКО СТОИТ ОТЛАДОЧНЫЙ ВЫВОД
PERFORMANCE TEAM
4
Исследует производительность программ и их влияние на
производительность ОС.
- задержки при Startup / Boot / Hibernate / Resume;
- профилирование, поиск узких мест;
- оптимизация основных сценариев;
- контроль потребления ресурсов.
Проблема: рыхлый код
ПРОВЕДЁМ ЭКСПЕРИМЕНТ
5
1. Возьмём реальный продукт - KIS 2015.
2. Вырежем для опытов фрагмент на 3 млн строк.
3. Сколько в нём отладочного вывода? 15 тыс строк.
4. Как изменится размер исполняемых модулей,
если выкинуть весь отладочный вывод?
10%
объёма исполняемых модулей
0,5%
строк исходного текста C++
СИНТЕТИЧЕСКИЙ ПРИМЕР
6
void TestTraceStream()
{
TRACE(level) << "Hello" << ' ' << "World!";
SomeFunc();
}
void TestTracePrintf()
{
TRACE(level, "%s%c%s", "Hello", ' ', "World!");
SomeFunc();
}
подготовка
вывод сообщения
полезная нагрузка
Разберёмся в деталях - откуда взялось так много кода и как сделать
так, чтобы его стало меньше.
КТО ВИНОВАТ И ЧТО ДЕЛАТЬ
#define MY_WARN() TRACE_WARN() << "MyClass(" << this << ")::" FUNCTION " "
#define LOGGED_RETURN(code) do { MY_WARN() << (code); return (code); } while(0)
// Now replace every 'return' with 'LOGGED_RETURN'
void Service::Method()
{
try
{
TRACE_INFO() << "Trying";
DoSomething();
}
catch (...)
{
TRACE_ERR() << "Failed";
}
}
void Service::~Service()
{
TRACE_INFO() << "Done " << m_filename;
}
ЧТО ПИШУТ РАЗРАБОТЧИКИ
8
ЧТО ДОЛЖЕН УМЕТЬ ТРАССИРОВЩИК
9
1. Использовать синтаксис потоков вывода C++.
Поскольку он всем знаком, и давно используется в кодовой базе.
2. Выводить любые типы данных.
И чтобы разработчикам не требовалось писать ничего сложнее привычного оператора << для нового типа.
3. Работать из разных потоков (threads).
Не создавая конкуренции. Простаивать на синхронизации из-за отладочного вывода - это последнее дело.
4. Не создавать лишних исключений.
Мало кому понравится, если отладочный вывод начнёт влиять на ход работы смыслового кода.
5. Не вычислять выводимые значения, если они не нужны.
И вообще тратить минимум усилий на выражения, которые не должны выводиться.
ЧТО СКРЫВАЕТСЯ ЗА МАКРОСАМИ
10
if (!ShouldTrace(GET_TRACER(), LevelWarn))
(void)0;
else
MakeTraceStream(GET_TRACER(), LevelWarn) << ...
if (const TraceHolder& h = TraceHolder(GET_TRACER(), LevelWarn))
(void)0;
else
MakeTraceStream(h.tracer, h.level).SelfRef() << ...MakeTraceStream(h.tracer, h.level).SelfRef() << ...
#define MY_WARN() TRACE_WARN() << "MyClass(" << this << ")::" FUNCTION " "
ЧТО ВЫНУЖДЕН ДЕЛАТЬ КОМПИЛЯТОР
11
MakeTraceStream(tracer, level).SelfRef() << foo() << "data size = " << m_x ;
Не оптимальный по размеру и простоте машинный код
Необходим код
раскрутки стека
Захват критической секции
или создание буфера
Выход: требуется
деструктор
Инлайн-подстановка
операторов вывода
Вход: создание
временного объекта
MakeTraceStream(h.tracer, h.level).SelfRef() << ...
ЧТО БУДЕМ ОПТИМИЗИРОВАТЬ
12
Необходим код
раскрутки стека
Инлайн-подстановка
операторов вывода
Вход: создание
временного объекта3. Избавимся от повторяющегося кода.
Будь то инлайн-подстановка или инстанциация кучи сложных функций.
2. Минимизируем объём кода в точке вызова.
Особенно тех инструкций, которые выполняются при выключенном выводе.
1. Избавимся от кода обработки исключений.
Не пожертвовав при этом ни exception safety, ни thread safety.
MakeTraceStream(tracer, level).SelfRef() << foo() << "data size = " << m_x ;tracer level foo() "data size = " m_xMakeTraceStream SelfRef << << << ;
Надо вычислять на месте
Эти вычисления можно вынести в отдельную общую функцию
КАК БУДЕМ ОПТИМИЗИРОВАТЬ
13
MakeTraceStream(tracer, level).SelfRef() << foo() << "data size = " << m_x ;
TracePut(tracer, { level, foo(), "data size = ", m_x });
tracer <<= KLTRACE_LAZY_OUTPUT() << level << foo() << "data size = " << m_x;
tracer <<= SomeSpecialType() << level << foo() << "data size = " << m_x;
1
что
2
куда
3
как
ЧТО ДАЮТ EXPRESSION TEMPLATES
14
a + b * c
ExprPlus< Ta, ExprMult< Tb, Tc > >
&a, &b, &c
тип :
содержимое :
SomeSpecialType() << level << foo() << "data size = " << m_x;
ArgumentPack<Typelist<> >
ArgumentPack<Typelist<level_t> >
ArgumentPack<Typelist<level_t, long> >
ArgumentPack<Typelist<level_t, long, const char [13]> >
ArgumentPack<Typelist<level_t, long, const char [13], int> > &a1 &a2 &a3 &a4
&a1 &a2 &a3
&a1 &a2
&a1
Они позволяют сформировать кортеж из аргументов, отложив вычисления на потом.
ВОЛШЕБНЫЙ ОПЕРАТОР <<=
15
template <typename TracerType, typename Typelist>
TracerType& operator<<=(TracerType& tracer, const ArgumentPack<Typelist>& args);
Задача: убрать параметризацию функции вывода по Typelist.
Заменим параметризацию типом на параметризацию данными.
ArgumentPack
const T1* p1
const T2* p2
const Tn* pn
...
{
const Descriptor* d = &DescriptorsFor<TracerType, Typelist>::head;
DoOutput<TracerType>(tracer, args.begin(), d);
}
1-2 типа несколько тысяч комбинаций
addr p1; func* f1
addr p2; func* f2
addr pn; func* fn
...
addr p1
addr p2
addr pn
...
+
func* f1
func* f2
func* fn
...
NULL
ВЫВОД ОДНОГО ЗНАЧЕНИЯ
16
WorkerFunc
Функция с неизменным типом аргументов, которая выводит конкретный тип данных в конкретный тип потока.
template <typename TracerType, typename ValueType>
void OutputWorker(void* tracer, addr_t valuePtr)
{
*(TracerType*)tracer << *(const ValueType*)valuePtr;
}
СТАТИЧЕСКАЯ ИНИЦИАЛИЗАЦИЯ СПИСКА
17
struct Descriptor
{
WorkerFunc* worker;
const Descriptor* next;
};
// DescriptorsFor consists of a single static member named 'head'.
template <typename TracerType, typename Typelist>
const Descriptor DescriptorsFor<TracerType, Typelist>::head =
{
WorkerFunc<TracerType, Typelist::Head>,
&DescriptorsFor<TracerType, Typelist::Tail>
};
Descriptor
Статически инициализируемый список из ссылок на рабочие функции.
ВЫВОД ВСЕГО ВЫРАЖЕНИЯ
18
template <typename TracerType>
void DoOutput(TracerType& tracer, const addr_t* args, const Descriptor* d)
{
try
{
output_traits<TracerType>::actual_type actualStream(tracer);
for (int i = 0; d; ++i, d = d->next)
d->worker(&actualStream, args[i]);
}
catch (...)
{
}
}
DoOutput
Единая функция для любых операций вывода.
ПРИЯТНЫЕ ОСОБЕННОСТИ
19
1. Простые типы можно класть в ArgumentPack по значению.
template <typename T> struct PackTraits : PackByRef {};
template <> struct PackTraits<int> : PackByVal {};
2. Макрос можно использовать с любым потоковым выводом.
char buf[128];
buf <<= KLTRACE_LAZY_OUTPUT() << "Hello, " << n << " Worlds!";
3. Метод годится для цепочки любых однородных операторов.
dst <<= KLTRACE_LAZY_FORMAT("Hello, %1 %2!n") % n % m_who;
filename <<= KLTRACE_LAZY_PATH() / diskRoot / m_configPath / "config.xml";
4. Можно получить несколько функций на каждый аргумент.
my_container <<= KLTRACE_LAZY_APPEND() + my_vector + my_list + my_range;
// instantiates begin() and end() for each source.
НЕПРИЯТНЫЕ ОСОБЕННОСТИ
20
2. Возможна неоднозначность при выборе оператора <<.
1. Операторы вывода должны быть видны для ADL.
namespace myproj
{
template <typename AnyStream, typename T1, typename T2>
Stream& operator<<(AnyStream& os, const std::pair<T1, T2>& arg);
void foo(const std::pair<int, int>& data)
{
TRACE_INFO() << data; // Compilation error. Could be solved in C++11
}
} // namespace myproj
template <typename Stream> operator<<(const Stream& os, const MyType& arg);
template <typename X> operator<<(const ArgumentPack& os, const X& arg);
ArgumentPack() << MyType(); // неоднозначность
НЕПРИЯТНЫЕ ОСОБЕННОСТИ
21
3. Нужны специальные меры для вывода std::endl.
template <typename Char, typename Traits>
basic_ostream<Char, Traits>& endl(basic_ostream<Char, Traits>& os);
struct AbstractManipulator; // умеет инициаизироваться выражением std::endl
template <typename Typelist>
operator<<(const ArgumentPack& os, const AbstractManipulator& manip);
4. Нельзя подменять поток в процессе вычисления выражения.
template <typename AnyStream>
CommaInserterStream<AnyStream> operator<<(AnyStream& os, MyCoolManip*);
5. При выключенной оптимизации код становится только хуже.
Для эффективной упаковки аргументов в кортеж обязательно нужна инлайн-подстановка.
Победа!
РЕЗУЛЬТАТЫ
СИНТЕТИЧЕСКИЙ ПРИМЕР
23
void TestTraceStream()
{
TRACE(level) << "Hello" << ' ' << "World!";
SomeFunc();
}
void TestTracePrintf()
{
TRACE(level, "%s%c%s", "Hello", ' ', "World!");
SomeFunc();
}
Stream Printf Expr. Templates
ВОПРОСЫ?
Kaspersky Lab HQ
39A/3 Leningradskoe Shosse
Moscow, 125212, Russian Federation
Tel: +7 (495) 797-8700
www.kaspersky.com
ССЫЛКИ И КОНТАКТЫ
25
"Pimp my log", Marc Eaddy http://www.youtube.com/watch?v=TS_waQZcZVc
Эти слайды доступны на http://meetingcpp.ru/
Пример кода доступен там http://meetingcpp.ru/
Игорь Гусаров Igor.Gusarov@kaspersky.com
Александр Леденев Alexander.Ledenev@kaspersky.com
Андрей Солодовников Andrey.Solodovnikov@kaspersky.com

Contenu connexe

Tendances

Юнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, GoogleЮнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, Googleyaevents
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Dima Dzuba
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияSergey Platonov
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Sergey Platonov
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptSergey Platonov
 
Аскетичная разработка браузера
Аскетичная разработка браузераАскетичная разработка браузера
Аскетичная разработка браузераPlatonov Sergey
 
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Noveo
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаSergey Platonov
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерSergey Platonov
 
Пояснения к статье про Copy-Paste
Пояснения к статье про Copy-PasteПояснения к статье про Copy-Paste
Пояснения к статье про Copy-PasteTatyanazaxarova
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Platonov Sergey
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Sergey Platonov
 
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Platonov Sergey
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Yauheni Akhotnikau
 
Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Tatyanazaxarova
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияPlatonov Sergey
 
Филипп Ковалев — Путь в npm
Филипп Ковалев — Путь в npmФилипп Ковалев — Путь в npm
Филипп Ковалев — Путь в npmYandex
 

Tendances (20)

C++ exceptions
C++ exceptionsC++ exceptions
C++ exceptions
 
Юнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, GoogleЮнит-тестирование и Google Mock. Влад Лосев, Google
Юнит-тестирование и Google Mock. Влад Лосев, Google
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизация
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 
бегун
бегунбегун
бегун
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
 
Аскетичная разработка браузера
Аскетичная разработка браузераАскетичная разработка браузера
Аскетичная разработка браузера
 
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптер
 
Пояснения к статье про Copy-Paste
Пояснения к статье про Copy-PasteПояснения к статье про Copy-Paste
Пояснения к статье про Copy-Paste
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
 
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического ана...
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
 
Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализация
 
бегун
бегунбегун
бегун
 
Филипп Ковалев — Путь в npm
Филипп Ковалев — Путь в npmФилипп Ковалев — Путь в npm
Филипп Ковалев — Путь в npm
 

En vedette

Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на QtДенис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на QtSergey Platonov
 
Конверсия управляемых языков в неуправляемые
Конверсия управляемых языков в неуправляемыеКонверсия управляемых языков в неуправляемые
Конверсия управляемых языков в неуправляемыеPlatonov Sergey
 
Categories for the Working C++ Programmer
Categories for the Working C++ ProgrammerCategories for the Working C++ Programmer
Categories for the Working C++ ProgrammerPlatonov Sergey
 
Debugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template MetaprogramsDebugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template MetaprogramsPlatonov Sergey
 
Алексей Кутумов, Coroutines everywhere
Алексей Кутумов, Coroutines everywhereАлексей Кутумов, Coroutines everywhere
Алексей Кутумов, Coroutines everywhereSergey Platonov
 
Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Sergey Platonov
 
Антон Полухин. C++17
Антон Полухин. C++17Антон Полухин. C++17
Антон Полухин. C++17Sergey Platonov
 
Multithreading done right
Multithreading done rightMultithreading done right
Multithreading done rightPlatonov Sergey
 
High quality library from scratch
High quality library from scratchHigh quality library from scratch
High quality library from scratchPlatonov Sergey
 
Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного бага
Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного багаЛев Казаркин, Удивительные приключения регистров SSE или в поисках одного бага
Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного багаSergey Platonov
 
Метаобъектная система Qt
Метаобъектная система QtМетаобъектная система Qt
Метаобъектная система QtPlatonov Sergey
 
С++ without new and delete
С++ without new and deleteС++ without new and delete
С++ without new and deletePlatonov Sergey
 
Библиотека Boost с нуля на примере Boost.DLL
Библиотека Boost с нуля на примере Boost.DLLБиблиотека Boost с нуля на примере Boost.DLL
Библиотека Boost с нуля на примере Boost.DLLPlatonov Sergey
 
Address/Thread/Memory Sanitizer
Address/Thread/Memory SanitizerAddress/Thread/Memory Sanitizer
Address/Thread/Memory SanitizerPlatonov Sergey
 
Конкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыКонкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыPlatonov Sergey
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IPlatonov Sergey
 
Практика использования Dependency Injection
Практика использования Dependency InjectionПрактика использования Dependency Injection
Практика использования Dependency InjectionPlatonov Sergey
 
Практика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-серверПрактика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-серверPlatonov Sergey
 

En vedette (20)

Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на QtДенис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
 
Конверсия управляемых языков в неуправляемые
Конверсия управляемых языков в неуправляемыеКонверсия управляемых языков в неуправляемые
Конверсия управляемых языков в неуправляемые
 
Categories for the Working C++ Programmer
Categories for the Working C++ ProgrammerCategories for the Working C++ Programmer
Categories for the Working C++ Programmer
 
Debugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template MetaprogramsDebugging and Profiling C++ Template Metaprograms
Debugging and Profiling C++ Template Metaprograms
 
Алексей Кутумов, Coroutines everywhere
Алексей Кутумов, Coroutines everywhereАлексей Кутумов, Coroutines everywhere
Алексей Кутумов, Coroutines everywhere
 
Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >
 
Антон Полухин. C++17
Антон Полухин. C++17Антон Полухин. C++17
Антон Полухин. C++17
 
Multithreading done right
Multithreading done rightMultithreading done right
Multithreading done right
 
High quality library from scratch
High quality library from scratchHigh quality library from scratch
High quality library from scratch
 
Цена ошибки
Цена ошибкиЦена ошибки
Цена ошибки
 
Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного бага
Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного багаЛев Казаркин, Удивительные приключения регистров SSE или в поисках одного бага
Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного бага
 
Метаобъектная система Qt
Метаобъектная система QtМетаобъектная система Qt
Метаобъектная система Qt
 
С++ without new and delete
С++ without new and deleteС++ without new and delete
С++ without new and delete
 
Библиотека Boost с нуля на примере Boost.DLL
Библиотека Boost с нуля на примере Boost.DLLБиблиотека Boost с нуля на примере Boost.DLL
Библиотека Boost с нуля на примере Boost.DLL
 
Address/Thread/Memory Sanitizer
Address/Thread/Memory SanitizerAddress/Thread/Memory Sanitizer
Address/Thread/Memory Sanitizer
 
Конкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыКонкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнеры
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
 
Практика использования Dependency Injection
Практика использования Dependency InjectionПрактика использования Dependency Injection
Практика использования Dependency Injection
 
Generic programming
Generic programmingGeneric programming
Generic programming
 
Практика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-серверПрактика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-сервер
 

Similaire à Оптимизация трассирования с использованием Expression templates

static - defcon russia 20
static  - defcon russia 20static  - defcon russia 20
static - defcon russia 20DefconRussia
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioAndrey Karpov
 
Тестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиТестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиZestranec
 
Тестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиТестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиSQALab
 
High Load 2009 Dimaa Rus Ready 16 9
High Load 2009 Dimaa Rus Ready 16 9High Load 2009 Dimaa Rus Ready 16 9
High Load 2009 Dimaa Rus Ready 16 9HighLoad2009
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1Michael Karpov
 
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Mikhail Kurnosov
 
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Mikhail Kurnosov
 
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...Ontico
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода Pavel Tsukanov
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кодаAndrey Karpov
 
анализ кода: от проверки стиля до автоматического тестирования
анализ кода: от проверки стиля до автоматического тестированияанализ кода: от проверки стиля до автоматического тестирования
анализ кода: от проверки стиля до автоматического тестированияRuslan Shevchenko
 
Всё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программистаВсё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программистаAndrey Karpov
 
Как выглядит современный фронтенд
Как выглядит современный фронтендКак выглядит современный фронтенд
Как выглядит современный фронтендTimophy Chaptykov
 
Семь тысяч Rps, один go
Семь тысяч Rps, один goСемь тысяч Rps, один go
Семь тысяч Rps, один goBadoo Development
 
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестов
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестовЮлия Ковалёва. Fscheck — альтернативный путь для unit тестов
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестовMskDotNet Community
 
Лекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPЛекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPMikhail Kurnosov
 
PHP Tricks
PHP TricksPHP Tricks
PHP TricksBlackFan
 

Similaire à Оптимизация трассирования с использованием Expression templates (20)

static - defcon russia 20
static  - defcon russia 20static  - defcon russia 20
static - defcon russia 20
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
Тестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиТестирование программных фильтров безопасности
Тестирование программных фильтров безопасности
 
Programming c++ (begin-if-else)
Programming c++ (begin-if-else)Programming c++ (begin-if-else)
Programming c++ (begin-if-else)
 
Тестирование программных фильтров безопасности
Тестирование программных фильтров безопасностиТестирование программных фильтров безопасности
Тестирование программных фильтров безопасности
 
High Load 2009 Dimaa Rus Ready 16 9
High Load 2009 Dimaa Rus Ready 16 9High Load 2009 Dimaa Rus Ready 16 9
High Load 2009 Dimaa Rus Ready 16 9
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1
 
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
Лекция 7: Многопоточное программирование: часть 3 (OpenMP)
 
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
Лекция 7: Фибоначчиевы кучи (Fibonacci heaps)
 
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
 
PowerShell
PowerShellPowerShell
PowerShell
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кода
 
анализ кода: от проверки стиля до автоматического тестирования
анализ кода: от проверки стиля до автоматического тестированияанализ кода: от проверки стиля до автоматического тестирования
анализ кода: от проверки стиля до автоматического тестирования
 
Всё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программистаВсё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программиста
 
Как выглядит современный фронтенд
Как выглядит современный фронтендКак выглядит современный фронтенд
Как выглядит современный фронтенд
 
Семь тысяч Rps, один go
Семь тысяч Rps, один goСемь тысяч Rps, один go
Семь тысяч Rps, один go
 
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестов
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестовЮлия Ковалёва. Fscheck — альтернативный путь для unit тестов
Юлия Ковалёва. Fscheck — альтернативный путь для unit тестов
 
Лекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMPЛекция 6. Стандарт OpenMP
Лекция 6. Стандарт OpenMP
 
PHP Tricks
PHP TricksPHP Tricks
PHP Tricks
 

Plus de Platonov Sergey

Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3Platonov Sergey
 
Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Platonov Sergey
 
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговлеТененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговлеPlatonov Sergey
 
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на LinuxПавел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на LinuxPlatonov Sergey
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IIДмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IIPlatonov Sergey
 
QML\Qt Quick на практике
QML\Qt Quick на практикеQML\Qt Quick на практике
QML\Qt Quick на практикеPlatonov Sergey
 
Визуализация автомобильных маршрутов
Визуализация автомобильных маршрутовВизуализация автомобильных маршрутов
Визуализация автомобильных маршрутовPlatonov Sergey
 
Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++Platonov Sergey
 
HPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычисленийHPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычисленийPlatonov Sergey
 
Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08Platonov Sergey
 
Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...Platonov Sergey
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияДракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияPlatonov Sergey
 
One definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим житьOne definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим житьPlatonov Sergey
 
Денис Кормалев Метаобъектная система Qt
Денис Кормалев Метаобъектная система QtДенис Кормалев Метаобъектная система Qt
Денис Кормалев Метаобъектная система QtPlatonov Sergey
 
Максим Хижинский Lock-free maps
Максим Хижинский Lock-free mapsМаксим Хижинский Lock-free maps
Максим Хижинский Lock-free mapsPlatonov Sergey
 
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Platonov Sergey
 
Оптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesОптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesPlatonov Sergey
 

Plus de Platonov Sergey (18)

Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3
 
Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.
 
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговлеТененёв Анатолий, Boost.Asio в алгоритмической торговле
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
 
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на LinuxПавел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IIДмитрий Кашицын, Вывод типов в динамических и не очень языках II
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
 
QML\Qt Quick на практике
QML\Qt Quick на практикеQML\Qt Quick на практике
QML\Qt Quick на практике
 
Визуализация автомобильных маршрутов
Визуализация автомобильных маршрутовВизуализация автомобильных маршрутов
Визуализация автомобильных маршрутов
 
Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++Функциональный микроскоп: линзы в C++
Функциональный микроскоп: линзы в C++
 
HPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычисленийHPX: C++11 runtime система для параллельных и распределённых вычислений
HPX: C++11 runtime система для параллельных и распределённых вычислений
 
Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08Ranges calendar-novosibirsk-2015-08
Ranges calendar-novosibirsk-2015-08
 
Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...Использование maven для сборки больших модульных c++ проектов на примере Odin...
Использование maven для сборки больших модульных c++ проектов на примере Odin...
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияДракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
 
One definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим житьOne definition rule - что это такое, и как с этим жить
One definition rule - что это такое, и как с этим жить
 
Concepts lite
Concepts liteConcepts lite
Concepts lite
 
Денис Кормалев Метаобъектная система Qt
Денис Кормалев Метаобъектная система QtДенис Кормалев Метаобъектная система Qt
Денис Кормалев Метаобъектная система Qt
 
Максим Хижинский Lock-free maps
Максим Хижинский Lock-free mapsМаксим Хижинский Lock-free maps
Максим Хижинский Lock-free maps
 
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
 
Оптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templatesОптимизация трассирования с использованием Expression templates
Оптимизация трассирования с использованием Expression templates
 

Оптимизация трассирования с использованием Expression templates

  • 1. ОПТИМИЗАЦИЯ ТРАССИРОВАНИЯ С ИСПОЛЬЗОВАНИЕМ EXPRESSION TEMPLATES Игорь Гусаров Software Expert, Kaspersky Lab
  • 2. БУДЕМ ГОВОРИТЬ О FRONT-END 2 СКОЛЬКО СТОИТ ОТЛАДОЧНЫЙ ВЫВОД КТО ВИНОВАТ И ЧТО ДЕЛАТЬ РЕЗУЛЬТАТЫ И ПЛАНЫ22 7 3 Ради большей наглядности фрагменты исходного текста C++ приведены на слайдах в упрощённом виде.
  • 3. Или история про то, как маленькая функция раздулась до десяти килобайт кода. СКОЛЬКО СТОИТ ОТЛАДОЧНЫЙ ВЫВОД
  • 4. PERFORMANCE TEAM 4 Исследует производительность программ и их влияние на производительность ОС. - задержки при Startup / Boot / Hibernate / Resume; - профилирование, поиск узких мест; - оптимизация основных сценариев; - контроль потребления ресурсов. Проблема: рыхлый код
  • 5. ПРОВЕДЁМ ЭКСПЕРИМЕНТ 5 1. Возьмём реальный продукт - KIS 2015. 2. Вырежем для опытов фрагмент на 3 млн строк. 3. Сколько в нём отладочного вывода? 15 тыс строк. 4. Как изменится размер исполняемых модулей, если выкинуть весь отладочный вывод? 10% объёма исполняемых модулей 0,5% строк исходного текста C++
  • 6. СИНТЕТИЧЕСКИЙ ПРИМЕР 6 void TestTraceStream() { TRACE(level) << "Hello" << ' ' << "World!"; SomeFunc(); } void TestTracePrintf() { TRACE(level, "%s%c%s", "Hello", ' ', "World!"); SomeFunc(); } подготовка вывод сообщения полезная нагрузка
  • 7. Разберёмся в деталях - откуда взялось так много кода и как сделать так, чтобы его стало меньше. КТО ВИНОВАТ И ЧТО ДЕЛАТЬ
  • 8. #define MY_WARN() TRACE_WARN() << "MyClass(" << this << ")::" FUNCTION " " #define LOGGED_RETURN(code) do { MY_WARN() << (code); return (code); } while(0) // Now replace every 'return' with 'LOGGED_RETURN' void Service::Method() { try { TRACE_INFO() << "Trying"; DoSomething(); } catch (...) { TRACE_ERR() << "Failed"; } } void Service::~Service() { TRACE_INFO() << "Done " << m_filename; } ЧТО ПИШУТ РАЗРАБОТЧИКИ 8
  • 9. ЧТО ДОЛЖЕН УМЕТЬ ТРАССИРОВЩИК 9 1. Использовать синтаксис потоков вывода C++. Поскольку он всем знаком, и давно используется в кодовой базе. 2. Выводить любые типы данных. И чтобы разработчикам не требовалось писать ничего сложнее привычного оператора << для нового типа. 3. Работать из разных потоков (threads). Не создавая конкуренции. Простаивать на синхронизации из-за отладочного вывода - это последнее дело. 4. Не создавать лишних исключений. Мало кому понравится, если отладочный вывод начнёт влиять на ход работы смыслового кода. 5. Не вычислять выводимые значения, если они не нужны. И вообще тратить минимум усилий на выражения, которые не должны выводиться.
  • 10. ЧТО СКРЫВАЕТСЯ ЗА МАКРОСАМИ 10 if (!ShouldTrace(GET_TRACER(), LevelWarn)) (void)0; else MakeTraceStream(GET_TRACER(), LevelWarn) << ... if (const TraceHolder& h = TraceHolder(GET_TRACER(), LevelWarn)) (void)0; else MakeTraceStream(h.tracer, h.level).SelfRef() << ...MakeTraceStream(h.tracer, h.level).SelfRef() << ... #define MY_WARN() TRACE_WARN() << "MyClass(" << this << ")::" FUNCTION " "
  • 11. ЧТО ВЫНУЖДЕН ДЕЛАТЬ КОМПИЛЯТОР 11 MakeTraceStream(tracer, level).SelfRef() << foo() << "data size = " << m_x ; Не оптимальный по размеру и простоте машинный код Необходим код раскрутки стека Захват критической секции или создание буфера Выход: требуется деструктор Инлайн-подстановка операторов вывода Вход: создание временного объекта MakeTraceStream(h.tracer, h.level).SelfRef() << ...
  • 12. ЧТО БУДЕМ ОПТИМИЗИРОВАТЬ 12 Необходим код раскрутки стека Инлайн-подстановка операторов вывода Вход: создание временного объекта3. Избавимся от повторяющегося кода. Будь то инлайн-подстановка или инстанциация кучи сложных функций. 2. Минимизируем объём кода в точке вызова. Особенно тех инструкций, которые выполняются при выключенном выводе. 1. Избавимся от кода обработки исключений. Не пожертвовав при этом ни exception safety, ни thread safety. MakeTraceStream(tracer, level).SelfRef() << foo() << "data size = " << m_x ;tracer level foo() "data size = " m_xMakeTraceStream SelfRef << << << ; Надо вычислять на месте Эти вычисления можно вынести в отдельную общую функцию
  • 13. КАК БУДЕМ ОПТИМИЗИРОВАТЬ 13 MakeTraceStream(tracer, level).SelfRef() << foo() << "data size = " << m_x ; TracePut(tracer, { level, foo(), "data size = ", m_x }); tracer <<= KLTRACE_LAZY_OUTPUT() << level << foo() << "data size = " << m_x; tracer <<= SomeSpecialType() << level << foo() << "data size = " << m_x; 1 что 2 куда 3 как
  • 14. ЧТО ДАЮТ EXPRESSION TEMPLATES 14 a + b * c ExprPlus< Ta, ExprMult< Tb, Tc > > &a, &b, &c тип : содержимое : SomeSpecialType() << level << foo() << "data size = " << m_x; ArgumentPack<Typelist<> > ArgumentPack<Typelist<level_t> > ArgumentPack<Typelist<level_t, long> > ArgumentPack<Typelist<level_t, long, const char [13]> > ArgumentPack<Typelist<level_t, long, const char [13], int> > &a1 &a2 &a3 &a4 &a1 &a2 &a3 &a1 &a2 &a1 Они позволяют сформировать кортеж из аргументов, отложив вычисления на потом.
  • 15. ВОЛШЕБНЫЙ ОПЕРАТОР <<= 15 template <typename TracerType, typename Typelist> TracerType& operator<<=(TracerType& tracer, const ArgumentPack<Typelist>& args); Задача: убрать параметризацию функции вывода по Typelist. Заменим параметризацию типом на параметризацию данными. ArgumentPack const T1* p1 const T2* p2 const Tn* pn ... { const Descriptor* d = &DescriptorsFor<TracerType, Typelist>::head; DoOutput<TracerType>(tracer, args.begin(), d); } 1-2 типа несколько тысяч комбинаций addr p1; func* f1 addr p2; func* f2 addr pn; func* fn ... addr p1 addr p2 addr pn ... + func* f1 func* f2 func* fn ... NULL
  • 16. ВЫВОД ОДНОГО ЗНАЧЕНИЯ 16 WorkerFunc Функция с неизменным типом аргументов, которая выводит конкретный тип данных в конкретный тип потока. template <typename TracerType, typename ValueType> void OutputWorker(void* tracer, addr_t valuePtr) { *(TracerType*)tracer << *(const ValueType*)valuePtr; }
  • 17. СТАТИЧЕСКАЯ ИНИЦИАЛИЗАЦИЯ СПИСКА 17 struct Descriptor { WorkerFunc* worker; const Descriptor* next; }; // DescriptorsFor consists of a single static member named 'head'. template <typename TracerType, typename Typelist> const Descriptor DescriptorsFor<TracerType, Typelist>::head = { WorkerFunc<TracerType, Typelist::Head>, &DescriptorsFor<TracerType, Typelist::Tail> }; Descriptor Статически инициализируемый список из ссылок на рабочие функции.
  • 18. ВЫВОД ВСЕГО ВЫРАЖЕНИЯ 18 template <typename TracerType> void DoOutput(TracerType& tracer, const addr_t* args, const Descriptor* d) { try { output_traits<TracerType>::actual_type actualStream(tracer); for (int i = 0; d; ++i, d = d->next) d->worker(&actualStream, args[i]); } catch (...) { } } DoOutput Единая функция для любых операций вывода.
  • 19. ПРИЯТНЫЕ ОСОБЕННОСТИ 19 1. Простые типы можно класть в ArgumentPack по значению. template <typename T> struct PackTraits : PackByRef {}; template <> struct PackTraits<int> : PackByVal {}; 2. Макрос можно использовать с любым потоковым выводом. char buf[128]; buf <<= KLTRACE_LAZY_OUTPUT() << "Hello, " << n << " Worlds!"; 3. Метод годится для цепочки любых однородных операторов. dst <<= KLTRACE_LAZY_FORMAT("Hello, %1 %2!n") % n % m_who; filename <<= KLTRACE_LAZY_PATH() / diskRoot / m_configPath / "config.xml"; 4. Можно получить несколько функций на каждый аргумент. my_container <<= KLTRACE_LAZY_APPEND() + my_vector + my_list + my_range; // instantiates begin() and end() for each source.
  • 20. НЕПРИЯТНЫЕ ОСОБЕННОСТИ 20 2. Возможна неоднозначность при выборе оператора <<. 1. Операторы вывода должны быть видны для ADL. namespace myproj { template <typename AnyStream, typename T1, typename T2> Stream& operator<<(AnyStream& os, const std::pair<T1, T2>& arg); void foo(const std::pair<int, int>& data) { TRACE_INFO() << data; // Compilation error. Could be solved in C++11 } } // namespace myproj template <typename Stream> operator<<(const Stream& os, const MyType& arg); template <typename X> operator<<(const ArgumentPack& os, const X& arg); ArgumentPack() << MyType(); // неоднозначность
  • 21. НЕПРИЯТНЫЕ ОСОБЕННОСТИ 21 3. Нужны специальные меры для вывода std::endl. template <typename Char, typename Traits> basic_ostream<Char, Traits>& endl(basic_ostream<Char, Traits>& os); struct AbstractManipulator; // умеет инициаизироваться выражением std::endl template <typename Typelist> operator<<(const ArgumentPack& os, const AbstractManipulator& manip); 4. Нельзя подменять поток в процессе вычисления выражения. template <typename AnyStream> CommaInserterStream<AnyStream> operator<<(AnyStream& os, MyCoolManip*); 5. При выключенной оптимизации код становится только хуже. Для эффективной упаковки аргументов в кортеж обязательно нужна инлайн-подстановка.
  • 23. СИНТЕТИЧЕСКИЙ ПРИМЕР 23 void TestTraceStream() { TRACE(level) << "Hello" << ' ' << "World!"; SomeFunc(); } void TestTracePrintf() { TRACE(level, "%s%c%s", "Hello", ' ', "World!"); SomeFunc(); } Stream Printf Expr. Templates
  • 24. ВОПРОСЫ? Kaspersky Lab HQ 39A/3 Leningradskoe Shosse Moscow, 125212, Russian Federation Tel: +7 (495) 797-8700 www.kaspersky.com
  • 25. ССЫЛКИ И КОНТАКТЫ 25 "Pimp my log", Marc Eaddy http://www.youtube.com/watch?v=TS_waQZcZVc Эти слайды доступны на http://meetingcpp.ru/ Пример кода доступен там http://meetingcpp.ru/ Игорь Гусаров Igor.Gusarov@kaspersky.com Александр Леденев Alexander.Ledenev@kaspersky.com Андрей Солодовников Andrey.Solodovnikov@kaspersky.com

Notes de l'éditeur

  1. To add background use Background button and choose from drop-down menu. Please mind the size of text areas.
  2. To update contents automatically fill in names of dividing slides and press Update button. Please mind the size of text areas.
  3. To add Dividing slide use Add section, or select from Structure drop down list. When a new Dividing slide is inserted, Content slide will be automatically updated. Please mind the size of text areas.
  4. Please mind the size of text areas.
  5. Please mind the size of text areas.
  6. Please mind the size of text areas.
  7. To add Dividing slide use Add section, or select from Structure drop down list. When a new Dividing slide is inserted, Content slide will be automatically updated. Please mind the size of text areas.
  8. Please mind the size of text areas.
  9. Please mind the size of text areas.
  10. Please mind the size of text areas.
  11. Please mind the size of text areas.
  12. Please mind the size of text areas.
  13. Please mind the size of text areas.
  14. Please mind the size of text areas.
  15. Please mind the size of text areas.
  16. Please mind the size of text areas.
  17. Please mind the size of text areas.
  18. Please mind the size of text areas.
  19. Please mind the size of text areas.
  20. Please mind the size of text areas.
  21. Please mind the size of text areas.
  22. To add Dividing slide use Add section, or select from Structure drop down list. When a new Dividing slide is inserted, Content slide will be automatically updated. Please mind the size of text areas.
  23. Please mind the size of text areas.
  24. The best way to finish your presentation is to place call to action text or contacts. Try to initiate feedback and further communication. Please mind the size of text areas.
  25. Please mind the size of text areas.