Составители:
Рубрика:
Глава 5.
Динамическая генерация кода
5.1. Введение в динамическую генерацию кода
Динамическая генерация кода – это прием программирования, за-
ключающийся в том, что фрагменты кода порождаются и запускаются
непосредственно во время выполнения программы. Этот прием был изве-
стен достаточно давно, но усложнение архитектуры компьютеров, и, что
особенно важно, усложнение наборов команд процессоров привело к то-
му, что в последние 10-15 лет динамическая генерация кода в некоторой
степени потеряла популярность.
Целью динамической генерации кода является использование ин-
формации, доступной только во время выполнения программы, для повы-
шения качества исполняемого кода. В терминах метавычислений можно
сказать, что динамическая генерация кода позволяет специализировать
фрагменты программы по данным, известным во время выполнения.
В некотором смысле, любой JIT-компилятор как раз использует ди-
намическую генерацию кода: имея некоторую программу, записанную на
промежуточном языке (байт-коде), и зная, какой процессор работает в си-
стеме, JIT-компилятор динамически транслирует программу в инструк-
ции этого процессора. При этом можно считать, что тип процессора – эта
как раз та часть информации, которая становится известной только во
время выполнения программы.
Естественно, не стоит чересчур увлекаться динамической генерацией
кода: этот прием далеко не всегда дает ускорение программы. Можно ска-
зать, что применение динамической генерации оправдано, если:
1. процесс вычислений в некотором фрагменте программы
преимущественно определяется информацией, известной толь-
ко во время выполнения;
2. запуск этого фрагмента осуществляется многократно;
3. выполнение фрагмента связано с существенными затратами
времени процессора.
В .NET доступно два способа организации динамической генерации
кода:
1. порождение программы на языке C# и вызов компилятора C#;
2. непосредственное порождение метаданных и CIL-кода.
Динамическая генерация кода
163
);
MethodBuilder mainMethod =
module.DefineGlobalMethod(
“main”,
MethodAttributes.Static |
MethodAttributes.Public,
typeof(void),
null
);
MethodInfo ConsoleWriteLineMethod =
((typeof(Console)).GetMethod(“WriteLine”,
new Type[] { typeof(string) } ));
ILGenerator il = mainMethod.GetILGenerator();
il.Emit(OpCodes.Ldstr,”Hello, World!”);
il.Emit(OpCodes.Call,ConsoleWriteLineMethod);
il.Emit(OpCodes.Ret);
module.CreateGlobalFunctions();
assembly.SetEntryPoint(
mainMethod,PEFileKinds.ConsoleApplication
);
assembly.Save(“hello.exe”);
}
}
4.4.3. Сравнение возможностей библиотек
Возможности, предоставляемые библиотекой Metadata Unmanaged
API и библиотекой рефлексии, представлены в таблице 4.3.
Таблица 4.3. Сравнение возможностей библиотек
Из таблицы следует, что ни одна из библиотек, поставляемых вместе
с .NET Framework, не позволяет читать CIL-код, хотя эта возможность
требуется целому ряду метаинструментов (например, верификаторам и
оптимизаторам кода).
162
CIL и системное программирование в Microsoft .NET
Metadata Unmanaged API Reflection API
Чтение метаданных + +
Генерация метаданных + +
Чтение CIL-кода – –
Генерация CIL-кода – +
162 CIL и системное программирование в Microsoft .NET Динамическая генерация кода 163
);
MethodBuilder mainMethod = Глава 5.
module.DefineGlobalMethod(
“main”, Динамическая генерация кода
MethodAttributes.Static |
MethodAttributes.Public,
typeof(void),
null 5.1. Введение в динамическую генерацию кода
);
MethodInfo ConsoleWriteLineMethod = Динамическая генерация кода – это прием программирования, за-
((typeof(Console)).GetMethod(“WriteLine”, ключающийся в том, что фрагменты кода порождаются и запускаются
new Type[] { typeof(string) } )); непосредственно во время выполнения программы. Этот прием был изве-
ILGenerator il = mainMethod.GetILGenerator(); стен достаточно давно, но усложнение архитектуры компьютеров, и, что
il.Emit(OpCodes.Ldstr,”Hello, World!”); особенно важно, усложнение наборов команд процессоров привело к то-
il.Emit(OpCodes.Call,ConsoleWriteLineMethod); му, что в последние 10-15 лет динамическая генерация кода в некоторой
il.Emit(OpCodes.Ret); степени потеряла популярность.
module.CreateGlobalFunctions(); Целью динамической генерации кода является использование ин-
assembly.SetEntryPoint( формации, доступной только во время выполнения программы, для повы-
mainMethod,PEFileKinds.ConsoleApplication шения качества исполняемого кода. В терминах метавычислений можно
); сказать, что динамическая генерация кода позволяет специализировать
assembly.Save(“hello.exe”); фрагменты программы по данным, известным во время выполнения.
} В некотором смысле, любой JIT-компилятор как раз использует ди-
} намическую генерацию кода: имея некоторую программу, записанную на
промежуточном языке (байт-коде), и зная, какой процессор работает в си-
4.4.3. Сравнение возможностей библиотек стеме, JIT-компилятор динамически транслирует программу в инструк-
Возможности, предоставляемые библиотекой Metadata Unmanaged ции этого процессора. При этом можно считать, что тип процессора – эта
API и библиотекой рефлексии, представлены в таблице 4.3. как раз та часть информации, которая становится известной только во
время выполнения программы.
Таблица 4.3. Сравнение возможностей библиотек Естественно, не стоит чересчур увлекаться динамической генерацией
кода: этот прием далеко не всегда дает ускорение программы. Можно ска-
Metadata Unmanaged API Reflection API
зать, что применение динамической генерации оправдано, если:
Чтение метаданных + + 1. процесс вычислений в некотором фрагменте программы
Генерация метаданных + + преимущественно определяется информацией, известной толь-
Чтение CIL-кода – – ко во время выполнения;
Генерация CIL-кода – + 2. запуск этого фрагмента осуществляется многократно;
3. выполнение фрагмента связано с существенными затратами
Из таблицы следует, что ни одна из библиотек, поставляемых вместе времени процессора.
с .NET Framework, не позволяет читать CIL-код, хотя эта возможность В .NET доступно два способа организации динамической генерации
требуется целому ряду метаинструментов (например, верификаторам и кода:
оптимизаторам кода). 1. порождение программы на языке C# и вызов компилятора C#;
2. непосредственное порождение метаданных и CIL-кода.
Страницы
- « первая
- ‹ предыдущая
- …
- 86
- 87
- 88
- 89
- 90
- …
- следующая ›
- последняя »
