Ứng dụng máy chủ của chúng tôi có một số phương thức, được gọi theo thứ tự lặp qua kết quả 20M và chuyển đổi nó. Mỗi phương pháp trong đường ống này lưu trữ bản sao dữ liệu 200+ megabyte, với RAM có thể dự đoán trước và tác động hiệu suất GC.Mẫu để chia nhỏ C# bằng cách sử dụng khối để bật lập trình chức năng
Mỗi phương pháp sau một mô hình tương tự:
public HugeCollection1 Step1 (SomeType sourceData)
{
var transformed = new List<RowType>;
using (var foo = InitializeSomethingExpensive(sourceData))
{
foreach (var row in foo)
{
transformed.Add (TransformRow(row));
}
}
return transformed;
}
Sau đó, các phương pháp này được gọi là trong một đường ống, ví dụ
var results1 = Step1(sourceData);
var results2 = Step2(results1);
var results3 = Step3(results2);
...
var finalResults = StepN (resultsNMinus1);
return finalResults; // final results
Tôi muốn biến điều này thành giải pháp chức năng hơn lặp qua dữ liệu nguồn gốc mà không bao giờ giữ toàn bộ tập dữ liệu trong RAM. Tôi muốn kết thúc với Danh sách kết quả cuối cùng mà không có bất kỳ bộ sưu tập trung gian nào.
Nếu không có thiết lập bắt buộc ở mỗi giai đoạn của đường ống, thì giải pháp sẽ đơn giản: chỉ cần chạy từng chuyển đổi cho mỗi hàng và chỉ lưu trữ kết quả cuối cùng.
var transformed = new List<SmallResult>;
// TODO: How to set up and ensure teardown of the *other* pipeline steps?
using (var foo = InitializeSomethingExpensive(sourceData))
{
foreach (var row in foo)
{
object result = row;
foreach (var step in Pipeline)
{
result = step.Transform (result);
}
transformed.Add (result as SmallResult);
}
}
return transformed;
Nhưng ngày nay, mỗi bước đường ống riêng biệt này có quy trình thiết lập và xé riêng được thực thi thông qua khối using
.
Mô hình tốt để cấu trúc lại từng phương pháp đường ống này để mã thiết lập/teardown được đảm bảo là gì? Trong pseudo-code, tôi muốn kết thúc với điều này:
- cài đặt tất cả các bước
- Vòng qua mỗi hàng
- Chuyển hàng qua từng bước
- End loop
- Cleanup tất cả các bước , đảm bảo rằng việc dọn dẹp luôn xảy ra
- Trả lại (nhỏ) kết quả
Nó không được ca ngợi ctical để kết hợp tất cả các khối sử dụng vào một phương thức duy nhất vì mã trong mỗi bước này dài và được chia sẻ và tôi không muốn lặp lại mã được chia sẻ đó trong một phương thức.
Tôi biết tôi có thể thay thế thủ công khối using
bằng try
/finally
, nhưng làm điều đó theo cách thủ công cho nhiều tài nguyên có vẻ khó khăn hơn mức cần thiết.
Có giải pháp đơn giản hơn hay không, ví dụ: sử dụng using
và yield
cùng một cách thông minh? Hoặc có một triển khai lớp "đa sử dụng" có sẵn giúp quá trình thiết lập/tách rời được phối hợp dễ dàng (ví dụ: hàm tạo của nó chấp nhận danh sách các hàm trả về IDisposable và việc thực thi Dispose() của nó sẽ đảm bảo rằng mọi thứ được làm sạch)?
Có vẻ như đây là một mô hình mà ai đó thông minh hơn tôi đã tìm ra, vì vậy hãy hỏi tại đây trước khi phát minh lại bánh xe.
Tôi có một thời gian khó dịch mối quan tâm đa sử dụng của bạn vì tôi không thấy gì nhiều hơn việc sử dụng khối trong mã của bạn. Năng suất có giá trị đáng ngờ vì người gọi không cần phải di chuyển đến cuối chuỗi, đó là nơi bạn sẽ tự nhiên gọi là Vứt bỏ. – hoodaticus
Mỗi bước đường ống có yêu cầu 'foo' riêng của mình (là bản sao của dữ liệu nguồn không?) – Blorgbeard
Xác định xác định là một trong những lĩnh vực mà C++ pwns quản lý ngôn ngữ. – hoodaticus