NET Code hot reload

Содержание

Слайд 2

Что за «Code hot reload»?

Обновление кода приложения без перезапуска этого приложения.
.NET Framework

Что за «Code hot reload»? Обновление кода приложения без перезапуска этого приложения.
(4.6 +)
Надеюсь такие слова вас не пугают: CLR, MSIL, Assembly, указатель.

Слайд 3

DirectumRX – ECM-система

DirectumRX – ECM-система

Слайд 4

DirectumRX Development Studio

DirectumRX Development Studio

Слайд 5

Прикладная разработка DirectumRX

Development Studio (IDE)

Локальный сервер приложений

Код платформы (framework)

Прикладной код

Новый прикладной код

Deploy

Прикладная разработка DirectumRX Development Studio (IDE) Локальный сервер приложений Код платформы (framework)
(dll)

compile

restart

Слайд 6

Зачем нам HotReload

Development Studio (IDE)

Локальный сервер приложений

Код платформы (framework)

Прикладной код

Новый прикладной код

Deploy

compile

restart

Зачем нам HotReload Development Studio (IDE) Локальный сервер приложений Код платформы (framework)

Слайд 7

Дополнительные ограничения и пожелания

Если поменялась структура БД, одним HotReload не обойтись.
HotReload и

Дополнительные ограничения и пожелания Если поменялась структура БД, одним HotReload не обойтись.
отладка в Dev Studio (breakpoints, watch).
Подходит и для серверного, и для клиентского кода (у нас есть Desktop-клиент).

Слайд 8

Основная идея

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

Development Studio (IDE)

Локальный

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

Код платформы

Прикладной код

Новый прикладной код

Исходник или Assembly

inject

Слайд 9

Решения в лоб

Reflection – LoadAssembly (Shadow Copy Assemblies)
Managed Extensibility Framework (MEF, VS-MEF)
Mono.Cecil

Решения в лоб Reflection – LoadAssembly (Shadow Copy Assemblies) Managed Extensibility Framework (MEF, VS-MEF) Mono.Cecil

Слайд 10

Решения в лоб. Проблемы

Не повлияем на уже существующие в памяти объекты.
Новые объекты,

Решения в лоб. Проблемы Не повлияем на уже существующие в памяти объекты.
создаваемые через new будут ссылаться на старые типы.
В случае с MEF прикладной код придётся переписать особым образом (атрибуты, интерфейсы).

Слайд 11

Emit

CodeDom – компиляция С# в Assembly сразу в память в AppDomain.
Emit –

Emit CodeDom – компиляция С# в Assembly сразу в память в AppDomain.
генерация IL-кода.

Development Studio (IDE)

Локальный сервер приложений

Платформа

Прикладной код

Новые прикладные исходники

C#

compile

emit

Слайд 12

Emit. Проблемы

Emit работает только с DynamicAssembly. А при компиляции CodeDom’a мы получаем обычную

Emit. Проблемы Emit работает только с DynamicAssembly. А при компиляции CodeDom’a мы
Assembly.
Чтобы «завести» динамический класс, нужно вызвать у него CreateType(). Это блокирует его дальнейшие модификации.

Слайд 13

Edit and Continue

Встроенный в Visual Studio хитрый механизм, генерирующий некоторые дельты.
Общедоступного API

Edit and Continue Встроенный в Visual Studio хитрый механизм, генерирующий некоторые дельты.
нет.
Даже в самой VS механизм не работает в ряде случаев.

Слайд 15

Method Inject v1

Method Inject v1

Слайд 16

­Method Inject v1

Суть – замена указателя на метод.

MethodInfo methodToReplace = … ; MethodInfo

­Method Inject v1 Суть – замена указателя на метод. MethodInfo methodToReplace =
methodToInject = … ;
unsafe { long* target = (long*) methodToReplace.MethodHandle.Value.ToPointer();
long* inject = (long*) methodToInject.MethodHandle.Value.ToPointer();
*target = *inject; }

В реальности чуток сложнее, потому что надо учесть x86/x64, Debug/Release.

Слайд 17

Как хранятся описания классов в .NET

Заголовок
MethodTable ptr
Field value 1
Field value 2

ObjectInstance


ToString() ptr
Equals()

Как хранятся описания классов в .NET Заголовок MethodTable ptr Field value 1
ptr
….
MyMethod1() ptr

MethodTable

{
Console.WriteLine(1);
}

На самом деле тут IL, конечно

Слайд 18

Method Inject v1. Суть

Заголовок
MethodTable ptr
Field value 1
Field value 2

ObjectInstance


ToString() ptr
Equals() ptr
….
MyMethod1()

Method Inject v1. Суть Заголовок MethodTable ptr Field value 1 Field value
ptr

MethodTable

{
Console.WriteLine(1);
}

{
Console.WriteLine(2);
}

Слайд 19

Method Inject v1. Проверяем на практике

Есть два класса…

Target
TargetMethod()

Injection
InjectionMethod()

Injector

Method Inject v1. Проверяем на практике Есть два класса… Target TargetMethod() Injection InjectionMethod() Injector

Слайд 20

Method Inject v1. Проверяем на практике

Исходный MethodTable
TestClasses.Target.Test()
TestClasses.Target.TargetMethod()
TestClasses.Target.get_Value()
TestClasses.Target..ctor (System.String)

WinDbg + SOS

Method Inject v1. Проверяем на практике Исходный MethodTable TestClasses.Target.Test() TestClasses.Target.TargetMethod() TestClasses.Target.get_Value() TestClasses.Target..ctor (System.String) WinDbg + SOS

Слайд 21

Method Inject v1. Проверяем на практике

MethodTable после Inject
TestClasses.Target.Test()
TestClasses.Injection.InjectionMethod()
TestClasses.Target.get_Value()
TestClasses.Target..ctor (System.String)

Method Inject v1. Проверяем на практике MethodTable после Inject TestClasses.Target.Test() TestClasses.Injection.InjectionMethod() TestClasses.Target.get_Value() TestClasses.Target..ctor (System.String)

Слайд 22

Method Inject v1. Дополнительные работы

Сравнить прикладные исходники и найти изменившиеся методы.
Передать исходники

Method Inject v1. Дополнительные работы Сравнить прикладные исходники и найти изменившиеся методы.
методов на сервер.
Создать новый класс, засунуть в него методы и скомпилировать в память.
Найти старый метод и сделать MethodInject на новый.

Слайд 23

Method Inject v1. ПРОБЛЕМА!

Прекрасно работает
пока мы не вызвали подменяемый метод.

Method Inject v1. ПРОБЛЕМА! Прекрасно работает пока мы не вызвали подменяемый метод.

Слайд 24

Method Inject v1. ПРОБЛЕМА!

….
Code ptr


….
MyMethod1() ptr

MethodTable

{
Console.WriteLine(1);
}

MethodDesc

Stub

PreJitStub

native machine code

Write jmp to jitted code

compileMethod

Method Inject v1. ПРОБЛЕМА! …. Code ptr … … …. MyMethod1() ptr

Слайд 25

Method Inject v2

Method Inject v2

Слайд 26

Method Inject v2

public static class InjectionHelper
{
...
public static void Initialize()
public

Method Inject v2 public static class InjectionHelper { ... public static void
static void UpdateILCodes(MethodInfo method, byte[] ilCodes)
...
}

Слайд 27

Method Inject v2

….
Code ptr


….
MyMethod1() ptr

MethodTable

IL

MethodDesc

Stub

PreJitStub

machine code

Write jmp to jitted code

compileMethod

Method Inject v2 …. Code ptr … … …. MyMethod1() ptr …

Слайд 28

Injector

….
Code ptr


….
MyMethod1() ptr

MethodTable

IL

MethodDesc

Stub

PreJitStub

machine code

MethodDesc.Reset()

Method Inject v2

Write jmp to jitted code

compileMethod

hook

Injector …. Code ptr … … …. MyMethod1() ptr … MethodTable IL

Слайд 29

Method Inject v2. Проблемки

Нормально заработало только на .NET Framework 2.0 - 4.0
Inline маленьких

Method Inject v2. Проблемки Нормально заработало только на .NET Framework 2.0 -
методов.
Лезем внутрь CLR. Слишком рискованно для продакшена.

Слайд 30

Давайте вспомним, с чего мы начали

Есть платформа.
Она исполняет прикладной код.
Мы хотим подменять

Давайте вспомним, с чего мы начали Есть платформа. Она исполняет прикладной код.
прикладной код.

Слайд 31

Что за прикладной код?

Document
Name
Author
Created

ServerHandlers
BeforeSave()
AfterSave()

ServerFunctions
ServerFoo()

ClientHandlers
Showing()

ClientFunctions
ClientFoo()

Этот класс генерируется платформой

Что за прикладной код? Document Name Author Created … ServerHandlers BeforeSave() AfterSave()

Слайд 32

Class swap

Платформенный код создаёт прикладные объекты (Dependency Injection).
Не возимся с методами – заменяем

Class swap Платформенный код создаёт прикладные объекты (Dependency Injection). Не возимся с
сразу весь объект.

Document1
Name

IDocument1ServerFunctions
Foo()

Document1ServerFunctions
Foo()

IDocument1ServerFunctions

Слайд 33

Class swap

Document1

Document1ServerFunctions
Foo()

IDocument1ServerFunctions

AppTypesManager

Implementation

Create ServerFunctions ()

Class swap Document1 Document1ServerFunctions Foo() IDocument1ServerFunctions AppTypesManager Implementation Create ServerFunctions ()

Слайд 34

Class swap


Document1

Document1ServerFunctions
Foo()

IDocument1ServerFunctions

AppTypesManager

Create ServerFunctions ()

Injector

Create type

C# sources

Class swap … Document1 Document1ServerFunctions Foo() IDocument1ServerFunctions AppTypesManager Create ServerFunctions () Injector Create type C# sources

Слайд 35

Class swap

Document1

Document1ServerFunctions
Foo()

IDocument1ServerFunctions

Document1ServerFunctions
Foo()

IDocument1ServerFunctions

AppTypesManager

Implementation

Create ServerFunctions ()

Injector

Create type

Register

C# sources

Class swap Document1 Document1ServerFunctions Foo() IDocument1ServerFunctions Document1ServerFunctions Foo() IDocument1ServerFunctions AppTypesManager Implementation Create

Слайд 36

Заключение

В продакшен это не пошло :( Деплой мы ускорили иначе – оптимизации.
Исследования –

Заключение В продакшен это не пошло :( Деплой мы ускорили иначе –
круто.
Погружение в детали инструмента – интересно.

Слайд 37

()

.net core
JIT disable
Custom .NET CLR

() .net core JIT disable Custom .NET CLR

Слайд 38

THE END

Асадуллин Тимур

Directum, Уфа

[email protected]

THE END Асадуллин Тимур Directum, Уфа timonik@bk.ru
Имя файла: NET-Code-hot-reload.pptx
Количество просмотров: 36
Количество скачиваний: 0