2015-12-14 20 views
7

Tôi có hai giao diện. ICacheHolder sẽ được thực hiện bởi một lớp thực hiện logic của một đối tượng trò chơi và IVisualizer đó sẽ là đại diện trực quan.Hai Danh sách chứa một giao diện so với một Danh sách chứa một cấu trúc có hai giao diện

public interface ICacheHolder 
{ 
    void updateCacheWithCurrentState(int chachFrame); 

    void resizeCache(int newSize); 

    T getCacheFrame<T>(int cacheIndex, float interpolationToNext) where T : struct; 
} 

public interface IVisualizer 
{ 
    void updateVisualization(ICacheHolder cacheHolder, int cacheIndex, float interpolation); 
} 

Mỗi ICacheHolder kết nối với một đối tượng IVisualizer mối quan hệ là từ 1 đến 1. Tôi đang cố gắng để xác định xem tốt hơn của nó (hiệu suất/bộ nhớ khôn ngoan) để lưu trữ chúng trong hai danh sách riêng biệt hoặc trong một Danh sách như struct . Sẽ tạo ra một sự khác biệt lớn chút nào? Sẽ có boxing xảy ra nếu tôi sử dụng phiên bản struct? Tôi Recon kích thước của danh sách sẽ là từ 100 đến 1000.

Phiên bản 1:

public class CacheFramework 
{ 
private List<ICacheHolder> cacheHolders = new List<ICacheHolder>(); 
private List<IVisualizer> visualizers = new List<IVisualizer>(); 
... 
} 

Version 2:

struct SimulationObject 
{ 
    public ICacheHolder CacheHolder; 
    public IVisualizer Visualizer; 
} 
public class CacheFramework 
{ 
private List<SimulationObject> cacheHolder = new List<SimulationObject>(); 
... 
} 

hoạt động như Add và Remove sẽ không được thực hiện rất thường xuyên. Chỉ khi bắt đầu trò chơi, có thể có thêm nhiều cuộc gọi.

Phiên bản 1:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer) 
{ 
    if (!cacheHolders.Contains(cacheHolder) && !visualizers.Contains(visualizer)) 
    { 
     cacheHolders.Add(cacheHolder); 
     visualizers.Add(visualizer); 
     return true; 
    } 
    return false; 
} 

Version 2:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer) 
{ 
    int index = simulationObjects.FindIndex(
     delegate (SimulationObject simulationObject) 
     { 
      return simulationObject.CacheHolder == cacheHolder || simulationObject.Visualizer == visualizer; 
     } 
     ); 

    if (index >= 0) 
    { 
     SimulationObject newObject; 
     newObject.CacheHolder = cacheHolder; 
     newObject.Visualizer = visualizer; 
     return true; 
    } 
    return false; 
} 

danh sách sẽ được truy cập ít nhất mỗi khung thông qua chỉ số của nó.

Thông tin bổ sung: Mỗi lớp sử dụng ICacheHolder sẽ chứa List<struct> với dữ liệu như vị trí, xoay vòng hoặc sức khỏe. Mỗi phần tử danh sách sẽ là ảnh chụp nhanh kịp thời. Mục tiêu là nó di chuyển qua thời gian qua lại.

Sửa 1:

lỗi cố định trong AddSimulationObject Version 2.

Như đã chỉ ra AddSimulationObject Phiên bản 2 có thể là:

private bool AddSimulationObject(ICacheHolder cacheHolder, IVisualizer visualizer) 
{ 
    SimulationObject newObject = new SimulationObject { CacheHolder = cacheHolder, Visualizer = visualizer }; 
    if (simulationObjects.Contains(newObject)) 
    { 
     simulationObjects.Add(newObject); 
     return true; 
    } 
    return false; 
} 

Nhưng trong trường hợp này tôi sẽ cần phải chắc chắn cacheHolder và visualizer không xuất hiện trong bất kỳ kết hợp nào khác.

Chỉnh sửa 2:

Tôi đang sử dụng Unity3D mà hỗ trợ chủ yếu là NET. 3.5

Như đã chỉ ra, tốt hơn nên sử dụng bộ sưu tập .NET có tra cứu nhanh hơn Danh sách. Hoặc nếu danh sách có thể sắp xếp, hãy sử dụng List.BinarySearch.

Sửa 3:

Tôi sẽ sử dụng phiên bản struct. Tôi không phải là máy bay phản lực chắc chắn có bao nhiêu tra cứu sẽ có mặt ở đó. Tôi có thể đổi sang bộ sưu tập .NET khác nếu nó sắp xảy ra.

+4

Bất cứ khi nào tôi thấy câu hỏi về hiệu suất, tôi liên kết câu hỏi này: http://ericlippert.com/2012/12/17/performance-rant/ – DavidG

+1

Bạn đã hiển thị cả hai phiên bản dưới dạng mã. Vậy các giá trị thời gian/bộ nhớ bạn đã đo bằng mã đó là ở đâu? Nếu bạn đã đo nó, bạn có thể nói - tùy thuộc vào tiêu chí của bạn - phiên bản nào phù hợp với yêu cầu của bạn. –

+1

Chỉ cần một FYI - bạn không cần 'FindIndex' của bạn với một đại biểu. Structs sẽ trả về 'true' khi so sánh với cùng các trường. Đó là: 'mới SimulationObject {CacheHolder = ch, Visualizer = v} .Equals (new SimulationObject {CacheHolder = ch, Visualizer = v})' sẽ trả về true. Bạn có thể chỉ đơn giản sử dụng 'var exist = simulationObjects.Contains (new SimulationObject {CacheHolder = cacheHolder, Visualizer = visualizer});' – Rob

Trả lời

1

tôi sẽ khuyên bạn nên sử dụng phương pháp cấu trúc, vì hai lý do:

  • Trong .NET, struct tham số kiểu generic được xử lý đặc biệt và no boxing will occur.
  • Cách tiếp cận đó sẽ đảm bảo theo cấu trúc bạn có các yếu tố phù hợp với nhau. Đối với tôi, có vẻ như nó dễ dàng hơn để giải thích.

Vì vậy, khi nói đến câu hỏi liệu có nên sử dụng danh sách các cấu trúc hoặc struct danh sách, tôi chắc chắn sẽ thích sử dụng danh sách các cấu trúc, ngay cả khi nó gây ra một hiệu suất thả chút. Trong trường hợp của bạn, tôi mong đợi danh sách các phiên bản cấu trúc để hoạt động tốt hơn, tuy nhiên tôi không thể đảm bảo nó. Bạn có thể chạy hồ sơ bất cứ lúc nào. Nhưng có một điều chắc chắn: sự khác biệt hiệu suất nhỏ hơn nhiều so với chi phí của tìm kiếm tuyến tính trong AddSimulationObject.

2

Nhận xét của Eric Lippert rất đúng. Trong trường hợp này không có nhu cầu thực sự để thậm chí thử và so sánh sự khác biệt hiệu suất, như các bộ sưu tập quá nhỏ, vì vậy không cần phải lo lắng về thời gian cpu.

Cấu trúc danh sách bộ nhớ ... sử dụng khối bộ nhớ tiếp giáp và chỉ trở thành vấn đề bộ nhớ khi chúng thực sự thực sự lớn. (Ý tôi là hàng triệu.)

Chỉ gợi ý khác: Nếu mỗi chu kỳ trò chơi bạn thực hiện tìm kiếm trong các danh sách đó, bạn có thể chỉ cần chọn cấu trúc khác được tối ưu hóa cho tra cứu. Từ điển hiệu quả hơn rất nhiều khi truy xuất các mục khi tìm kiếm thực hiện tra cứu từ một chỉ mục, trong khi danh sách sẽ thực hiện truyền tải các mục.

0

Bạn đang nói về danh sách tham chiếu, một trong các giải pháp của bạn sẽ hoạt động tốt. Nhưng nếu hai giao diện của bạn có nghĩa là để đi bởi cặp, bạn có thể sử dụng List<Tuple<ICacheHolder, IVisualizer>>

+0

Cảm ơn Mẹo. Chỉ cần thử nghiệm nó. Tôi đang làm việc với Unity3D Tuple là .NET Framework 4 và tiếc là không được hỗ trợ. Unity/Mono chủ yếu vẫn còn trên NET. 3.5. – Markus

+0

@Markus: Sẽ đáng để cập nhật câu hỏi của bạn để xác định rằng bạn đang sử dụng Unity3D. Cho rằng .NET 4 bây giờ đã hơn 5 tuổi, bất cứ lúc nào bạn đang đặt ra một vấn đề và * không thể * sử dụng nó, bạn nên giải thích lý do tại sao. –

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