SlideShare a Scribd company logo
1 of 58
Download to read offline
Продолжаем говорить о микрооптимизациях
.NET-приложений
Андрей Акиньшин, JetBrains
.NEXT 2015 Moscow
1/32
Про что будем разговаривать?
2/32
Про что будем разговаривать?
Не будет:
• Универсальных способов оптимизации
• Скучной теории
• Подробного устройства .NET, GC, JIT, CPU
2/32
Про что будем разговаривать?
Не будет:
• Универсальных способов оптимизации
• Скучной теории
• Подробного устройства .NET, GC, JIT, CPU
Будет:
• Много весёлых историй1
1
Все истории основаны на реальных событиях
2/32
Roslyn
3/32 Roslyn
Roslyn
Задачка:
void Print(string format,
params object[] args)
{
// ...
}
Print("DotNext"); // Будет ли аллокация?
4/32 Roslyn
Roslyn
Задачка:
void Print(string format,
params object[] args)
{
// ...
}
Print("DotNext"); // Будет ли аллокация?
old csc.exe Roslyn
new object[0] System.Array.Empty<T>1
1
.NET Framework 4.6+
4/32 Roslyn
Boxing
5/32 Boxing
Boxing
Будет ли упаковка/распаковка?
[MethodImpl(MethodImplOptions.NoInlining)]
private static TBase Foo<T, TBase>(T t)
where T : TBase
{
return (TBase) t;
}
6/32 Boxing
Boxing
Будет ли упаковка/распаковка?
[MethodImpl(MethodImplOptions.NoInlining)]
private static TBase Foo<T, TBase>(T t)
where T : TBase
{
return (TBase) t;
}
Взглянем на IL:
IL_0000: ldarg.0 ; t
IL_0001: box 0 ; T
IL_0006: unbox.any 1 ; TBase
IL_000b: ret
6/32 Boxing
Примеры
struct Bar {}
struct Bar<T> {}
Foo<int, int>(1);
Foo<long, long>(2);
Foo<Bar, Bar>(new Bar());
Foo<Bar<int>, Bar<int>>(new Bar<int>());
Foo<Bar<IList>, Bar<IList>>(new Bar<IList>());
7/32 Boxing
Примеры
struct Bar {}
struct Bar<T> {}
Foo<int, int>(1);
Foo<long, long>(2);
Foo<Bar, Bar>(new Bar());
Foo<Bar<int>, Bar<int>>(new Bar<int>());
Foo<Bar<IList>, Bar<IList>>(new Bar<IList>());
Но не сможет ли JIT нам помочь?
7/32 Boxing
Иногда сможет
Foo<int, int>(1);
Foo<long, long>(2);
Foo<Bar, Bar>(new Bar());
Foo<Bar<int>, Bar<int>>(new Bar<int>());
⇓
mov eax,ecx ; (С точностью до регистра)
ret
8/32 Boxing
А иногда нет
Foo<Bar<IList>, Bar<IList>>(new Bar<IList>());
⇓
sub rsp,28h
mov dword ptr [rsp+30h],ecx
mov rax,qword ptr [rsp+30h]
mov rcx,qword ptr [rax+10h]
mov rcx,qword ptr [rcx]
btr rcx,0
cmovb rcx,qword ptr [rcx]
lea rdx,[rsp+38h]
call 00007FF8C37D48D0
mov rdx,rax
mov rax,qword ptr [rsp+30h]
mov rcx,qword ptr [rax+10h]
mov rcx,qword ptr [rcx+8]
btr rcx,0
cmovb rcx,qword ptr [rcx]
call 00007FF8C3896870
mov al,byte ptr [rax]
add rsp,28h
ret
9/32 Boxing
GC
10/32 GC
GC
class Foo
{
public object Bar { get; set; }
}
var foo = new Foo() { Bar = new object() };
// Long live the Bar!
GC.KeepAlive(foo);
11/32 GC
GC
class Foo
{
public object Bar { get; set; }
}
var foo = new Foo() { Bar = new object() };
// Long live the Bar!
GC.KeepAlive(foo);
Уважаемые знатоки, внимание, вопрос:
Может ли string удерживать ссылку на object?
11/32 GC
GC
class Foo
{
public object Bar { get; set; }
}
var foo = new Foo() { Bar = new object() };
// Long live the Bar!
GC.KeepAlive(foo);
Уважаемые знатоки, внимание, вопрос:
Может ли string удерживать ссылку на object?
var foo = "DotNext";
var bar = new object();
BlackBox(); // Что же находится в чёрном ящике?
// Long live the Bar!
GC.KeepAlive(foo);
11/32 GC
GC
Удивительный BCL:
ConditionalWeakTable<TKey, TValue> Class
Enables compilers to dynamically attach object fields to managed objects.
c MSDN
12/32 GC
GC
Удивительный BCL:
ConditionalWeakTable<TKey, TValue> Class
Enables compilers to dynamically attach object fields to managed objects.
c MSDN
А давайте немножко пошалим:
var foo = "DotNext";
var bar = new object();
var cwt = new ConditionalWeakTable<string, object>();
cwt.Add(foo, bar);
String.Intern(foo);
// foo держит ссылку на bar
GC.KeepAlive(cwt);
12/32 GC
OS
13/32 OS
OS
14/32 OS
Guid
15/32 OS
Benchmarks
16/32 Benchmarks
Benchmarks
Что там может быть сложного?
17/32 Benchmarks
Benchmarks
Что там может быть сложного?
// Нужно замерить время?
public double WithoutStopwatch()
{
double a = 1, b = 1;
for (int i = 0; i < 100; i++)
a = a + b;
return a;
}
17/32 Benchmarks
Benchmarks
Что там может быть сложного?
// Нужно замерить время?
public double WithoutStopwatch()
{
double a = 1, b = 1;
for (int i = 0; i < 100; i++)
a = a + b;
return a;
}
// У нас же есть Stopwatch!
public double WithStopwatch()
{
double a = 1, b = 1;
var sw = Stopwatch.Start();
for (int i = 0; i < 100; i++)
a = a + b;
Print(sw.ElapsedMilliseconds);
return a;
}
17/32 Benchmarks
Benchmarks
Что там может быть сложного?
// Нужно замерить время?
public double WithoutStopwatch()
{
double a = 1, b = 1;
for (int i = 0; i < 100; i++)
a = a + b;
return a;
}
// У нас же есть Stopwatch!
public double WithStopwatch()
{
double a = 1, b = 1;
var sw = Stopwatch.Start();
for (int i = 0; i < 100; i++)
a = a + b;
Print(sw.ElapsedMilliseconds);
return a;
}
WithoutStopwatch WithStopwatch
∼100ns ∼350ns
17/32 Benchmarks
Benchmarks
Что там может быть сложного?
// Нужно замерить время?
public double WithoutStopwatch()
{
double a = 1, b = 1;
for (int i = 0; i < 100; i++)
a = a + b;
return a;
}
// У нас же есть Stopwatch!
public double WithStopwatch()
{
double a = 1, b = 1;
var sw = Stopwatch.Start();
for (int i = 0; i < 100; i++)
a = a + b;
Print(sw.ElapsedMilliseconds);
return a;
}
WithoutStopwatch WithStopwatch
∼100ns ∼350ns
; a + b
fld1
faddp st(1),st
; a + b
fld1
fadd qword ptr [ebp-0Ch]
fstp qword ptr [ebp-0Ch]
17/32 Benchmarks
RyuJIT
18/32 RyuJIT
RyuJIT
Если бы вы были JIT-компилятором,
то как бы вы скомпилировали следующий код?
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong RotateRight64(ulong value)
{
return (value >> 1) | (value << 63);
}
19/32 RyuJIT
RyuJIT
Если бы вы были JIT-компилятором,
то как бы вы скомпилировали следующий код?
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong RotateRight64(ulong value)
{
return (value >> 1) | (value << 63);
}
Может быть так?
mov rdx,rax ; value
shr rdx,1 ; value >> 1
shl rax,3Fh ; value << 63
or eax,edx ; (value >> 1) | (value << 63)
19/32 RyuJIT
RyuJIT
Если бы вы были JIT-компилятором,
то как бы вы скомпилировали следующий код?
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong RotateRight64(ulong value)
{
return (value >> 1) | (value << 63);
}
Может быть так?
mov rdx,rax ; value
shr rdx,1 ; value >> 1
shl rax,3Fh ; value << 63
or eax,edx ; (value >> 1) | (value << 63)
Или так?
ror rax,1
19/32 RyuJIT
RyuJIT
Time Percent
ComputeHash 4047ms 100%
RotateRight 1487ms 37%
20/32 RyuJIT
RyuJIT
21/32 RyuJIT
Blittable
22/32 Blittable
Blittable
Загадка для любителей помаршалить:
[StructLayout(LayoutKind.Explicit)]
public struct UInt128
{
[FieldOffset(0)] public ulong Value1;
[FieldOffset(8)] public ulong Value2;
}
22/32 Blittable
Blittable
Загадка для любителей помаршалить:
[StructLayout(LayoutKind.Explicit)]
public struct UInt128
{
[FieldOffset(0)] public ulong Value1;
[FieldOffset(8)] public ulong Value2;
}
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
public UInt128 UInt128;
public char Char;
}
22/32 Blittable
Blittable
Загадка для любителей помаршалить:
[StructLayout(LayoutKind.Explicit)]
public struct UInt128
{
[FieldOffset(0)] public ulong Value1;
[FieldOffset(8)] public ulong Value2;
}
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
public UInt128 UInt128;
public char Char;
}
var myStruct = new MyStruct();
var baseAddress = (int)&myStruct;
var uInt128Address = (int)&myStruct.UInt128;
22/32 Blittable
Blittable
Загадка для любителей помаршалить:
[StructLayout(LayoutKind.Explicit)]
public struct UInt128
{
[FieldOffset(0)] public ulong Value1;
[FieldOffset(8)] public ulong Value2;
}
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
public UInt128 UInt128;
public char Char;
}
var myStruct = new MyStruct();
var baseAddress = (int)&myStruct;
var uInt128Address = (int)&myStruct.UInt128;
Console.WriteLine(uInt128Address - baseAddress); // ???
Console.WriteLine(Marshal.OffsetOf(typeof(MyStruct), "UInt128")); // ???
22/32 Blittable
Blittable
Загадка для любителей помаршалить:
[StructLayout(LayoutKind.Explicit)]
public struct UInt128
{
[FieldOffset(0)] public ulong Value1;
[FieldOffset(8)] public ulong Value2;
}
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
public UInt128 UInt128;
public char Char;
}
var myStruct = new MyStruct();
var baseAddress = (int)&myStruct;
var uInt128Address = (int)&myStruct.UInt128;
Console.WriteLine(uInt128Address - baseAddress); // ???
Console.WriteLine(Marshal.OffsetOf(typeof(MyStruct), "UInt128")); // ???
MS.NET-x86 MS.NET-x64 Mono
Address 4 8 0
Marshal 0 0 0
22/32 Blittable
Memory
Event Latency Scaled
1 CPU cycle 0.3 ns 1 s
Level 1 cache access 0.9 ns 3 s
Level 2 cache access 2.8 ns 9 s
Level 3 cache access 12.9 ns 43 s
Main memory access 120 ns 6 min
Solid-state disk I/O 50-150 µs 2-6 days
Rotational disk I/O 1-10 ms 1-12 months
Internet: SF to NYC 40 ms 4 years
Internet: SF to UK 81 ms 8 years
Internet: SF to Australia 183 ms 19 years
OS virtualization reboot 4 s 423 years
SCSI command time-out 30 s 3000 years
Hardware virtualization reboot 40 s 4000 years
Physical system reboot 5 m 32 millenia
c Systems Performance: Enterprise and the Cloud
23/32 Memory
Memory
Задача: подсчитать сумму элементов массива
const int N = 1024;
int[,] a = new int[N, N];
24/32 Memory
Memory
Задача: подсчитать сумму элементов массива
const int N = 1024;
int[,] a = new int[N, N];
[Benchmark]
public double Sum_ij()
{
var sum = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
sum += a[i, j];
return sum;
}
24/32 Memory
Memory
Задача: подсчитать сумму элементов массива
const int N = 1024;
int[,] a = new int[N, N];
[Benchmark]
public double Sum_ij()
{
var sum = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
sum += a[i, j];
return sum;
}
[Benchmark]
public double Sum_ji()
{
var sum = 0;
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
sum += a[i, j];
return sum;
}
24/32 Memory
Memory
Задача: подсчитать сумму элементов массива
const int N = 1024;
int[,] a = new int[N, N];
[Benchmark]
public double Sum_ij()
{
var sum = 0;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
sum += a[i, j];
return sum;
}
[Benchmark]
public double Sum_ji()
{
var sum = 0;
for (int j = 0; j < N; j++)
for (int i = 0; i < N; i++)
sum += a[i, j];
return sum;
}
Sum_ij() Sum_ji()
∼1.5ms ∼9ms
∗
LegacyJIT-x86, i7-4702MQ CPU @ 2.20GHz
24/32 Memory
Memory
25/32 Memory
stackalloc
26/32 stackalloc
stackalloc
for (int i = 0; i < 10000000; i++)
{
// Alloc class on heap
var hello = new HelloClassOnStack(random);
result += hello.Compute(i);
}
vs
for (int i = 0; i < 10000000; i++)
{
// Alloc class on stack
var hello = stackalloc HelloClassOnStack(random);
result += hello.Compute(i);
}
27/32 stackalloc
stackalloc
for (int i = 0; i < 10000000; i++)
{
// Alloc class on heap
var hello = new HelloClassOnStack(random);
result += hello.Compute(i);
}
vs
for (int i = 0; i < 10000000; i++)
{
// Alloc class on stack
var hello = stackalloc HelloClassOnStack(random);
result += hello.Compute(i);
}
Time GC Collect
stack ∼400ms 0
heap ∼5000ms 100+
27/32 stackalloc
Branch prediction
28/32 Branch prediction
Branch prediction
const int N = 32767;
int[] sorted, unsorted; // random numbers [0..255]
private static int Sum(int[] data)
{
int sum = 0;
for (int i = 0; i < N; i++)
if (data[i] >= 128)
sum += data[i];
return sum;
}
29/32 Branch prediction
Branch prediction
const int N = 32767;
int[] sorted, unsorted; // random numbers [0..255]
private static int Sum(int[] data)
{
int sum = 0;
for (int i = 0; i < N; i++)
if (data[i] >= 128)
sum += data[i];
return sum;
}
[Benchmark]
public int Sorted()
{
return Sum(sorted);
}
[Benchmark]
public int Unsorted()
{
return Sum(unsorted);
}
29/32 Branch prediction
Branch prediction
const int N = 32767;
int[] sorted, unsorted; // random numbers [0..255]
private static int Sum(int[] data)
{
int sum = 0;
for (int i = 0; i < N; i++)
if (data[i] >= 128)
sum += data[i];
return sum;
}
[Benchmark]
public int Sorted()
{
return Sum(sorted);
}
[Benchmark]
public int Unsorted()
{
return Sum(unsorted);
}
Sorted Unsorted
∼20µs ∼150µs
∗
LegacyJIT-x86, i7-4702MQ CPU @ 2.20GHz
29/32 Branch prediction
Branch prediction
Branchless version:
private static int Sum(int[] data)
{
int sum = 0;
for (int i = 0; i < N; i++)
{
// if (data[i] >= 128)
// sum += data[i];
int t = (data[i] - 128) >> 31;
sum += ~t & data[i];
}
return sum;
}
30/32 Branch prediction
Branch prediction
Branchless version:
private static int Sum(int[] data)
{
int sum = 0;
for (int i = 0; i < N; i++)
{
// if (data[i] >= 128)
// sum += data[i];
int t = (data[i] - 128) >> 31;
sum += ~t & data[i];
}
return sum;
}
Sorted Unsorted
Branch ∼20µs ∼150µs
Branchless ∼30µs ∼30µs
∗
LegacyJIT-x86, i7-4702MQ CPU @ 2.20GHz
30/32 Branch prediction
Методическая литература
31/32
Вопросы?
Андрей Акиньшин, JetBrains
http://aakinshin.net
https://github.com/AndreyAkinshin
https://twitter.com/andrey_akinshin
andrey.akinshin@gmail.com
32/32

More Related Content

What's hot

Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMSergey Platonov
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Sergey Platonov
 
хитрости выведения типов
хитрости выведения типовхитрости выведения типов
хитрости выведения типовcorehard_by
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksMikhail Kurnosov
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksMikhail Kurnosov
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Yandex
 
Антон Полухин, Немного о Boost
Антон Полухин, Немного о BoostАнтон Полухин, Немного о Boost
Антон Полухин, Немного о BoostSergey Platonov
 
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“Platonov Sergey
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловSergey Platonov
 
разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3Eugeniy Tyumentcev
 
Сложности микробенчмаркинга
Сложности микробенчмаркингаСложности микробенчмаркинга
Сложности микробенчмаркингаAndrey Akinshin
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonovComputer Science Club
 
разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2Eugeniy Tyumentcev
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castRoman Orlov
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухинcorehard_by
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияДракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияPlatonov Sergey
 
Python&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython Meetup
 
Unsafe: to be or to be removed?
Unsafe: to be or to be removed?Unsafe: to be or to be removed?
Unsafe: to be or to be removed?Alexey Fyodorov
 
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворковНикита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворковSergey Platonov
 

What's hot (20)

Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
 
хитрости выведения типов
хитрости выведения типовхитрости выведения типов
хитрости выведения типов
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building Blocks
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
 
Антон Полухин, Немного о Boost
Антон Полухин, Немного о BoostАнтон Полухин, Немного о Boost
Антон Полухин, Немного о Boost
 
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“
Григорий Демченко, “Асинхронность и сопрограммы: обработка данных“
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
 
разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3
 
Сложности микробенчмаркинга
Сложности микробенчмаркингаСложности микробенчмаркинга
Сложности микробенчмаркинга
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
 
разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_cast
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияДракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
 
Python&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.by
 
Unsafe: to be or to be removed?
Unsafe: to be or to be removed?Unsafe: to be or to be removed?
Unsafe: to be or to be removed?
 
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворковНикита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
 
C sharp deep dive
C sharp deep diveC sharp deep dive
C sharp deep dive
 

Viewers also liked

発明の神に好かれるには
発明の神に好かれるには発明の神に好かれるには
発明の神に好かれるにはShu Yamada
 
事業継続のためのIt運用
事業継続のためのIt運用事業継続のためのIt運用
事業継続のためのIt運用Shu Yamada
 
Tourism achievements under the New Thracian Gold project in 2013
Tourism achievements under the New Thracian Gold project in 2013Tourism achievements under the New Thracian Gold project in 2013
Tourism achievements under the New Thracian Gold project in 2013Mihaela Kircheva
 
Aulas virtuales educacion 2014
Aulas virtuales educacion 2014Aulas virtuales educacion 2014
Aulas virtuales educacion 2014luis98martinez
 
1.8 division i w
1.8 division i w1.8 division i w
1.8 division i wTzenma
 
Taller técnicas efectivas de cobranza
Taller técnicas efectivas de cobranzaTaller técnicas efectivas de cobranza
Taller técnicas efectivas de cobranzaantonio soto
 
Mobile usage trends 2015
Mobile usage trends 2015Mobile usage trends 2015
Mobile usage trends 2015Alina Slichuk
 
Recordings at bedford square
Recordings at bedford squareRecordings at bedford square
Recordings at bedford squareheatherer19
 
Vaal Mental Health - Business Profile v 6
Vaal Mental Health - Business Profile v 6Vaal Mental Health - Business Profile v 6
Vaal Mental Health - Business Profile v 6Johan (Sipho) Coetzee
 
Sept/Oct Lunenburg County SPCA Newsletter
Sept/Oct Lunenburg County SPCA NewsletterSept/Oct Lunenburg County SPCA Newsletter
Sept/Oct Lunenburg County SPCA NewsletterCathie Billings
 
Cim d'àligues. Sessió de vol
Cim d'àligues. Sessió de volCim d'àligues. Sessió de vol
Cim d'àligues. Sessió de volprimariachanel
 
Tugas materi5 van
Tugas materi5 vanTugas materi5 van
Tugas materi5 vanvanradhinal
 
Fusf presentation to share 11.20
Fusf presentation to share 11.20Fusf presentation to share 11.20
Fusf presentation to share 11.20fusfpresent
 
Luxembourg investment climate - Main tax features
Luxembourg investment climate - Main tax featuresLuxembourg investment climate - Main tax features
Luxembourg investment climate - Main tax featuresLoyens & Loeff
 
Werken in het buitenland - 2015
Werken in het buitenland - 2015Werken in het buitenland - 2015
Werken in het buitenland - 2015Loyens & Loeff
 
Alta gastronomia Masia Notari 2014
Alta gastronomia Masia Notari 2014Alta gastronomia Masia Notari 2014
Alta gastronomia Masia Notari 2014Igrafiq Diseño Web
 

Viewers also liked (19)

発明の神に好かれるには
発明の神に好かれるには発明の神に好かれるには
発明の神に好かれるには
 
事業継続のためのIt運用
事業継続のためのIt運用事業継続のためのIt運用
事業継続のためのIt運用
 
Tourism achievements under the New Thracian Gold project in 2013
Tourism achievements under the New Thracian Gold project in 2013Tourism achievements under the New Thracian Gold project in 2013
Tourism achievements under the New Thracian Gold project in 2013
 
Aulas virtuales educacion 2014
Aulas virtuales educacion 2014Aulas virtuales educacion 2014
Aulas virtuales educacion 2014
 
Boeren landleven
Boeren landlevenBoeren landleven
Boeren landleven
 
Style sheet
Style sheetStyle sheet
Style sheet
 
1.8 division i w
1.8 division i w1.8 division i w
1.8 division i w
 
Taller técnicas efectivas de cobranza
Taller técnicas efectivas de cobranzaTaller técnicas efectivas de cobranza
Taller técnicas efectivas de cobranza
 
Mobile usage trends 2015
Mobile usage trends 2015Mobile usage trends 2015
Mobile usage trends 2015
 
Recordings at bedford square
Recordings at bedford squareRecordings at bedford square
Recordings at bedford square
 
Vaal Mental Health - Business Profile v 6
Vaal Mental Health - Business Profile v 6Vaal Mental Health - Business Profile v 6
Vaal Mental Health - Business Profile v 6
 
Sept/Oct Lunenburg County SPCA Newsletter
Sept/Oct Lunenburg County SPCA NewsletterSept/Oct Lunenburg County SPCA Newsletter
Sept/Oct Lunenburg County SPCA Newsletter
 
Cim d'àligues. Sessió de vol
Cim d'àligues. Sessió de volCim d'àligues. Sessió de vol
Cim d'àligues. Sessió de vol
 
Tugas materi5 van
Tugas materi5 vanTugas materi5 van
Tugas materi5 van
 
Fusf presentation to share 11.20
Fusf presentation to share 11.20Fusf presentation to share 11.20
Fusf presentation to share 11.20
 
RP Singh
RP SinghRP Singh
RP Singh
 
Luxembourg investment climate - Main tax features
Luxembourg investment climate - Main tax featuresLuxembourg investment climate - Main tax features
Luxembourg investment climate - Main tax features
 
Werken in het buitenland - 2015
Werken in het buitenland - 2015Werken in het buitenland - 2015
Werken in het buitenland - 2015
 
Alta gastronomia Masia Notari 2014
Alta gastronomia Masia Notari 2014Alta gastronomia Masia Notari 2014
Alta gastronomia Masia Notari 2014
 

Similar to Продолжаем говорить о микрооптимизациях .NET-приложений

Распространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложенийРаспространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложенийAndrey Akinshin
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actualYevgen Levik
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMTech Talks @NSU
 
11 встреча — Введение в GPGPU (А. Свириденков)
11 встреча — Введение в GPGPU (А. Свириденков)11 встреча — Введение в GPGPU (А. Свириденков)
11 встреча — Введение в GPGPU (А. Свириденков)Smolensk Computer Science Club
 
Когда в C# не хватает C++ . Часть 3.
Когда в C# не хватает C++. Часть 3. Когда в C# не хватает C++. Часть 3.
Когда в C# не хватает C++ . Часть 3. Mikhail Shcherbakov
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6Technopark
 
Cpp0x Introduction
Cpp0x IntroductionCpp0x Introduction
Cpp0x IntroductionFedor Vompe
 
Deep Dive C# by Sergey Teplyakov
Deep Dive  C# by Sergey TeplyakovDeep Dive  C# by Sergey Teplyakov
Deep Dive C# by Sergey TeplyakovAlex Tumanoff
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Yandex
 
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerJPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerAnton Arhipov
 
разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2etyumentcev
 
Введение в разработку многопоточных приложений
Введение в разработку многопоточных приложенийВведение в разработку многопоточных приложений
Введение в разработку многопоточных приложенийCUSTIS
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кодаAndrey Karpov
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода Pavel Tsukanov
 
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Fwdays
 
Поговорим о различных версиях .NET
Поговорим о различных версиях .NETПоговорим о различных версиях .NET
Поговорим о различных версиях .NETAndrey Akinshin
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Yandex
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на Pythonru_Parallels
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на PythonCodeFest
 

Similar to Продолжаем говорить о микрооптимизациях .NET-приложений (20)

Распространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложенийРаспространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложений
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actual
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVM
 
11 встреча — Введение в GPGPU (А. Свириденков)
11 встреча — Введение в GPGPU (А. Свириденков)11 встреча — Введение в GPGPU (А. Свириденков)
11 встреча — Введение в GPGPU (А. Свириденков)
 
Когда в C# не хватает C++ . Часть 3.
Когда в C# не хватает C++. Часть 3. Когда в C# не хватает C++. Часть 3.
Когда в C# не хватает C++ . Часть 3.
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6
 
Cpp0x Introduction
Cpp0x IntroductionCpp0x Introduction
Cpp0x Introduction
 
Deep Dive C# by Sergey Teplyakov
Deep Dive  C# by Sergey TeplyakovDeep Dive  C# by Sergey Teplyakov
Deep Dive C# by Sergey Teplyakov
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
 
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerJPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profiler
 
разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2
 
Введение в разработку многопоточных приложений
Введение в разработку многопоточных приложенийВведение в разработку многопоточных приложений
Введение в разработку многопоточных приложений
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кода
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода
 
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
 
Поговорим о различных версиях .NET
Поговорим о различных версиях .NETПоговорим о различных версиях .NET
Поговорим о различных версиях .NET
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на Python
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на Python
 

More from Andrey Akinshin

Поговорим про performance-тестирование
Поговорим про performance-тестированиеПоговорим про performance-тестирование
Поговорим про performance-тестированиеAndrey Akinshin
 
Сложности performance-тестирования
Сложности performance-тестированияСложности performance-тестирования
Сложности performance-тестированияAndrey Akinshin
 
Поговорим про память
Поговорим про памятьПоговорим про память
Поговорим про памятьAndrey Akinshin
 
Кроссплатформенный .NET и как там дела с Mono и CoreCLR
Кроссплатформенный .NET и как там дела с Mono и CoreCLRКроссплатформенный .NET и как там дела с Mono и CoreCLR
Кроссплатформенный .NET и как там дела с Mono и CoreCLRAndrey Akinshin
 
Теория и практика .NET-бенчмаркинга (25.01.2017, Москва)
 Теория и практика .NET-бенчмаркинга (25.01.2017, Москва) Теория и практика .NET-бенчмаркинга (25.01.2017, Москва)
Теория и практика .NET-бенчмаркинга (25.01.2017, Москва)Andrey Akinshin
 
Let’s talk about microbenchmarking
Let’s talk about microbenchmarkingLet’s talk about microbenchmarking
Let’s talk about microbenchmarkingAndrey Akinshin
 
Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)
Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)
Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)Andrey Akinshin
 
Подружили CLR и JVM в Project Rider
Подружили CLR и JVM в Project RiderПодружили CLR и JVM в Project Rider
Подружили CLR и JVM в Project RiderAndrey Akinshin
 
Что нам готовит грядущий C#7?
Что нам готовит грядущий C#7?Что нам готовит грядущий C#7?
Что нам готовит грядущий C#7?Andrey Akinshin
 
.NET 2015: Будущее рядом
.NET 2015: Будущее рядом.NET 2015: Будущее рядом
.NET 2015: Будущее рядомAndrey Akinshin
 
Практические приёмы оптимизации .NET-приложений
Практические приёмы оптимизации .NET-приложенийПрактические приёмы оптимизации .NET-приложений
Практические приёмы оптимизации .NET-приложенийAndrey Akinshin
 
Низкоуровневые оптимизации .NET-приложений
Низкоуровневые оптимизации .NET-приложенийНизкоуровневые оптимизации .NET-приложений
Низкоуровневые оптимизации .NET-приложенийAndrey Akinshin
 
Основы работы с Git
Основы работы с GitОсновы работы с Git
Основы работы с GitAndrey Akinshin
 
Сборка мусора в .NET
Сборка мусора в .NETСборка мусора в .NET
Сборка мусора в .NETAndrey Akinshin
 

More from Andrey Akinshin (15)

Поговорим про performance-тестирование
Поговорим про performance-тестированиеПоговорим про performance-тестирование
Поговорим про performance-тестирование
 
Сложности performance-тестирования
Сложности performance-тестированияСложности performance-тестирования
Сложности performance-тестирования
 
Поговорим про память
Поговорим про памятьПоговорим про память
Поговорим про память
 
Кроссплатформенный .NET и как там дела с Mono и CoreCLR
Кроссплатформенный .NET и как там дела с Mono и CoreCLRКроссплатформенный .NET и как там дела с Mono и CoreCLR
Кроссплатформенный .NET и как там дела с Mono и CoreCLR
 
Теория и практика .NET-бенчмаркинга (25.01.2017, Москва)
 Теория и практика .NET-бенчмаркинга (25.01.2017, Москва) Теория и практика .NET-бенчмаркинга (25.01.2017, Москва)
Теория и практика .NET-бенчмаркинга (25.01.2017, Москва)
 
Let’s talk about microbenchmarking
Let’s talk about microbenchmarkingLet’s talk about microbenchmarking
Let’s talk about microbenchmarking
 
Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)
Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)
Теория и практика .NET-бенчмаркинга (02.11.2016, Екатеринбург)
 
Подружили CLR и JVM в Project Rider
Подружили CLR и JVM в Project RiderПодружили CLR и JVM в Project Rider
Подружили CLR и JVM в Project Rider
 
Что нам готовит грядущий C#7?
Что нам готовит грядущий C#7?Что нам готовит грядущий C#7?
Что нам готовит грядущий C#7?
 
.NET 2015: Будущее рядом
.NET 2015: Будущее рядом.NET 2015: Будущее рядом
.NET 2015: Будущее рядом
 
Практические приёмы оптимизации .NET-приложений
Практические приёмы оптимизации .NET-приложенийПрактические приёмы оптимизации .NET-приложений
Практические приёмы оптимизации .NET-приложений
 
Низкоуровневые оптимизации .NET-приложений
Низкоуровневые оптимизации .NET-приложенийНизкоуровневые оптимизации .NET-приложений
Низкоуровневые оптимизации .NET-приложений
 
Основы работы с Git
Основы работы с GitОсновы работы с Git
Основы работы с Git
 
Сборка мусора в .NET
Сборка мусора в .NETСборка мусора в .NET
Сборка мусора в .NET
 
Phd presentation
Phd presentationPhd presentation
Phd presentation
 

Продолжаем говорить о микрооптимизациях .NET-приложений

  • 1. Продолжаем говорить о микрооптимизациях .NET-приложений Андрей Акиньшин, JetBrains .NEXT 2015 Moscow 1/32
  • 2. Про что будем разговаривать? 2/32
  • 3. Про что будем разговаривать? Не будет: • Универсальных способов оптимизации • Скучной теории • Подробного устройства .NET, GC, JIT, CPU 2/32
  • 4. Про что будем разговаривать? Не будет: • Универсальных способов оптимизации • Скучной теории • Подробного устройства .NET, GC, JIT, CPU Будет: • Много весёлых историй1 1 Все истории основаны на реальных событиях 2/32
  • 6. Roslyn Задачка: void Print(string format, params object[] args) { // ... } Print("DotNext"); // Будет ли аллокация? 4/32 Roslyn
  • 7. Roslyn Задачка: void Print(string format, params object[] args) { // ... } Print("DotNext"); // Будет ли аллокация? old csc.exe Roslyn new object[0] System.Array.Empty<T>1 1 .NET Framework 4.6+ 4/32 Roslyn
  • 9. Boxing Будет ли упаковка/распаковка? [MethodImpl(MethodImplOptions.NoInlining)] private static TBase Foo<T, TBase>(T t) where T : TBase { return (TBase) t; } 6/32 Boxing
  • 10. Boxing Будет ли упаковка/распаковка? [MethodImpl(MethodImplOptions.NoInlining)] private static TBase Foo<T, TBase>(T t) where T : TBase { return (TBase) t; } Взглянем на IL: IL_0000: ldarg.0 ; t IL_0001: box 0 ; T IL_0006: unbox.any 1 ; TBase IL_000b: ret 6/32 Boxing
  • 11. Примеры struct Bar {} struct Bar<T> {} Foo<int, int>(1); Foo<long, long>(2); Foo<Bar, Bar>(new Bar()); Foo<Bar<int>, Bar<int>>(new Bar<int>()); Foo<Bar<IList>, Bar<IList>>(new Bar<IList>()); 7/32 Boxing
  • 12. Примеры struct Bar {} struct Bar<T> {} Foo<int, int>(1); Foo<long, long>(2); Foo<Bar, Bar>(new Bar()); Foo<Bar<int>, Bar<int>>(new Bar<int>()); Foo<Bar<IList>, Bar<IList>>(new Bar<IList>()); Но не сможет ли JIT нам помочь? 7/32 Boxing
  • 13. Иногда сможет Foo<int, int>(1); Foo<long, long>(2); Foo<Bar, Bar>(new Bar()); Foo<Bar<int>, Bar<int>>(new Bar<int>()); ⇓ mov eax,ecx ; (С точностью до регистра) ret 8/32 Boxing
  • 14. А иногда нет Foo<Bar<IList>, Bar<IList>>(new Bar<IList>()); ⇓ sub rsp,28h mov dword ptr [rsp+30h],ecx mov rax,qword ptr [rsp+30h] mov rcx,qword ptr [rax+10h] mov rcx,qword ptr [rcx] btr rcx,0 cmovb rcx,qword ptr [rcx] lea rdx,[rsp+38h] call 00007FF8C37D48D0 mov rdx,rax mov rax,qword ptr [rsp+30h] mov rcx,qword ptr [rax+10h] mov rcx,qword ptr [rcx+8] btr rcx,0 cmovb rcx,qword ptr [rcx] call 00007FF8C3896870 mov al,byte ptr [rax] add rsp,28h ret 9/32 Boxing
  • 16. GC class Foo { public object Bar { get; set; } } var foo = new Foo() { Bar = new object() }; // Long live the Bar! GC.KeepAlive(foo); 11/32 GC
  • 17. GC class Foo { public object Bar { get; set; } } var foo = new Foo() { Bar = new object() }; // Long live the Bar! GC.KeepAlive(foo); Уважаемые знатоки, внимание, вопрос: Может ли string удерживать ссылку на object? 11/32 GC
  • 18. GC class Foo { public object Bar { get; set; } } var foo = new Foo() { Bar = new object() }; // Long live the Bar! GC.KeepAlive(foo); Уважаемые знатоки, внимание, вопрос: Может ли string удерживать ссылку на object? var foo = "DotNext"; var bar = new object(); BlackBox(); // Что же находится в чёрном ящике? // Long live the Bar! GC.KeepAlive(foo); 11/32 GC
  • 19. GC Удивительный BCL: ConditionalWeakTable<TKey, TValue> Class Enables compilers to dynamically attach object fields to managed objects. c MSDN 12/32 GC
  • 20. GC Удивительный BCL: ConditionalWeakTable<TKey, TValue> Class Enables compilers to dynamically attach object fields to managed objects. c MSDN А давайте немножко пошалим: var foo = "DotNext"; var bar = new object(); var cwt = new ConditionalWeakTable<string, object>(); cwt.Add(foo, bar); String.Intern(foo); // foo держит ссылку на bar GC.KeepAlive(cwt); 12/32 GC
  • 25. Benchmarks Что там может быть сложного? 17/32 Benchmarks
  • 26. Benchmarks Что там может быть сложного? // Нужно замерить время? public double WithoutStopwatch() { double a = 1, b = 1; for (int i = 0; i < 100; i++) a = a + b; return a; } 17/32 Benchmarks
  • 27. Benchmarks Что там может быть сложного? // Нужно замерить время? public double WithoutStopwatch() { double a = 1, b = 1; for (int i = 0; i < 100; i++) a = a + b; return a; } // У нас же есть Stopwatch! public double WithStopwatch() { double a = 1, b = 1; var sw = Stopwatch.Start(); for (int i = 0; i < 100; i++) a = a + b; Print(sw.ElapsedMilliseconds); return a; } 17/32 Benchmarks
  • 28. Benchmarks Что там может быть сложного? // Нужно замерить время? public double WithoutStopwatch() { double a = 1, b = 1; for (int i = 0; i < 100; i++) a = a + b; return a; } // У нас же есть Stopwatch! public double WithStopwatch() { double a = 1, b = 1; var sw = Stopwatch.Start(); for (int i = 0; i < 100; i++) a = a + b; Print(sw.ElapsedMilliseconds); return a; } WithoutStopwatch WithStopwatch ∼100ns ∼350ns 17/32 Benchmarks
  • 29. Benchmarks Что там может быть сложного? // Нужно замерить время? public double WithoutStopwatch() { double a = 1, b = 1; for (int i = 0; i < 100; i++) a = a + b; return a; } // У нас же есть Stopwatch! public double WithStopwatch() { double a = 1, b = 1; var sw = Stopwatch.Start(); for (int i = 0; i < 100; i++) a = a + b; Print(sw.ElapsedMilliseconds); return a; } WithoutStopwatch WithStopwatch ∼100ns ∼350ns ; a + b fld1 faddp st(1),st ; a + b fld1 fadd qword ptr [ebp-0Ch] fstp qword ptr [ebp-0Ch] 17/32 Benchmarks
  • 31. RyuJIT Если бы вы были JIT-компилятором, то как бы вы скомпилировали следующий код? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong RotateRight64(ulong value) { return (value >> 1) | (value << 63); } 19/32 RyuJIT
  • 32. RyuJIT Если бы вы были JIT-компилятором, то как бы вы скомпилировали следующий код? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong RotateRight64(ulong value) { return (value >> 1) | (value << 63); } Может быть так? mov rdx,rax ; value shr rdx,1 ; value >> 1 shl rax,3Fh ; value << 63 or eax,edx ; (value >> 1) | (value << 63) 19/32 RyuJIT
  • 33. RyuJIT Если бы вы были JIT-компилятором, то как бы вы скомпилировали следующий код? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong RotateRight64(ulong value) { return (value >> 1) | (value << 63); } Может быть так? mov rdx,rax ; value shr rdx,1 ; value >> 1 shl rax,3Fh ; value << 63 or eax,edx ; (value >> 1) | (value << 63) Или так? ror rax,1 19/32 RyuJIT
  • 34. RyuJIT Time Percent ComputeHash 4047ms 100% RotateRight 1487ms 37% 20/32 RyuJIT
  • 37. Blittable Загадка для любителей помаршалить: [StructLayout(LayoutKind.Explicit)] public struct UInt128 { [FieldOffset(0)] public ulong Value1; [FieldOffset(8)] public ulong Value2; } 22/32 Blittable
  • 38. Blittable Загадка для любителей помаршалить: [StructLayout(LayoutKind.Explicit)] public struct UInt128 { [FieldOffset(0)] public ulong Value1; [FieldOffset(8)] public ulong Value2; } [StructLayout(LayoutKind.Sequential)] public struct MyStruct { public UInt128 UInt128; public char Char; } 22/32 Blittable
  • 39. Blittable Загадка для любителей помаршалить: [StructLayout(LayoutKind.Explicit)] public struct UInt128 { [FieldOffset(0)] public ulong Value1; [FieldOffset(8)] public ulong Value2; } [StructLayout(LayoutKind.Sequential)] public struct MyStruct { public UInt128 UInt128; public char Char; } var myStruct = new MyStruct(); var baseAddress = (int)&myStruct; var uInt128Address = (int)&myStruct.UInt128; 22/32 Blittable
  • 40. Blittable Загадка для любителей помаршалить: [StructLayout(LayoutKind.Explicit)] public struct UInt128 { [FieldOffset(0)] public ulong Value1; [FieldOffset(8)] public ulong Value2; } [StructLayout(LayoutKind.Sequential)] public struct MyStruct { public UInt128 UInt128; public char Char; } var myStruct = new MyStruct(); var baseAddress = (int)&myStruct; var uInt128Address = (int)&myStruct.UInt128; Console.WriteLine(uInt128Address - baseAddress); // ??? Console.WriteLine(Marshal.OffsetOf(typeof(MyStruct), "UInt128")); // ??? 22/32 Blittable
  • 41. Blittable Загадка для любителей помаршалить: [StructLayout(LayoutKind.Explicit)] public struct UInt128 { [FieldOffset(0)] public ulong Value1; [FieldOffset(8)] public ulong Value2; } [StructLayout(LayoutKind.Sequential)] public struct MyStruct { public UInt128 UInt128; public char Char; } var myStruct = new MyStruct(); var baseAddress = (int)&myStruct; var uInt128Address = (int)&myStruct.UInt128; Console.WriteLine(uInt128Address - baseAddress); // ??? Console.WriteLine(Marshal.OffsetOf(typeof(MyStruct), "UInt128")); // ??? MS.NET-x86 MS.NET-x64 Mono Address 4 8 0 Marshal 0 0 0 22/32 Blittable
  • 42. Memory Event Latency Scaled 1 CPU cycle 0.3 ns 1 s Level 1 cache access 0.9 ns 3 s Level 2 cache access 2.8 ns 9 s Level 3 cache access 12.9 ns 43 s Main memory access 120 ns 6 min Solid-state disk I/O 50-150 µs 2-6 days Rotational disk I/O 1-10 ms 1-12 months Internet: SF to NYC 40 ms 4 years Internet: SF to UK 81 ms 8 years Internet: SF to Australia 183 ms 19 years OS virtualization reboot 4 s 423 years SCSI command time-out 30 s 3000 years Hardware virtualization reboot 40 s 4000 years Physical system reboot 5 m 32 millenia c Systems Performance: Enterprise and the Cloud 23/32 Memory
  • 43. Memory Задача: подсчитать сумму элементов массива const int N = 1024; int[,] a = new int[N, N]; 24/32 Memory
  • 44. Memory Задача: подсчитать сумму элементов массива const int N = 1024; int[,] a = new int[N, N]; [Benchmark] public double Sum_ij() { var sum = 0; for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) sum += a[i, j]; return sum; } 24/32 Memory
  • 45. Memory Задача: подсчитать сумму элементов массива const int N = 1024; int[,] a = new int[N, N]; [Benchmark] public double Sum_ij() { var sum = 0; for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) sum += a[i, j]; return sum; } [Benchmark] public double Sum_ji() { var sum = 0; for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) sum += a[i, j]; return sum; } 24/32 Memory
  • 46. Memory Задача: подсчитать сумму элементов массива const int N = 1024; int[,] a = new int[N, N]; [Benchmark] public double Sum_ij() { var sum = 0; for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) sum += a[i, j]; return sum; } [Benchmark] public double Sum_ji() { var sum = 0; for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) sum += a[i, j]; return sum; } Sum_ij() Sum_ji() ∼1.5ms ∼9ms ∗ LegacyJIT-x86, i7-4702MQ CPU @ 2.20GHz 24/32 Memory
  • 49. stackalloc for (int i = 0; i < 10000000; i++) { // Alloc class on heap var hello = new HelloClassOnStack(random); result += hello.Compute(i); } vs for (int i = 0; i < 10000000; i++) { // Alloc class on stack var hello = stackalloc HelloClassOnStack(random); result += hello.Compute(i); } 27/32 stackalloc
  • 50. stackalloc for (int i = 0; i < 10000000; i++) { // Alloc class on heap var hello = new HelloClassOnStack(random); result += hello.Compute(i); } vs for (int i = 0; i < 10000000; i++) { // Alloc class on stack var hello = stackalloc HelloClassOnStack(random); result += hello.Compute(i); } Time GC Collect stack ∼400ms 0 heap ∼5000ms 100+ 27/32 stackalloc
  • 52. Branch prediction const int N = 32767; int[] sorted, unsorted; // random numbers [0..255] private static int Sum(int[] data) { int sum = 0; for (int i = 0; i < N; i++) if (data[i] >= 128) sum += data[i]; return sum; } 29/32 Branch prediction
  • 53. Branch prediction const int N = 32767; int[] sorted, unsorted; // random numbers [0..255] private static int Sum(int[] data) { int sum = 0; for (int i = 0; i < N; i++) if (data[i] >= 128) sum += data[i]; return sum; } [Benchmark] public int Sorted() { return Sum(sorted); } [Benchmark] public int Unsorted() { return Sum(unsorted); } 29/32 Branch prediction
  • 54. Branch prediction const int N = 32767; int[] sorted, unsorted; // random numbers [0..255] private static int Sum(int[] data) { int sum = 0; for (int i = 0; i < N; i++) if (data[i] >= 128) sum += data[i]; return sum; } [Benchmark] public int Sorted() { return Sum(sorted); } [Benchmark] public int Unsorted() { return Sum(unsorted); } Sorted Unsorted ∼20µs ∼150µs ∗ LegacyJIT-x86, i7-4702MQ CPU @ 2.20GHz 29/32 Branch prediction
  • 55. Branch prediction Branchless version: private static int Sum(int[] data) { int sum = 0; for (int i = 0; i < N; i++) { // if (data[i] >= 128) // sum += data[i]; int t = (data[i] - 128) >> 31; sum += ~t & data[i]; } return sum; } 30/32 Branch prediction
  • 56. Branch prediction Branchless version: private static int Sum(int[] data) { int sum = 0; for (int i = 0; i < N; i++) { // if (data[i] >= 128) // sum += data[i]; int t = (data[i] - 128) >> 31; sum += ~t & data[i]; } return sum; } Sorted Unsorted Branch ∼20µs ∼150µs Branchless ∼30µs ∼30µs ∗ LegacyJIT-x86, i7-4702MQ CPU @ 2.20GHz 30/32 Branch prediction