2009-10-08 33 views
8

Trong một ứng dụng Delphi chúng tôi đang làm việc trên chúng tôi có một cấu trúc lớn của các đối tượng liên quan. Một số thuộc tính của các đối tượng này có các giá trị được tính toán trong thời gian chạy và tôi đang tìm cách lưu trữ kết quả cho các phép tính chuyên sâu hơn. Một cách tiếp cận mà tôi sử dụng là tiết kiệm giá trị trong một thành viên tư nhân lần đầu tiên nó được tính toán. Dưới đây là một ví dụ ngắn:Phương pháp tiếp cận để lưu vào bộ nhớ đệm các giá trị được tính

unit Unit1; 

interface 

type 
    TMyObject = class 
    private 
    FObject1, FObject2: TMyOtherObject; 
    FMyCalculatedValue: Integer; 
     function GetMyCalculatedValue: Integer; 
    public 
    property MyCalculatedValue: Integer read GetMyCalculatedValue; 
    end; 

implementation 

    function TMyObject.GetMyCalculatedValue: Integer; 
    begin 
    if FMyCalculatedValue = 0 then 
    begin 
     FMyCalculatedValue := 
     FObject1.OtherCalculatedValue + // This is also calculated 
     FObject2.OtherValue; 
    end; 

    Result := FMyCalculatedValue; 
    end; 

end. 

Nó không phải là hiếm khi các đối tượng được sử dụng để thay đổi tính toán và giá trị lưu trữ nên được đặt lại và tính toán lại. Cho đến nay chúng tôi đã giải quyết vấn đề này bằng cách sử dụng mẫu người quan sát: các đối tượng triển khai sự kiện OnChange để người khác có thể đăng ký, nhận thông báo khi họ thay đổi và đặt lại giá trị được lưu trong bộ nhớ cache. Cách tiếp cận này hoạt động nhưng có một số nhược điểm:

  • Phải mất rất nhiều bộ nhớ để quản lý đăng ký.
  • Nó không mở rộng tốt khi giá trị được lưu trong bộ nhớ cache phụ thuộc vào nhiều đối tượng (ví dụ: danh sách).
  • Sự phụ thuộc không phải là rất cụ thể (ngay cả khi giá trị bộ nhớ cache chỉ phụ thuộc vào một thuộc tính, nó cũng sẽ được đặt lại khi các thuộc tính khác thay đổi).
  • Quản lý đăng ký tác động đến hiệu suất tổng thể và khó duy trì (đối tượng bị xóa, di chuyển, ...).
  • Không rõ cách xử lý các tính toán tùy thuộc vào các giá trị được tính khác.

Và cuối cùng là câu hỏi: bạn có thể đề xuất các phương pháp tiếp cận khác để triển khai các giá trị được tính toán được lưu trong bộ nhớ cache không?

+0

Ngay cả khi được gắn thẻ 'delphi', tôi rất quan tâm đến việc biết liệu một mẫu cụ thể có được phát triển hay không. –

+0

Tôi đã thêm thẻ Delphi để nó giới hạn các đề xuất thành các ngôn ngữ được đánh máy tĩnh, không phải rác. – Tihauan

Trả lời

1

Trong tác phẩm của tôi, tôi sử dụng Bold cho Delphi có thể quản lý không giới hạn cấu trúc phức tạp của các giá trị được lưu trữ phụ thuộc vào nhau. Thông thường, mỗi biến chỉ chứa một phần nhỏ của vấn đề. Trong khuôn khổ này được gọi là các thuộc tính có nguồn gốc. Có nguồn gốc vì giá trị không được lưu trong cơ sở dữ liệu, Nó chỉ phụ thuộc vào các thuộc tính có nguồn gốc khác hoặc các thuộc tính liên tục trong cơ sở dữ liệu.

Mã đằng sau thuộc tính đó được viết bằng Delphi làm thủ tục hoặc trong OCL (Ngôn ngữ ràng buộc đối tượng) trong mô hình. Nếu bạn viết nó như là mã Delphi, bạn phải đăng ký các biến phụ thuộc. Vì vậy, nếu thuộc tính C phụ thuộc vào A và B thì bất cứ khi nào A hoặc B thay đổi mã cho recalc C được gọi tự động khi C được đọc. Vì vậy, lần đầu tiên C được đọc A và B cũng được đọc (có thể từ cơ sở dữ liệu). Miễn là A và B không thay đổi, bạn có thể đọc C và có hiệu năng rất nhanh. Đối với các tính toán phức tạp, điều này có thể tiết kiệm khá nhiều thời gian CPU.

Tin xấu và xấu là Bold không được hỗ trợ chính thức nữa và bạn cũng không thể mua nó. Tôi cho rằng bạn có thể nhận được nếu bạn hỏi đủ người, nhưng tôi không biết nơi bạn có thể tải xuống. Khoảng năm 2005-2006 nó đã được tải về miễn phí từ Borland nhưng không được nữa. Nó chưa sẵn sàng cho D2009 vì ai đó phải chuyển nó sang Unicode.

Tùy chọn khác là ECO với dot.net từ Capable Objects. ECO là một plugin trong Visual Studio. Nó là một framwork được hỗ trợ có ý tưởng và tác giả giống như Bold cho Delphi. Nhiều thứ cũng được cải thiện, ví dụ databinding được sử dụng cho các thành phần GUI. Cả Bold và ECO đều sử dụng một mô hình làm điểm trung tâm với các lớp, thuộc tính và liên kết. Chúng có thể được lưu giữ trong một cơ sở dữ liệu hoặc một tệp xml. Với phiên bản miễn phí của ECO, mô hình có thể có tối đa 12 lớp, nhưng như tôi nhớ không có giới hạn nào khác.

Bold và ECO chứa nhiều hơn thuộc tính có nguồn gốc khiến bạn hiệu quả hơn và cho phép bạn suy nghĩ về vấn đề thay vì chi tiết kỹ thuật của cơ sở dữ liệu hoặc trong trường hợp của bạn. Bạn được chào đón với nhiều câu hỏi hơn về những khuôn khổ đó!

Edit: Có thực sự là một tải link for Embarcadero registred users cho Bold cho Delphi cho D7, khá cũ ... Tôi biết đã có bản cập nhật cho D2005, D2006 quảng cáo.

+0

Các khung điều khiển mô hình nói chung và "Bold cho Delphi" trong âm thanh đặc biệt rất thú vị. Cảm ơn bạn! – Tihauan

+0

Tôi thực sự tìm thấy Bold cho D2006 (Tôi nghĩ rằng đó là phiên bản công khai mới nhất) trên một trong những harddrives của tôi vì vậy nếu bạn quan tâm chỉ mail cho tôi trên [email protected] vì vậy tôi có thể gửi nó. Hoặc bằng Skype, id của tôi là d98rolb. –

+0

Tihauan, để biết thêm thông tin và ví dụ nhỏ về cách các giá trị xuất phát hoạt động trong Bold, hãy xem blog của tôi tại http://boldfordelphi.blogspot.com/#derattr. –

4

Nếu bạn muốn tránh Mẫu quan sát, bạn có thể thử sử dụng phương pháp băm.

Ý tưởng sẽ là bạn 'băm' đối số và kiểm tra xem điều này có khớp với 'băm' mà trạng thái được lưu hay không. Nếu nó không, sau đó bạn recompute (và do đó lưu hash mới như là chìa khóa).

Tôi biết tôi làm cho nó nghe như tôi chỉ nghĩ về nó, nhưng trên thực tế nó được sử dụng bởi các phần mềm nổi tiếng.

Ví dụ: SCons (thay thế Makefile) để kiểm tra xem mục tiêu có cần được xây dựng lại tốt nhất là phương pháp dấu thời gian hay không.

Chúng tôi đã sử dụng SCons hơn một năm nay và chúng tôi chưa bao giờ phát hiện bất kỳ vấn đề nào về mục tiêu không được xây dựng lại, vì vậy hàm băm của chúng hoạt động tốt!

+0

Chỉ cần đảm bảo rằng tính toán băm (hoặc bất kỳ phương pháp nào bạn chọn) là (đáng kể) nhanh hơn so với tính toán lại. –

+0

Có, tôi đã không chỉ ra nó như nó nghe rõ ràng, nhưng như mọi khi với tối ưu hóa ... bạn thực sự phải đo lường. –

2

Bạn có thể lưu trữ các bản sao cục bộ của các giá trị đối tượng bên ngoài được yêu cầu. Thói quen truy cập sau đó so sánh bản sao cục bộ với giá trị bên ngoài và chỉ tính toán lại trên một thay đổi.

Truy cập các thuộc tính đối tượng bên ngoài cũng sẽ buộc phải đánh giá lại các thuộc tính đó, do đó hệ thống sẽ tự động cập nhật, nhưng chỉ tính lại khi cần. Tôi không biết bạn có cần thực hiện các bước để tránh phụ thuộc vòng tròn hay không.

Điều này làm tăng lượng không gian bạn cần cho mỗi đối tượng, nhưng loại bỏ mẫu quan sát viên. Nó cũng xóa tất cả các tính toán cho đến khi chúng cần thiết, thay vì thực hiện phép tính mỗi khi một tham số nguồn thay đổi. Tôi hy vọng điều này có liên quan đến hệ thống của bạn.

unit Unit1; 

interface 

type 
    TMyObject = class 
    private 
    FObject1, FObject2: TMyOtherObject; 
    FObject1Val, FObject2Val: Integer; 
    FMyCalculatedValue: Integer; 
     function GetMyCalculatedValue: Integer; 
    public 
    property MyCalculatedValue: Integer read GetMyCalculatedValue; 
    end; 

implementation 

    function TMyObject.GetMyCalculatedValue: Integer; 
    begin 
    if (FObject1.OtherCalculatedValue <> FObjectVal1) 
    or (FObject2.OtherValue <> FObjectVal2) then 
    begin 
     FMyCalculatedValue := 
     FObject1.OtherCalculatedValue + // This is also calculated 
     FObject2.OtherValue; 
     FObjectVal1 := FObject1.OtherCalculatedValue; 
     FObjectVal2 := Object2.OtherValue; 
    end; 

    Result := FMyCalculatedValue; 
    end; 

end. 
+0

Tôi cũng sẽ xác minh rằng fObject1 và fObject2 được chỉ định trước khi thực hiện phép tính ... chỉ để an toàn. – skamradt

+0

@skamradt: đã đồng ý. Tôi giả định rằng câu hỏi đã bỏ qua xác thực đầu vào/phát hiện lỗi để giữ mã ví dụ đơn giản. – IanH

Các vấn đề liên quan