在C#开发中,Reflection.Emit允许开发者在运行时动态生成IL代码并创建类型、方法等,相比普通反射减少了部分元数据查找开销,但在高并发场景下其性能表现仍需结合实际场景分析。

反射发射的基本原理
Reflection.Emit的核心是System.Reflection.Emit命名空间下的类,比如AssemblyBuilder、ModuleBuilder、TypeBuilder、MethodBuilder等,开发者可以通过这些类手动编写IL指令,动态生成可执行的代码逻辑。和普通反射相比,它不需要在每次调用时都进行元数据查找和方法绑定,生成后的动态方法可以直接调用。
高并发下的性能测试对比
我们通过一个简单的高并发场景测试,对比直接调用、普通反射调用、反射发射生成的动态方法调用的性能差异。首先定义测试用的基础类:
public class TestService
{
public int Add(int a, int b)
{
return a + b;
}
}
接下来分别实现三种调用方式,并使用多线程模拟高并发场景:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
// 预热,避免JIT编译影响测试结果
TestDirectCall(1);
TestNormalReflection(1);
TestEmitCall(1);
int concurrencyCount = 100; // 并发线程数
int invokeCountPerThread = 10000; // 每个线程调用次数
Console.WriteLine("直接调用性能测试:");
TestDirectCallConcurrent(concurrencyCount, invokeCountPerThread);
Console.WriteLine("普通反射调用性能测试:");
TestNormalReflectionConcurrent(concurrencyCount, invokeCountPerThread);
Console.WriteLine("反射发射调用性能测试:");
TestEmitCallConcurrent(concurrencyCount, invokeCountPerThread);
}
// 直接调用
static int DirectCall(TestService service, int a, int b)
{
return service.Add(a, b);
}
static void TestDirectCall(int count)
{
var service = new TestService();
for (int i = 0; i < count; i++)
{
DirectCall(service, i, i + 1);
}
}
static void TestDirectCallConcurrent(int concurrency, int perThreadCount)
{
var service = new TestService();
var tasks = new List<Task>();
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < concurrency; i++)
{
tasks.Add(Task.Run(() =>
{
for (int j = 0; j < perThreadCount; j++)
{
DirectCall(service, j, j + 1);
}
}));
}
Task.WaitAll(tasks.ToArray());
sw.Stop();
Console.WriteLine($"总调用次数:{concurrency * perThreadCount},耗时:{sw.ElapsedMilliseconds}ms");
}
// 普通反射调用
static MethodInfo _addMethodInfo;
static object[] _params = new object[2];
static int NormalReflectionCall(TestService service, int a, int b)
{
if (_addMethodInfo == null)
{
_addMethodInfo = typeof(TestService).GetMethod("Add");
}
_params[0] = a;
_params[1] = b;
return (int)_addMethodInfo.Invoke(service, _params);
}
static void TestNormalReflection(int count)
{
var service = new TestService();
for (int i = 0; i < count; i++)
{
NormalReflectionCall(service, i, i + 1);
}
}
static void TestNormalReflectionConcurrent(int concurrency, int perThreadCount)
{
var service = new TestService();
var tasks = new List<Task>();
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < concurrency; i++)
{
tasks.Add(Task.Run(() =>
{
for (int j = 0; j < perThreadCount; j++)
{
NormalReflectionCall(service, j, j + 1);
}
}));
}
Task.WaitAll(tasks.ToArray());
sw.Stop();
Console.WriteLine($"总调用次数:{concurrency * perThreadCount},耗时:{sw.ElapsedMilliseconds}ms");
}
// 反射发射生成动态方法
static Func<TestService, int, int, int> _emitFunc;
static Func<TestService, int, int, int> GenerateEmitFunc()
{
var method = typeof(TestService).GetMethod("Add");
var dynamicMethod = new DynamicMethod("AddProxy", typeof(int), new[] { typeof(TestService), typeof(int), typeof(int) });
var ilGenerator = dynamicMethod.GetILGenerator();
// 加载第一个参数(TestService实例)
ilGenerator.Emit(OpCodes.Ldarg_0);
// 加载第二个参数a
ilGenerator.Emit(OpCodes.Ldarg_1);
// 加载第三个参数b
ilGenerator.Emit(OpCodes.Ldarg_2);
// 调用TestService的Add方法
ilGenerator.Emit(OpCodes.Callvirt, method);
// 返回结果
ilGenerator.Emit(OpCodes.Ret);
return (Func<TestService, int, int, int>)dynamicMethod.CreateDelegate(typeof(Func<TestService, int, int, int>));
}
static int EmitCall(TestService service, int a, int b)
{
if (_emitFunc == null)
{
_emitFunc = GenerateEmitFunc();
}
return _emitFunc(service, a, b);
}
static void TestEmitCall(int count)
{
var service = new TestService();
for (int i = 0; i < count; i++)
{
EmitCall(service, i, i + 1);
}
}
static void TestEmitCallConcurrent(int concurrency, int perThreadCount)
{
var service = new TestService();
var tasks = new List<Task>();
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < concurrency; i++)
{
tasks.Add(Task.Run(() =>
{
for (int j = 0; j < perThreadCount; j++)
{
EmitCall(service, j, j + 1);
}
}));
}
Task.WaitAll(tasks.ToArray());
sw.Stop();
Console.WriteLine($"总调用次数:{concurrency * perThreadCount},耗时:{sw.ElapsedMilliseconds}ms");
}
}
测试结果分析
在多次测试后,我们可以得到大致的性能排序:直接调用耗时最短,其次是反射发射生成的动态方法调用,普通反射调用耗时最长。在高并发场景下,反射发射的优势主要体现在以下几个方面:
- 动态方法生成后会被缓存,后续调用不需要重复生成,减少了IL生成的开销
- 避免了普通反射每次调用时的元数据查找和方法绑定开销
- 生成的动态方法和直接调用的性能差距在高并发下会被进一步缩小,因为JIT编译后的执行效率接近直接调用
但反射发射也存在性能瓶颈:
- 首次生成动态方法时需要编写IL指令、创建委托,这个过程有一定的开销,不适合频繁动态生成不同的方法
- 如果高并发下频繁创建新的动态方法,会导致内存占用上升,甚至触发GC,反而影响性能
- 动态方法的缓存如果处理不当,会出现线程安全问题,导致重复生成或者缓存失效
高并发下使用反射发射的优化建议
如果需要在高并发场景下使用Reflection.Emit,可以参考以下优化方案:
1. 缓存生成的动态委托
将生成的动态方法对应的委托缓存起来,避免重复生成,比如使用ConcurrentDictionary做线程安全的缓存:
using System.Collections.Concurrent;
public static class EmitDelegateCache
{
private static readonly ConcurrentDictionary<string, object> _cache = new ConcurrentDictionary<string, object>();
public static Func<TestService, int, int, int> GetAddDelegate()
{
return (Func<TestService, int, int, int>)_cache.GetOrAdd("TestService_Add", key =>
{
var method = typeof(TestService).GetMethod("Add");
var dynamicMethod = new DynamicMethod("AddProxy", typeof(int), new[] { typeof(TestService), typeof(int), typeof(int) });
var ilGenerator = dynamicMethod.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldarg_1);
ilGenerator.Emit(OpCodes.Ldarg_2);
ilGenerator.Emit(OpCodes.Callvirt, method);
ilGenerator.Emit(OpCodes.Ret);
return dynamicMethod.CreateDelegate(typeof(Func<TestService, int, int, int>));
});
}
}
2. 避免频繁动态生成不同类型或方法
反射发射适合场景是动态生成的逻辑相对固定,只需要生成一次就可以重复使用的情况,如果需要频繁生成不同的动态逻辑,建议评估是否可以使用其他方式替代,比如表达式树或者提前生成代码。
3. 注意动态程序集的生命周期
如果使用AssemblyBuilder创建动态程序集,要注意程序集的生命周期,避免不必要的内存占用,优先使用DynamicMethod,它的轻量级特性更适合高并发场景下的临时动态逻辑生成。
总结
在高并发场景下,Reflection.Emit的性能表现远优于普通反射,接近直接调用的性能,前提是做好动态委托的缓存,避免频繁生成动态方法。如果动态生成的逻辑是固定可复用的,反射发射是高并发下替代普通反射的优质选择,否则需要结合具体场景评估是否适用,避免出现性能反效果。
C#Reflection_Emit高并发性能优化修改时间:2026-07-12 09:12:36