Hiệu suất trong .NET Core

Hiệu suất trong .NET Core

Hiệu suất trong .NET Core

Chào mọi người! Bài viết này là tập hợp các Thực tiễn Tốt nhất mà tôi và các đồng nghiệp đã sử dụng trong một thời gian dài khi làm việc trong các dự án khác nhau.

Thông tin về máy thực hiện tính toán:BenchmarkDotNet=v0.11.5, OS=Windows 10. 0.18362
CPU Intel Core i5-8250U 1.60GHz (Kaby Lake R), 1 CPU, 8 nhân logic và 4 nhân vật lý
.NET Core SDK=3.0.100
[Máy chủ]: .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), RyuJIT 64bit
Cốt lõi: .NET Core 2.2.7 (CoreCLR 4.6.28008.02, CoreFX 4.6.28008.03), RyuJIT 64bit
[Máy chủ]: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), RyuJIT 64bit
Cốt lõi: .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), RyuJIT 64bit

Công việc=Thời gian chạy cốt lõi=Lõi

ToList vs ToArray và Chu kỳ


Tôi đã định chuẩn bị thông tin này bằng việc phát hành .NET Core 3.0, nhưng họ đã đánh bại tôi, tôi không muốn đánh cắp vinh quang của người khác và sao chép thông tin của người khác nên tôi sẽ chỉ chỉ ra liên kết đến một bài viết hay trong đó sự so sánh được mô tả chi tiết.

Thay mặt tôi, tôi chỉ muốn trình bày với bạn các phép đo và kết quả của tôi; tôi đã thêm các vòng lặp ngược vào chúng cho những người yêu thích vòng lặp viết “kiểu C++”.

Mã Code:

public class Bench
    {
        private List<int> _list;
        private int[] _array;

        [Params(100000, 10000000)] public int N;

        [GlobalSetup]
        public void Setup()
        {
            const int MIN = 1;
            const int MAX = 10;
            Random random = new Random();
            _list = Enumerable.Repeat(0, N).Select(i => random.Next(MIN, MAX)).ToList();
            _array = _list.ToArray();
        }

        [Benchmark]
        public int ForList()
        {
            int total = 0;
            for (int i = 0; i < _list.Count; i++)
            {
                total += _list[i];
            }

            return total;
        }
        
        [Benchmark]
        public int ForListFromEnd()
        {
            int total = 0;t
            for (int i = _list.Count-1; i > 0; i--)
            {
                total += _list[i];
            }

            return total;
        }

        [Benchmark]
        public int ForeachList()
        {
            int total = 0;
            foreach (int i in _list)
            {
                total += i;
            }

            return total;
        }

        [Benchmark]
        public int ForeachArray()
        {
            int total = 0;
            foreach (int i in _array)
            {
                total += i;
            }

            return total;
        }

        [Benchmark]
        public int ForArray()
        {
            int total = 0;
            for (int i = 0; i < _array.Length; i++)
            {
                total += _array[i];
            }

            return total;
        }
        
        [Benchmark]
        public int ForArrayFromEnd()
        {
            int total = 0;
            for (int i = _array.Length-1; i > 0; i--)
            {
                total += _array[i];
            }

            return total;
        }
    }

Tốc độ hiệu suất trong .NET Core 2.2 và 3.0 gần như giống hệt nhau. Đây là những gì tôi có thể có được trong .NET Core 3.0:

Hiệu suất trong .NET Core

Hiệu suất trong .NET Core

Chúng ta có thể kết luận rằng việc xử lý lặp lại bộ sưu tập Mảng nhanh hơn do được tối ưu hóa bên trong và phân bổ kích thước bộ sưu tập rõ ràng. Cũng cần nhớ rằng bộ sưu tập Danh sách có những ưu điểm riêng và bạn nên sử dụng bộ sưu tập phù hợp tùy theo yêu cầu tính toán. Ngay cả khi bạn viết logic để làm việc với các vòng lặp, đừng quên rằng đây là một vòng lặp thông thường và nó cũng có thể được tối ưu hóa vòng lặp. Một bài viết đã được đăng trên habr cách đây khá lâu: https://habr.com/ru/post/124910/. Nó vẫn có liên quan và khuyến khích đọc.

Quăng

Một năm trước, tôi làm việc tại một công ty trong một dự án cũ, trong dự án đó, việc xử lý xác thực trường thông qua cấu trúc thử bắt-ném là điều bình thường. Khi đó tôi đã hiểu rằng đây là logic kinh doanh không lành mạnh cho dự án, vì vậy bất cứ khi nào có thể, tôi đã cố gắng không sử dụng thiết kế như vậy. Nhưng hãy cùng tìm hiểu xem tại sao cách xử lý lỗi với cách xây dựng như vậy lại tệ. Tôi đã viết một đoạn mã nhỏ để so sánh hai cách tiếp cận và tạo điểm chuẩn cho từng tùy chọn.

Mã Code:

        public bool ContainsHash()
        {
            bool result = false;
            foreach (var file in _files)
            {
                var extension = Path.GetExtension(file);
                if (_hash.Contains(extension))
                    result = true;
            }

            return result;
        }

        public bool ContainsHashTryCatch()
        {
            bool result = false;
            try
            {
                foreach (var file in _files)
                {
                    var extension = Path.GetExtension(file);
                    if (_hash.Contains(extension))
                        result = true;
                }
                
                if(!result) 
                    throw new Exception("false");
            }
            catch (Exception e)
            {
                result = false;
            }

            return result;
        }

Kết quả trong .NET Core 3.0 và Core 2.2 có kết quả tương tự (.NET Core 3.0):

Hiệu suất trong .NET Core

Hiệu suất trong .NET Core

Thử bắt làm cho mã khó hiểu hơn và tăng thời gian thực hiện chương trình của bạn. Nhưng nếu bạn cần cấu trúc này, bạn không nên chèn những dòng mã không mong muốn xử lý lỗi - điều này sẽ làm cho mã dễ hiểu hơn. Trên thực tế, việc tải hệ thống không phải là việc xử lý các ngoại lệ mà là việc tự đưa ra các lỗi thông qua cấu trúc ném Ngoại lệ mới.

Việc ném ngoại lệ chậm hơn một số lớp sẽ thu thập lỗi ở định dạng được yêu cầu. Nếu bạn đang xử lý một biểu mẫu hoặc một số dữ liệu và bạn biết rõ lỗi đó là gì, tại sao không xử lý nó?

Bạn không nên viết cấu trúc Throw new Exception() nếu tình huống này không phải là ngoại lệ. Xử lý và ném một ngoại lệ là rất tốn kém!!!

ToLower, ToLowerInvariant, ToUpper, ToUpperInvariant

Hơn 5 năm kinh nghiệm làm việc trên nền tảng .NET, tôi đã gặp nhiều dự án sử dụng đối sánh chuỗi. Tôi cũng thấy hình ảnh sau: có một giải pháp Doanh nghiệp với nhiều dự án, mỗi dự án thực hiện so sánh chuỗi một cách khác nhau. Nhưng nên sử dụng cái gì và thống nhất nó như thế nào? Trong cuốn sách CLR via C# của Richter, tôi đọc được thông tin rằng phương thức ToUpperInvariant() nhanh hơn ToLowerInvariant().

Trích từ cuốn sách:

Hiệu suất trong .NET Core

Tất nhiên, tôi không tin vào điều đó và quyết định chạy một số thử nghiệm trên .NET Framework và kết quả khiến tôi bị sốc - hiệu suất tăng hơn 15%. Sau đó, khi đến nơi làm việc vào sáng hôm sau, tôi đưa những số đo này cho cấp trên và cấp cho họ quyền truy cập vào mã nguồn. Sau đó, 2 trong số 14 dự án đã được thay đổi để phù hợp với các phép đo mới và vì hai dự án này tồn tại để xử lý các bảng Excel khổng lồ nên kết quả có ý nghĩa quan trọng hơn đối với sản phẩm.

Mình cũng đưa ra cho các bạn số đo của các phiên bản .NET Core khác nhau để mỗi bạn có thể đưa ra lựa chọn hướng tới giải pháp tối ưu nhất. Và tôi chỉ muốn nói thêm rằng ở công ty nơi tôi làm việc, chúng tôi sử dụng ToUpper() để so sánh các chuỗi.

Mã Code:

public const string defaultString =  "VXTDuob5YhummuDq1PPXOHE4PbrRjYfBjcHdFs8UcKSAHOCGievbUItWhU3ovCmRALgdZUG1CB0sQ4iMj8Z1ZfkML2owvfkOKxBCoFUAN4VLd4I8ietmlsS5PtdQEn6zEgy1uCVZXiXuubd0xM5ONVZBqDu6nOVq1GQloEjeRN8jXrj0MVUexB9aIECs7caKGddpuut3";

        [Benchmark]
        public bool ToLower()
        {
            return defaultString.ToLower() == defaultString.ToLower();
        }

        [Benchmark]
        public bool ToLowerInvariant()
        {
            return defaultString.ToLowerInvariant() == defaultString.ToLowerInvariant();
        }

        [Benchmark]
        public bool ToUpper()
        {
            return defaultString.ToUpper() == defaultString.ToUpper();
        }

        [Benchmark]
        public bool ToUpperInvariant()
        {
            return defaultString.ToUpperInvariant() == defaultString.ToUpperInvariant();
        }

Hiệu suất trong .NET Core

Hiệu suất trong .NET Core

Trong .NET Core 3.0, mức tăng của mỗi phương thức này là ~x2 và cân bằng việc triển khai giữa chúng.

Hiệu suất trong .NET Core

Hiệu suất trong .NET Core

Biên soạn bậc

Trong bài viết trước tôi đã mô tả ngắn gọn chức năng này, tôi xin đính chính và bổ sung lời nói của mình. Quá trình biên dịch đa cấp giúp tăng tốc thời gian khởi động giải pháp của bạn, nhưng bạn phải hy sinh rằng các phần mã của bạn sẽ được biên dịch thành một phiên bản được tối ưu hóa hơn ở chế độ nền, điều này có thể gây ra một chi phí nhỏ. Với sự ra đời của NET Core 3.0, thời gian xây dựng các dự án có kích hoạt tính năng biên dịch theo cấp đã giảm xuống và các lỗi liên quan đến công nghệ này đã được sửa. Trước đây, công nghệ này đã dẫn đến lỗi trong các yêu cầu đầu tiên trong ASP.NET Core và bị treo trong quá trình xây dựng đầu tiên ở chế độ biên dịch đa cấp. Nó hiện được bật theo mặc định trong .NET Core 3.0, nhưng bạn có thể tắt nó nếu muốn. Nếu bạn ở vị trí trưởng nhóm, cấp cao, cấp trung hoặc bạn là trưởng bộ phận thì bạn phải hiểu rằng việc phát triển dự án nhanh chóng sẽ làm tăng giá trị của nhóm và công nghệ này sẽ cho phép bạn tiết kiệm thời gian cho cả hai nhà phát triển. và thời gian của dự án.

Lên cấp .NET

Nâng cấp phiên bản .NET Framework / .NET Core của bạn. Thông thường, mỗi phiên bản mới đều cung cấp thêm hiệu suất và bổ sung thêm các tính năng mới.

Nhưng chính xác những lợi ích là gì? Hãy xem xét một số trong số họ:

  • .NET Core 3.0 đã giới thiệu hình ảnh R2R sẽ giảm thời gian khởi động của ứng dụng .NET Core.
  • Với phiên bản 2.2, Tier Compilation đã xuất hiện, nhờ đó các lập trình viên sẽ mất ít thời gian hơn để khởi động một dự án.
  • Hỗ trợ các tiêu chuẩn .NET mới.
  • Hỗ trợ phiên bản mới của ngôn ngữ lập trình.
  • Tối ưu hóa, với mỗi phiên bản mới, việc tối ưu hóa các thư viện cơ sở Collection/Struct/Stream/String/Regex và nhiều cải tiến khác. Nếu bạn đang di chuyển từ .NET Framework sang .NET Core, bạn sẽ nhận được sự tăng cường hiệu suất đáng kể. Để làm ví dụ, tôi đính kèm một liên kết tới một số tối ưu hóa đã được thêm vào .NET Core 3.0: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/

Hiệu suất trong .NET Core

Kết luận

Khi viết mã, bạn nên chú ý đến các khía cạnh khác nhau của dự án và sử dụng các tính năng của ngôn ngữ lập trình và nền tảng để đạt được kết quả tốt nhất. Tôi sẽ rất vui nếu bạn chia sẻ kiến ​​thức của mình liên quan đến tối ưu hóa trong .NET.

Liên kết tới github

Nguồn: www.habr.com

Mua dịch vụ lưu trữ đáng tin cậy cho các trang web có bảo vệ DDoS, máy chủ VPS VDS 🔥 Mua dịch vụ hosting website đáng tin cậy với bảo vệ DDoS, máy chủ VPS VDS | ProHoster