2013-09-29 6 views
2

성능을 위해 수치 계산을위한 코드를 동적으로 생성하려는 응용 프로그램에서 작업하고 있습니다. . 이 계산을 데이터 기반 연산으로 수행하는 것은 너무 느립니다. 내 요구 사항을 설명하려면 다음 클래스를 고려하십시오.C#에서 런타임 코드 생성을위한 다양한 옵션 이해 (Roslyn, CodeDom, Linq Expressions ... ...)

내가 원하는 것은 JIT에서 프로세스의 외부 루프를 구현하는 함수를 컴파일하는 것입니다. 이 함수를 정의하는 코드는 현재 ProcessOneSample을 구현하는 데 사용되는 데이터에 의해 생성됩니다. 내가 기대하고있는 것을 명확히하기 위해 모든 사전 조회가 컴파일 프로세스에서 한 번 수행되기를 기대한다 (즉, JIT 컴파일은 사전의 관련 객체에 직접 바인드 될 것이다). 따라서 컴파일 된 코드가 실제로 컴파일 될 때 실행되면 마치 모든 조회가 하드 코드 된 것입니다.

내가 알아 내려고하는 것은이 문제를 해결하는 데 가장 좋은 도구입니다. 이 질문을하는 이유는 매우 다양한 옵션이 있기 때문입니다.

  • Roslyn을 사용하십시오. 현재의 걸림돌은 구문에서 표현식을 호스트 프로그램의 멤버 변수 (즉, 'state'사전의 값)에 바인딩하는 방법입니다. 이것이 가능합니까?
  • LINQ 식 (Expression.Compile)을 사용하십시오.
  • CodeDom을 사용하십시오. 최근에 내 Google 검색에서이 사실을 알게되었고,이 질문을 던지는 메시지가 나타났습니다. .NET에서 세 번째 컴파일 프레임 워크를 통해 자신의 길을 걸려 넘어지는 것에 너무 성급하게 생각하지 않습니다.
  • 내 원래 계획을 알고 있기 전에 이 도구들 중은 JIT가 컴파일 한 원시 코드 (x86)를 호출하는 것이 었습니다. 나는 이것에 약간 경험이있다, 그러나 나가 아직 해결하지 않은 많은 미지수가 여기에서있다. 위 옵션의 성능이 충분하지 않은 경우이 또한 내 백업 옵션입니다. 위의 3 가지 솔루션 중 하나를 선호 할 것입니다. 왜냐하면 나는 그들이 훨씬 더 간단 할 것이며, 그 중 하나가 작동하도록 가정 할 것이기 때문입니다!

누구나 공유 할 수있는 이와 같은 경험이 있습니까?

+1

나는 당신이 수동으로 무엇을 할 것인지 이해하지 못한다. x86 asm? 무슨 맛? 그 아이디어를 떨어 뜨리는 것이 가장 좋을 것 같습니다. –

+0

@SimonWhitehead 예, Process 메서드에서 설명한 비헤이비어를 구현하는 네이티브 함수를 생성 할 수 있습니다. 내 기본 옵션이 아니며 먼저 .Net 옵션 중 하나를 사용하여 작업하는 것을 선호합니다. 성능이 .Net 선택에서 문제가되는 경우에만이 옵션을 사용합니다. – dsharlet

+1

코드 속도를 높이는 최선의 방법이라고 확신하십니까? 사전 액세스가 실제로 문제가 있는지보기 위해 성능을 측정 했습니까? 인터페이스 변경을 고려 했습니까 (아마도'double' 속성을 사용하여 객체 컬렉션을 사용할 수 있습니다)? – svick

답변

5

나는 당신의 예제를 이해하지 못한다. 또한 그 코드 생성은 성능을 향상시키는 가장 좋은 방법이다.

그러나 코드 생성 옵션을 이해하려면 먼저 요구 사항을 고려하십시오. 성능은 원하는 것이지만, 코드 생성의 성능과 생성 된 코드의 성능이 있습니다. 이것들은 definitelly 같은 물건이 아니다. 그렇다면 코드 작성 및 가독성이 있습니다. 다른 옵션은이 점수가 매우 다른 점수를가집니다.

첫 번째 옵션은 Reflection.Emit입니다. 특히 DynamicMethod입니다. Reflection.Emit은 상당히 낮은 수준의 API이며 매우 효율적입니다 (즉, 코드 생성에 우수한 성능이 있음). 또한 생성되는 코드를 완전히 제어 할 수 있으므로 가장 효율적인 코드를 생성 할 수 있습니다 (또는 매우 나쁜 코드를 생성 할 가능성이 있음). 또한 C#과 같은 언어로 허용되는 언어에 국한되지 않고 CLR의 모든 기능을 손쉽게 활용할 수 있습니다. Reflection.Emit의 가장 큰 문제점은 작성해야 할 많은 양의 코드와이를 수행하는 데 필요한 IL에 대한 깊은 지식입니다. 이 코드를 작성하는 것은 쉽지 않으며 나중에 읽거나 유지 관리하는 것도 쉽지 않습니다.

Linq.Expressions, 특히 Compile method이 좋은 대안을 제공합니다.Reflection.Emit을 사용하여 본질적으로 DynamicMethod 생성을 둘러싼 유형 안전 래퍼라고 생각할 수 있습니다. 아마도 큰 문제는 아니지만 코드를 생성하는 데 약간의 오버 헤드가 있습니다. 표현의 자유에 관해서는, 일반적인 C# 방법으로 할 수있는 모든 것을 거의 할 수 있습니다. 생성 된 코드를 완벽하게 제어 할 수는 없지만 품질은 일반적으로 매우 좋습니다. 이 방법의 가장 큰 장점은이 기술을 사용하여 프로그램을 작성하고 읽는 것이 훨씬 쉽다는 것입니다.

Roslyn의 경우 구문 트리를 생성하거나 C# (또는 VB)을 생성하고 컴파일 할 구문 트리로 구문 분석 할 수 있습니다. 우리가 생산 코드를 사용할 수 없기 때문에 (글을 쓰는 시점에서) 성능이 어떻게 될지를 일찍 추측 할 수있는 방법입니다. 분명히 구문 트리를 구문 분석하는 데 약간의 오버 헤드가 발생하며, 단일 메서드를 생성하는 경우 Paralle에서 여러 메서드를 생성 할 수있는 Roslyn의 기능이 크게 도움이되지 않습니다. Roslyn을 사용하면 매우 읽기 쉬운 프로그램을 사용할 수있는 잠재력이 있습니다.

CodeDom에 관해서는, 나는 그것을 추천합니다. 이것은 매우 오래된 API로, 현재 구현에서 코드를 컴파일하기 위해 CSC.exe 프로세스를 시작합니다. 또한 완전한 C# 언어를 지원하지 않는다고 생각합니다.