2011-12-09 35 views
7

tôi có phương pháp dll mà nên là "QoSed" - phương pháp này nên được gọi là tối đa 100 lần mỗi giây .:Cách tốt nhất để đếm bao nhiêu lần mỗi giây phương pháp này được gọi là

private static extern int ExecTrans(int connectionId); 

Phương pháp này chỉ được sử dụng ở một nơi trong chương trình vì vậy nó ok để qos nơi này. Tôi cần "bộ đếm qos" riêng biệt cho mỗi connectionId. Vì vậy, ExecTrans(1)ExecTrans(2) nên đi đến các quầy khác nhau.

Ở lần lặp đầu tiên, tôi muốn đếm tần suất phương thức được gọi (đối với mỗi connectionId). I E. Tôi muốn có "số liệu thống kê trực tiếp". Có hai cách tiếp cận:

- allow to exceed limitiation for a short period. for example allow "100 transaction from 0 to 1 second, 100 transaction from 1 to 2 seconds and 200 transactions from 0.5 to 1.5 second". 
- at any second interval transactions should not exceed 100. 

Hiện tại tôi không quan tâm đến phương pháp nào trong số này nhưng tôi sẽ chọn phương pháp nào tạo ít chi phí hơn. Tôi muốn qos để thêm càng ít "làm việc" càng tốt vì nó là phần mềm giao dịch nhạy cảm với mỗi 0,1 ms.

Đối với phương pháp tiếp cận đầu tiên tôi nghĩ rằng tôi có thể sử dụng một cái gì đó như thế (pseude mã, có lẽ statscurStats nên được thread-safe):

private int[] stats  // statistic to display to user 
private int[] curStats; // statistic currently collection 

OnOneSecondElapsed(object source, ElapsedEventArgs args) { 
    foreach (conId : connIds) { 
     stats[conId] = curStats[conId]; 
     curStats[conId] = 0; 
    } 
} 

myMethod { 
    ...... 
    ExecTrans(conId); 
    ++curStats[conId]; 
    ...... 
} 

Đối với cách tiếp cận thứ hai .... là nó có thể tạo ra một bộ sưu tập nơi các đối tượng sống chính xác trong một giây và sau một giây biến mất? Sau đó, mỗi lần tôi sẽ thêm đối tượng tiếp theo vào một bộ sưu tập trừ khi bộ sưu tập chứa 100 đối tượng.

Bạn nghĩ gì? Tôi không phải là familar với các tập tin thư viện C# vì vậy có lẽ tôi đang thiếu một số classess hữu ích, có lẽ bạn có thể đề xuất một cách tiếp cận khác.

Trả lời

5

Một cách tiếp cận thứ nhất:

  • Sử dụng một ConcurrentQueue<DateTime>
  • Trước khi mọi yêu cầu, kiểm tra kích thước của hàng đợi. Nếu> 100, hủy bỏ yêu cầu
  • Nếu < 100, enqueue các DateTime hiện hành và thực hiện các yêu cầu
  • Trong một sợi nền, mỗi 0,1 giây, loại bỏ các mục lớn hơn 1 giây

Nó sẽ được khá hiệu quả, nhưng:

  • Kể từ khi không có khóa giữa thời gian bạn kiểm tra số lượng hàng đợi và thời gian bạn enqueue, đôi khi bạn có thể nhận được hơi hơn 100 yêu cầu mỗi giây
  • Sinc e chuỗi nền thực thi sau mỗi 0,1 giây, nếu bạn nhận được 100 yêu cầu cùng một lúc, nó có thể chặn hàng đợi trong tối đa 1,1 giây. Điều chỉnh thời gian ngủ khi cần thiết.

Tôi có thể sai nhưng tôi không nghĩ có giải pháp hoàn hảo. Về cơ bản, hệ thống càng chính xác thì chi phí càng cao.Bạn phải điều chỉnh các thông số tùy thuộc vào nhu cầu của bạn.

+0

Tôi đoán có một số nhầm lẫn về việc phải làm gì khi đạt đến giới hạn. Thả các mục công việc mới? Thả các mục công việc cũ (Nếu chúng không xảy ra nội tuyến)? Giới thiệu tạm dừng? –

+0

giới thiệu tạm dừng – javapowered

+0

Sau đó, có thể thêm spinlock khi số đếm cao hơn 100 để kiểm tra lại. –

3

Có một công cụ gọi là profiler thực hiện chính xác những gì bạn đang tìm kiếm. Bạn chạy nó với mã của bạn và nó sẽ cho bạn biết chính xác bao nhiêu thời gian nó được sử dụng trong mỗi phương thức và bao nhiêu lần mỗi phương thức được gọi. Đây là một số old thread về C# profilers. Nếu bạn là một nhà phát triển chuyên nghiệp, bạn có thể đã có giấy phép công ty cho một hồ sơ.

+2

Tôi cần QOS trong tương lai! Tôi cần phải giới thiệu sự chậm trễ nếu một số phương pháp gọi là ofthen sau đó giá trị nhất định. Và tôi không muốn sử dụng profilier vì nó quá chậm. Profilier là tốt cho gỡ lỗi nhưng tôi cần phải có tính năng này trong sản xuất. – javapowered

1

Bạn sẽ được gọi nhiều hơn n lần mỗi giây trong một số trường hợp, tôi giả sử bạn không muốn thực hiện bất kỳ xử lý thực tế nào trong các trường hợp thêm.

Bạn có thể sử dụng đối tượng Q được đồng bộ hóa để giữ các giao dịch được xử lý cho từng kết nối. Gọi phương pháp của bạn sẽ chỉ làm lu mờ dữ liệu nói rằng những gì nên được thực hiện. Trong một chuỗi xử lý riêng biệt, (chỉ một cho hệ thống hoặc mỗi kết nối), bạn có thể khử các hoạt động và xử lý chúng với tốc độ 1 trên 0,01 giây. Chỉ cần cắt bớt kích cỡ Q xuống 100 (pop xuống 100) trước khi enqueing mỗi đơn vị công việc cho một kết nối nhất định và thì đấy, bạn loại bỏ thêm các mục công việc.

Lưu ý: Bạn sẽ cần một hàm thời gian chính xác để thực thi 1 giao dịch trong mỗi 0,01 giây. ví dụ:

Stopwatch watch = new Stopwatch(); 
int nextPause = watch.Elapsed.Milliseconds + 10; 
while (true) 
{ 
    //do work (dequeue one item and process it) 

    int now = watch.Elapsed.Milliseconds; 
    if(now < nextPause) { 
     Thread.Sleep(nextPause - now); 
    } 
    nextPause = watch.Elapsed.Milliseconds + 10; 
} 

Lưu ý: Nếu một giao dịch mất nhiều thời gian hơn 10 mili giây (1/100th của một giây), bạn có thể thả hạng mục công trình phụ ...

Nếu bạn muốn các sợi nhân được nhiều hơn "bursty" bạn có thể xử lý nhiều mục công việc trong một vòng lặp và sử dụng thời gian chờ lâu hơn, điều này sẽ yêu cầu một phần chờ đợi với một phần "mục còn lại" đếm. (Ngoài ra, tốt hơn là nên sử dụng Monitor.Pulse và Montior.Wait thay vì ngủ ...)

0

Trong trường hợp ai đó cần đo hơn là điều chỉnh ... đây là cách tiếp cận ngây thơ mang đến cho bạn ước tính sơ bộ :

class A{ 
    private int _calls; 
    private Stopwatch _sw; 

    public A(){ 
     _calls = 0; 
     _sw = new StopWatch(); 
     _sw.Start(); 
    } 

    public void MethodToMeasure(){ 
     //Do stuff 
     _calls++; 
     if(sw.ElapsedMilliseconds > 1000){ 
      _sw.Stop(); 
      //Save or print _calls here before it's zeroed 
      _calls = 0; 
      _sw.Restart(); 
     } 
    } 
} 
Các vấn đề liên quan