Struct 생성 성능 비교 (반사, 일반 반사, 일반 생성, 캐시 Emit)
12720 단어 struct
직접 생성 -> 캐시 Emit-> 일반 반사 -> 일반 생성 -> 반사 (직접 호출보다 약 68배 느린 반사) 로 캐시 Emit이 아닌 것을 피합니다.
Struct의 성능 비교Struct와 Class는 하나의 값 형식이고 하나의 인용 형식이며 하나의 창고에 분배되고 하나의 무더기에 분배되기 때문에 Class에서 창설하는 원칙이 모두 Struct에서 창설하는 원칙과 일치하는 것은 아니다.우리는 여전히 코드로 이야기한다.
테스트된 Struct:
struct
TestEntity { }
1. 수동으로 만들기
[TestInfo(Category
=
"
Struct.Constructor
"
, Name
=
"
Direct
"
)]
class
DirectInvokeMode : IRunable
{
public
void
Run()
{
new
TestEntity();
}
}
2. 반사 생성
[TestInfo(Category
=
"
Struct.Constructor
"
, Name
=
"
Reflect
"
)]
class
ReflectInvokeMode : IRunable
{
public
void
Run()
{
Activator.CreateInstance(
typeof
(TestEntity));
}
}
3. 일반 반사 생성
[TestInfo(Category
=
"
Struct.Constructor
"
, Name
=
"
GenericReflect
"
)]
class
GenericReflectInvokeMode : IRunable
{
public
void
Run()
{
Activator.CreateInstance
<
TestEntity
>
();
}
}
4. 일반 직접 생성
[TestInfo(Category
=
"
Struct.Constructor
"
, Name
=
"
Generic Create
"
)]
class
GenericCreateInvokeMode : IRunable
{
public
void
Run()
{
Create
<
TestEntity
>
();
}
static
T Create
<
T
>
()
where
T :
new
()
{
return
new
T();
}
}
5. 캐시 Emit 생성: 구조체에 기본 구조 함수가 없기 때문에 IL로 emit를 할 수 없습니다. 여기서 ExpressionTree로 Emit을 진행합니다.
/// <summary>
///
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static DefaultConstructorHandler GetDefaultCreator(this Type type)
{
if(type == Types.String)
{
DefaultConstructorHandler s = ()=>null;
return s;
}
var ctorExpression = Expression.Lambda<DefaultConstructorHandler>(Expression.Convert(Expression.New(type), typeof(object)));
var ctor = ctorExpression.Compile();
DefaultConstructorHandler handler = () =>
{
try
{
return ctor();
}
catch (TargetInvocationException ex)
{
throw ex.InnerException.Handle();
}
catch (Exception ex)
{
throw ex.Handle();
}
};
return handler;
}
위의 Emit 코드를 기반으로 작성된 Struct의 코드는 다음과 같습니다.
[TestInfo(Category = "Struct.Constructor", Name = "Emit")]
class EmitInvokeMode : IRunable
{
//
static readonly DefaultConstructorHandler Ctor = typeof(TestEntity).GetDefaultCreator();
public void Run()
{
Ctor();
}
}
테스트 함수:
for
(
int
i
=
0
; i
<
3
; i
++
)
{
foreach
(var item
in
Mappers)
CodeTimer.Time(item.Metadata.Category
+
"
->
"
+
item.Metadata.Name,
100000
, ()
=>
item.Value.Run());
}
출력 결과는 다음과 같습니다.
------ Test started: Assembly: NLite.Test.dll ------
Struct.Constructor->Direct
Time Elapsed: 4ms
CPU Cycles: 156,250
Gen 0: 0
Gen 1: 0
Gen 2: 0
Struct.Constructor->Reflect
Time Elapsed: 330ms
CPU Cycles: 2,968,750
Gen 0: 1
Gen 1: 0
Gen 2: 0
Struct.Constructor->GenericReflect
Time Elapsed: 26ms
CPU Cycles: 156,250
Gen 0: 1
Gen 1: 0
Gen 2: 0
Struct.Constructor->Generic Create
Time Elapsed: 3ms
CPU Cycles: 156,250
Gen 0: 0
Gen 1: 0
Gen 2: 0
Struct.Constructor->Emit
Time Elapsed: 7ms
CPU Cycles: 0
Gen 0: 1
Gen 1: 0
Gen 2: 0
Struct.Constructor->Direct
Time Elapsed: 1ms
CPU Cycles: 0
Gen 0: 0
Gen 1: 0
Gen 2: 0
Struct.Constructor->Reflect
Time Elapsed: 329ms
CPU Cycles: 3,281,250
Gen 0: 0
Gen 1: 0
Gen 2: 0
Struct.Constructor->GenericReflect
Time Elapsed: 22ms
CPU Cycles: 312,500
Gen 0: 0
Gen 1: 0
Gen 2: 0
Struct.Constructor->Generic Create
Time Elapsed: 4ms
CPU Cycles: 156,250
Gen 0: 0
Gen 1: 0
Gen 2: 0
Struct.Constructor->Emit
Time Elapsed: 3ms
CPU Cycles: 156,250
Gen 0: 0
Gen 1: 0
Gen 2: 0
Struct.Constructor->Direct
Time Elapsed: 1ms
CPU Cycles: 0
Gen 0: 0
Gen 1: 0
Gen 2: 0
Struct.Constructor->Reflect
Time Elapsed: 339ms
CPU Cycles: 3,437,500
Gen 0: 0
Gen 1: 0
Gen 2: 0
Struct.Constructor->GenericReflect
Time Elapsed: 22ms
CPU Cycles: 312,500
Gen 0: 0
Gen 1: 0
Gen 2: 0
Struct.Constructor->Generic Create
Time Elapsed: 2ms
CPU Cycles: 0
Gen 0: 0
Gen 1: 0
Gen 2: 0
Struct.Constructor->Emit
Time Elapsed: 3ms
CPU Cycles: 0
Gen 0: 0
Gen 1: 0
Gen 2: 0
1 passed, 0 failed, 0 skipped, took 2.53 seconds (NUnit 2.5.5).
테스트 결과에서 알 수 있듯이 범용 창설은 Emit을 초과하고 범용 반사를 초과한다. 이것은Class의 창설 테스트에서 Emit은 범용 반사를 초과하고 범용 반사는 범용 창설을 초과한다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
9-1. 구조체와 클래스 비교, 구조체 개념(struct)구조체와 클래스는 프로그램 코드의 구성요소가 되는 범용 구조이다. 상수, 변수, 그리고 함수를 정의하는 것과 같은 구문을 사용해서 구조체와 클래스에 프로퍼티와 메서드를 기능적으로 추가할 수 있다. 스위프트에서 클래스...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.