Khi làm việc với ánh xạ đối tượng trong .NET, các lập trình viên thường tranh luận giữa việc sử dụng AutoMapper – một thư viện mạnh mẽ cho ánh xạ tự động – và viết mapping thủ công. Để so sánh hiệu suất của hai phương pháp này, tôi đã thiết lập một bài kiểm tra BenchmarkDotNet cho bốn cấu trúc dữ liệu được mô tả dưới đây.
Mục lục
Thiết Lập Thử Nghiệm
Tôi đã tạo:
- Các lớp Source và Destination
- Các bản ghi (record) Source và Destination
- Các cấu trúc bản ghi (record struct) Source và Destination
Tất cả đều chia sẻ cùng một bộ thuộc tính:
- Các trường cơ bản như
Id,Name,Description,CreatedAt - Mười trường bổ sung (
Field1,Field2, v.v.) với nhiều kiểu dữ liệu khác nhau (int,string,double,decimal,bool,DateTime,Guid,long,float,char)
Phương Pháp Ánh Xạ
AutoMapper
Chúng ta cấu hình ánh xạ cho từng cặp source/destination:
var config = new MapperConfiguration(cfg => {<br> cfg.CreateMap<SourceClass, DestinationClass>();<br> cfg.CreateMap<SourceRecord, DestinationRecord>();<br> cfg.CreateMap<SourceRecordStruct, DestinationRecordStruct>();<br>});
Thư viện xử lý việc gán thuộc tính bên dưới, làm cho code trở nên ngắn gọn nhưng giới thiệu một chi phí hiệu suất nhất định.
Mapping Thủ Công
Chúng ta gán thuộc tính một cách rõ ràng trong code. Ví dụ, ánh xạ từ SourceClass sang DestinationClass:
public class SourceClass {<br> public int Id { get; set; }<br> public string Name { get; set; }<br> public string Description { get; set; }<br> public DateTime CreatedAt { get; set; }<br> public int Field1 { get; set; }<br> public string Field2 { get; set; }<br> public double Field3 { get; set; }<br> public decimal Field4 { get; set; }<br> public bool Field5 { get; set; }<br> public DateTime Field6 { get; set; }<br> public Guid Field7 { get; set; }<br> public long Field8 { get; set; }<br> public float Field9 { get; set; }<br> public char Field10 { get; set; }<br>}
Cấu Hình Benchmark
- BenchmarkDotNet: Sử dụng
[MemoryDiagnoser]để đo lường bộ nhớ được cấp phát và[SimpleJob(RuntimeMoniker.Net90)]để chạy trên .NET 9.0 - Mỗi phương pháp ánh xạ là một benchmark riêng biệt:
AutoMapperMapping()vs.ManualMapping()AutoMapperMappingRecord()vs.ManualMappingRecord()AutoMapperMappingRecordStruct()vs.ManualMappingRecordStruct()
Kết Quả Thử Nghiệm
Dưới đây là kết quả từ BenchmarkDotNet. Lưu ý cả Thời gian trung bình (tính bằng nanosecond) và Bộ nhớ được cấp phát (tính bằng byte):
Mapping Thủ Công nhanh hơn đáng kể trên tất cả các bài kiểm tra – với hệ số từ ~3 đến 10 lần.
Record Struct cho thấy khoảng cách hiệu suất lớn nhất:
- AutoMapper: ~96 ns
- Mapping thủ công: ~8.5 ns
Cấp phát bộ nhớ:
- AutoMapper liên tục cấp phát ~120 byte
- Mapping thủ công với records và record structs không hiển thị thêm cấp phát heap nào (ký hiệu ‘-‘ trong bảng)
Phân Tích Sự Đánh Đổi
Tiện Lợi vs. Hiệu Suất
AutoMapper giảm thiểu code trùng lặp và có thể làm code dễ đọc hơn. Tuy nhiên, nó giới thiệu chi phí về cả chu kỳ CPU và cấp phát bộ nhớ.
Bối Cảnh Quan Trọng
- Nếu bạn hiếm khi ánh xạ số lượng lớn đối tượng trong các đường dẫn quan trọng về hiệu suất, chi phí này có lẽ không đáng kể
- Nếu ứng dụng của bạn cần ánh xạ hàng nghìn hoặc hàng triệu đối tượng mỗi giây, phương pháp thủ công (đặc biệt với record structs) có thể mang lại lợi ích hiệu suất đáng kể
Khả Năng Bảo Trì
Mapping thủ công có thể trở nên cồng kềnh nếu bạn có nhiều thuộc tính hoặc kiểu. Mỗi thuộc tính mới yêu cầu thay đổi code. AutoMapper tự động ánh xạ các thuộc tính có tên khớp nhau, giảm thiểu nỗ lực bảo trì.
Kết Luận
Bạn nên chọn cái nào? Nó phụ thuộc vào trường hợp sử dụng cụ thể của bạn:
- Sử dụng AutoMapper nếu bạn coi trọng sự đơn giản, khả năng bảo trì và năng suất phát triển, và không gặp vấn đề về hiệu suất trong ánh xạ
- Sử dụng Mapping Thủ Công nếu mỗi nanosecond đều quan trọng, trong các tình huống thời gian thực hoặc thông lượng cao và bạn sẵn sàng đầu tư vào việc viết và duy trì code ánh xạ rõ ràng
Bằng cách chạy các benchmark này, chúng ta thấy một lợi thế hiệu suất rõ ràng cho mapping thủ công, đặc biệt với record structs. Tuy nhiên, đây có thể không phải là yếu tố quyết định trong mọi ứng dụng. Hãy đánh giá nhu cầu của bạn, đo lường hiệu suất thực tế và chọn phương pháp cân bằng tốt nhất giữa tốc độ và khả năng bảo trì.


