2012-09-21 5 views
3

나는 AutoMapper를 좋아한다. 나는 wcf 서비스 모델에서 비즈니스 모델에 이르기까지 서로 다른 도메인 사이의 엔티티 매핑을 위해 많은 프로젝트에서 이것을 사용하고있다.Automapper 성능을 향상시키는 방법은 무엇입니까?

샘플 웹 사이트에서 일부 부하 테스트 (VS Profiler 사용)를 수행 한 결과, AutoMapper가 높은 CPU 사용량을 책임지고 있음을 발견했습니다.

나는이 문제에 대한 몇 가지 장치를했을 : 끝에

using Microsoft.VisualStudio.TestTools.UnitTesting; 
using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 

namespace AutoMapper.Tests 
{ 
    [TestClass] 
    public class UnitTest 
    { 
     public class ClassSource 
     { 
      public string PropertyA { get; set; } 
      public int PropertyB { get; set; } 
      public NestedClassSource PropertyC { get; set; } 
     } 

     public class NestedClassSource 
     { 
      public string PropertyD { get; set; } 
      public DateTime PropertyE { get; set; } 
      public List<int> PropertyF { get; set; } 
     } 

     public class ClassDestination 
     { 
      public string PropertyA { get; set; } 
      public int PropertyB { get; set; } 
      public NestedClassDestination PropertyC { get; set; } 
     } 

     public class NestedClassDestination 
     { 
      public string PropertyD { get; set; } 
      public DateTime PropertyE { get; set; } 
      public List<int> PropertyF { get; set; } 
     } 

     [TestMethod] 
     public void MappingPerfTests() 
     { 
      Mapper.Initialize(a => 
      { 
       a.CreateMap<ClassSource, ClassDestination>(); 
       a.CreateMap<NestedClassSource, NestedClassDestination>(); 

      }); 
      Mapper.AssertConfigurationIsValid(); 

      IList<ClassSource> items = GenerateRandomSources(nbItems: 500); 

      //automapper 
      MicroBench(() => 
      { 
       var res = Mapper.Map<IList<ClassSource>, IList<ClassDestination>>(items); 
      }, nbIterations: 10); 
      // will take nearly 30 ms per test 
      // total : 300 ms 


      //manual mapper 
      MicroBench(() => 
      { 
       var res = new List<ClassDestination>(items.Count); 
       foreach (var source in items) 
       { 
        res.Add(new ClassDestination() 
        { 
         PropertyA = source.PropertyA, 
         PropertyB = source.PropertyB, 
         PropertyC = new NestedClassDestination() 
         { 
          PropertyD = source.PropertyC.PropertyD, 
          PropertyE = source.PropertyC.PropertyE, 
          PropertyF = new List<int>(source.PropertyC.PropertyF) 
         } 

        }); 
       } 
      }, nbIterations: 10); 
      // will take nearly 0 ms per test 
      // total : 1 ms 

     } 

     private IList<ClassSource> GenerateRandomSources(int nbItems = 1000) 
     { 
      IList<ClassSource> res = new List<ClassSource>(100); 
      foreach (var i in Enumerable.Range(1, nbItems)) 
      { 
       ClassSource item = new ClassSource() 
       { 
        PropertyA = "PropertyA", 
        PropertyB = i, 
        PropertyC = new NestedClassSource() { PropertyD = "PropertyD", PropertyE = DateTime.Now, PropertyF = Enumerable.Range(1, 10).ToList() } 
       }; 
       res.Add(item); 
      } 
      return res; 
     } 

     private void MicroBench(Action action, int nbIterations = 1000) 
     { 
      long totalElapsed = 0L; 

      foreach (var i in Enumerable.Range(1, nbIterations)) 
      { 
       Stopwatch watcher = Stopwatch.StartNew(); 

       action(); 

       watcher.Stop(); 
       Console.WriteLine("test : {0} ms", watcher.ElapsedMilliseconds); 
       totalElapsed += watcher.ElapsedMilliseconds; 
      } 

      Console.WriteLine("total : {0} ms", totalElapsed); 
      Console.WriteLine("avg : {0} ms", totalElapsed/nbIterations); 

     } 
    } 
} 

는 AutoMapper은 아주 느린 : 시험 당 평균 30 밀리 수동 매핑 미만 MS 걸리는 반면. 나는 "단지"500 개의 "단순한"객체를 매핑합니다! 어쩌면 MVC ViewModel의 경우 이것은 거의 발생하지 않지만 매핑하는 다른 MVC는 자주 발생할 수 있습니다.

30ms는 빠르지 만 실제 문제는이 30ms (아무 것도 없음)가 입니다. 웹 서버의 CPU 시간이 서버가 과다한 부하 (동시 사용자 100 명)를 어떻게 처리합니까? 사실, 우리 짐 테스트가 경고를 던지는 이유입니다.

Mapper.CreateMapExpression으로 linq 표현식을 생성하는 방법을 찾았지만 불행히도 표현식에 중첩 유형이나 옵션이 포함되어 있지 않습니다.

따라서 AutoMapper 성능을 향상시킬 수있는 방법이 있습니까? 모범 사례가 있습니까? 이 문서에

답변

12

덕분에, 그 대안뿐만 아니라 성능 측정, AutoMapper에 대한 몇 가지 통찰력을 얻을 수 있습니다. 나는 그것이 당신에게 더 전체 론적 견해를 줄 것이라고 생각하고 당신은 그만큼의 성과를 염려하지 않을 것입니다.

Which is faster: AutoMapper, Valuinjector, or manual mapping? To what degree is each one faster?

내 의견은 비슷합니다 - 귀하의 질문에 대한 정답은 (당신이 정말로 당신의 게시물에 질문을하지 않았다 :)) 없습니다. CPU 시간 대 휴먼 시간 (유지) 사이의 균형을 유지하면 두 시간을 비교할 수 없습니다. 그러나이 IMHO는 결정적인 요인이되어야하지만 분명히 당신에게 달려 있습니다.

편집

당신이 당신의 상황에 관련된 몇 가지 단서를 찾을 수 있는지 확인하기 위해 여기 찾고 시도해보십시오 Need to speed up automapper...It takes 32 seconds to do 113 objects 또한

다른 링크를 (비록 2009 년) ... 여전히,하지만 어쩌면 관련 Analyzing AutoMapper performance

감사합니다. 도움이되기를 바랍니다.

+1

물론 가능합니다. 그러나 Automapper는 이미 프로젝트에 포함되어 있으며 개발 팀에서는이를 배웠습니다. 부하 테스트 결과가 자동 작업자에게는 좋지 않기 때문에 성능 향상을위한 도움말을 검색하고 있습니다. – Cybermaxs

관련 문제