LinQ Performace - Tối ưu bộ nhớ với yield return và file stream
Trong nhiều ứng dụng từ đơn giản đến phức tạp, thường rất phổ biến việc đọc dữ liệu từ các files dữ liệu nguồn (text, excel, ...), tiếp đó là các bước xử lý dữ liệu thô và cuối cùng là hiển thị hoặc lưu lại dữ liệu đã đươc xử lý. Các files dữ liệu nguồn thường tương đối lớn, chứa rất nhiều dòng text.
Để giải quyết bài toán này, các developers thường làm theo dạng như sau:
public List<T> ReadInformationFromFile(string fileName)
{
string[] lines = File.ReadAllLines(fileName);
List<T> result = new List<T>();
foreach (var line in lines)
{
T obj = ProcessText(line);
result.Add(obj);
}
return result;
}
Khi execute code, hàm trên sẽ 1 danh sách gồm toàn bộ dữ liệu đã được xử lý, sau đó mới kết thúc. Đoạn mã theo dạng như snippet trên, là 'ok' về mặt logic, rõ ràng về cách xử lý. Tuy nhiên, cách làm trên sẽ không được chấp nhận ở những công việc đòi hỏi phải tối ưu về memory (thường là các hệ thống phải triển khai trên máy chủ của khách hàng hoặc trên máy tính cá nhân của 1 khách hàng - những nơi mà bạn sẽ rất khó để yêu cầu khách hàng cho phép truy xuất vào để kiểm tra khi có lỗi hoặc yêu cầu tăng dung lượng bộ nhớ).
Để giải quyết tình huống này, 1 cách 'khôn ngoan' hơn là hãy dùng yield return. Nó sẽ giúp cho ứng dụng hoạt động tốt hơn trong những trường hợp low memory hoặc bad memory usage (dạng bazt simpson, memory leak).
Đoạn mã trên sẽ được chỉnh lại như theo dạng sau:
public IEnumerable<T> ReadInformationFromFile(string fileName)
{
using (StreamReader sr = new StreamReader(fileName))
{
while ((line = sr.ReadLine()) != null)
{
T obj = Process(line);
yield return obj;
}
}
}
Với hàm này, file được đọc từng dòng, đọc đến dòng nào xử lý và trả về đến đó, không phỉa đợi xử lý xong tất cả các line rồi mới trả về kết quả. Việc xử lý như vậy sẽ giúp memory 'chịu đựng' tốt hơn khi hệ thống hoạt động ở chế độ 'high performance'. Khi dùng yield, .Net/NetCore platform sẽ compile method lại thành 1 state machine (có thể tham khảo state machine design pattern), implement các method Next, Current, … của IEnumerator.
Hi vọng bài viết sẽ giúp ích cho các bạn trong công việc !
Tác giả: Nguyễn Thanh Sơn
Chú ý: Tất cả các bài viết trên TEDU.COM.VN đều thuộc bản quyền TEDU, yêu cầu dẫn nguồn khi trích lại trên website khác.
Bài viết liên quan
Sử dụng kiểu tập hợp (Enum)
Enum (viết tắt của Enumeration) trong C# là một kiểu dữ liệu đặc biệt cho phép bạn định nghĩa một tập hợp các hằng số có tên
Đọc thêmTính đóng gói (Encapsulation) và best practices trong OOP
(Tính đóng gói) là một trong những nguyên tắc cơ bản của lập trình hướng đối tượng (OOP).
Đọc thêmTính trừu tượng - Abstract classes and interfaces
Tính trừu tượng (Abstraction) trong OOP là kỹ thuật ẩn đi các chi tiết triển khai và chỉ hiển thị cho người dùng những chức năng cần thiết.
Đọc thêmTính chất kế thừa (Inheritance) và đa hình (polymorphism)
Kế thừa là cơ chế cho phép một lớp (class) kế thừa các thuộc tính và phương thức từ một lớp khác.
Đọc thêmCách debug ứng dụng C#
Hướng dẫn cách debug chương trình C# trong Visual Studio và Visual Studio Code
Đọc thêmTìm hiểu về các loại Collection trong C#
Trong C#, collections là các cấu trúc dữ liệu được sử dụng để lưu trữ và quản lý các nhóm đối tượng. C# cung cấp nhiều loại collections khác nhau để phù hợp với các yêu cầu cụ thể của lập trình viên
Đọc thêmTổng quan về Generic và Non-Generic Collection
Hiểu khái niệm Generic và Non-Generic Collection và phân biệt giữa Generic Collection và Non-Generic Collection.
Đọc thêmSử dụng mảng (Arrays)
Mảng trong C# là một cấu trúc dữ liệu lưu trữ một dãy các phần tử có bộ nhớ nằm liên tiếp nhau và có kích thước cố đinh.
Đọc thêmLập trình hướng đối tượng
Lập trình hướng đối tượng (Object Oriented Programing) hay còn gọi là OOP. Là một kỹ thuật lập trình cho phép các lập trình viên có thể ánh xạ các thực thể bên ngoài đời thực và trừu tượng hoá thành các class và object trong mã nguồn.
Đọc thêmVòng lặp (loop)
Trong thực tế khi bạn cần thực thi một khối lệnh nhiều lần. Vòng lặp cho phép chúng ta thực thi một câu lệnh hoặc một khối lệnh nhiều lần.
Đọc thêm