2013-08-25 31 views
6

Tôi đang tìm kiếm tại Roslyn September 2012 CTP với Reflector, và tôi nhận thấy rằng lớp SlidingTextWindow có sau đây:Tại sao sử dụng ConcurrentQueue trong trường hợp này?

internal sealed class SlidingTextWindow : IDisposable 
{ 
    private static readonly ConcurrentQueue<char[]> arrayPool = new ConcurrentQueue<char[]>(); 
    private int basis; 
    private readonly LexerBaseCache cache; 
    private char[] characterWindow; 
    private int characterWindowCount; 
    private int characterWindowStart; 
    private int offset; 
    private readonly IText text; 
    private readonly int textEnd; 

    public SlidingTextWindow(IText text, LexerBaseCache cache) 
    { 
     this.text = text; 
     this.basis = 0; 
     this.characterWindowStart = 0; 
     this.offset = 0; 
     this.textEnd = text.Length; 
     this.cache = cache; 
     if (!arrayPool.TryDequeue(out this.characterWindow)) 
     { 
      this.characterWindow = new char[2048]; 
     } 
    } 

    public void Dispose() 
    { 
     arrayPool.Enqueue(this.characterWindow); 
     this.characterWindow = null; 
    } 

    // ... 
} 

tôi tin rằng mục đích của lớp này là để cung cấp cho chuỗi con của chuỗi nhập truy cập nhanh, bằng cách sử dụng char[] characterWindow, bắt đầu với 2048 ký tự cùng một lúc (mặc dù characterWindow có thể phát triển). Tôi tin rằng điều này là bởi vì nó là nhanh hơn để có chất nền của mảng ký tự hơn của chuỗi, như Eric Lippert seems to indicate on his blog.

Lớp SlidingTextWindow được khởi tạo mỗi khi lớp Lexer được khởi tạo, điều này xảy ra mỗi cuộc gọi đến SyntaxTree.ParseText.

Tôi không hiểu mục đích của trường arrayPool. Cách sử dụng duy nhất của nó trong lớp này là trong phương thức khởi tạo và Vứt bỏ. Khi gọi SyntaxTree.ParseText, có vẻ như chỉ có một phiên bản của lớp Lexer và của lớp SlidingTextWindow được tạo. Lợi thế nào đạt được bằng cách enqueuing các characterWindow khi một trường hợp được xử lý và bằng cách cố gắng dequeue một characterWindow khi một thể hiện được tạo ra?

Có lẽ ai đó từ nhóm Roslyn có thể giúp tôi hiểu điều này?

Trả lời

16

Lợi thế là áp lực thu thập bị giảm, có tác động tích cực đến hiệu suất tổng thể.

Trình thu thập rác .NET dĩ nhiên là một bộ thu gom rác có mục đích chung. Các mô hình phân bổ và đối tượng suốt đời của trình biên dịch và IDE khá khác so với các ứng dụng dòng kinh doanh trung bình của bạn và chúng có xu hướng làm căng thẳng GC theo những cách khác thường.

Nếu bạn nhìn khắp Roslyn, có rất nhiều nơi mà các mảng nhỏ được lưu trữ và sử dụng lại muộn hơn là cho phép GC xác định chúng là thùng rác ngắn và lấy lại chúng ngay lập tức. Các thí nghiệm thực nghiệm cho thấy rằng điều này mang lại một cải tiến có thể đo lường về hiệu suất.

Tôi không khuyên bạn nên làm như vậy trong ứng dụng của riêng bạn trừ khi hồ sơ của bạn cho biết rằng bạn có vấn đề về hiệu suất có thể đo lường được về áp lực thu thập. Đối với phần lớn các ứng dụng, GC được điều chỉnh rất tốt, và lợi ích của chiến lược tổng hợp không đáng giá.

+0

Bộ nhớ đệm của các mảng nhỏ có được thực hiện cho mục đích chính là giảm bộ nhớ hoặc tăng tốc độ (hoặc cả hai)? Có phải là trường hợp với rất nhiều mảng cần thiết cho một trình biên dịch/IDE, tạo ra một mảng mới mỗi lần sẽ mất rất nhiều bộ nhớ? Hoặc sẽ có một sự gia tăng tốc độ bằng cách sử dụng một hàng đợi an toàn thread và có nhiều chủ đề hành động trên các mảng? – cubetwo1729

+11

Chủ yếu là tốc độ và khả năng phản hồi. GC là thú vị khi nói đến hiệu suất - nó làm cho phân bổ bộ nhớ gần như miễn phí, nhưng bạn phải trả chi phí sau khi GC phải chạy. Và trong một số trường hợp, GC có tác động đáng chú ý khi nhập nếu nó xảy ra để chạy khi bạn nhập một ký tự trong trình chỉnh sửa trong khi viết mã và không thể thực hiện GC đồng thời hoàn toàn. Tôi muốn làm nổi bật những gì Eric đã đề cập - chúng tôi chỉ làm điều này khi chúng tôi thấy phân bổ cụ thể xuất hiện trên tiểu sử. Chúng tôi không làm những việc như thế này cho đến khi chúng tôi biết đó là một vấn đề cụ thể ở một địa điểm cụ thể. –

+0

@JasonMalinowski Bất kỳ lý do cụ thể nào để chọn 'ConcurrentQueue' thay vì' ConcurrentBag'? – CodesInChaos

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