2011-12-09 54 views
7

我有一個應該是「QoSed」 DLL方法 - 這種方法應該被稱爲最大每秒100次:最好的方式來算多少次每秒的方法被稱爲

private static extern int ExecTrans(int connectionId); 

,才使用此方法在程序中的一個地方,所以這個地方可以。 我需要爲每個connectionId單獨使用「qos counter」。所以ExecTrans(1)ExecTrans(2)應該去不同的計數器。

在第一次迭代中,我想要計算方法調用的頻率(每個connectionId)。即我想要「現場統計」。有兩種方法:

- 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. 

現在我不在乎使用哪個這些方法,但我會選擇一個產生更少的「開銷」。我希望qos儘可能減少「額外工作」,因爲它每隔0.1 ms就對交易軟件敏感。

對於第一種方法,我認爲我可以使用類似的東西(pseude碼,可能statscurStats應線程安全):

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]; 
    ...... 
} 

至於第二種方法....是它可能做一個集合,其中對象的生活只有一秒鐘和一秒鐘後消失?然後每次我將下一個對象添加到集合,除非集合包含100個對象。

您認爲如何?我不熟悉C#庫文件,所以可能我錯過了一些有用的分類,可能你可以建議另一種方法。

回答

5

第一種方法:

  • 使用ConcurrentQueue<DateTime>
  • 每個請求之前,檢查隊列的大小。如果> 100,取消該請求
  • 如果< 100,入隊的當前日期時間和執行請求
  • 在後臺線程中,每0.1秒,刪除條目比舊1秒

它應該是相當高效,但是:

  • 由於有時間之間沒有鎖定您檢查隊列計數和你排隊的時候,你可能有時會每秒
  • 辛格略高於100個請求e後臺線程每0.1秒執行一次,如果您同時收到100個請求,它可能會阻塞隊列達1.1秒。根據需要調整睡眠時間。

我可能是錯的,但我不認爲有一個完美的解決方案。基本上,系統越精確,有更多的開銷。您必須根據您的需要調整參數。

+0

我猜想在達到極限時應該怎麼做會有些困惑。放下新的工作物品?丟棄舊作品(如果它們不是內聯的)?介紹一個暫停? – 2011-12-09 17:50:41

+0

介紹一個暫停 – javapowered

+0

然後也許增加一個螺旋鎖計數高於100重新檢查。 –

3

有一個工具稱爲分析器,它完全符合您的要求。你用你的代碼運行它,它會告訴你在每個方法中花了多少時間以及每個方法被調用了多少次。這裏是關於C#分析器的old thread。如果您是一名專業開發人員,您可能已經擁有公司的一個分析師許可證。

+2

我需要在未來的QOS!如果某種方法稱之爲「更高」,那麼我需要引入延遲。我不想使用profilier,因爲它太慢了。 Profilier適合調試,但我需要在生產中使用此功能。 – javapowered

1

在某些情況下,你會每秒調用n次以上,我假設你不想在額外的情況下做任何實際的處理。

您可以使用同步的Q對象來保存每個連接要處理的事務。調用你的方法只會排列數據說明應該做什麼。在一個單獨的處理線程中(無論是系統還是每個連接),然後可以將操作出列並以每0.1秒1個的速率處理它們。在爲給定連接排隊每個工作單元之前,將Q大小截斷爲100(彈出到100),然後放棄額外的工作項目。

注意:您需要一個精確的計時功能來每強制執行1次交易.01秒。 如:

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; 
} 

注:如果一個事務需要更長的時間超過10毫秒(1/100秒),你可能會下降一些額外的工作項目......

如果你想在工作線程是更多的「突發」,你可以在一個循環中處理多個工作項目,並使用更長的等待時間,這需要部分等待「部件剩餘」計數。 (另外,最好使用Monitor.Pulse和Montior.Wait來代替睡眠...)

0

如果有人需要測量而不是調節...這是一種天真的方法,可以給你一個粗略的估計:

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(); 
     } 
    } 
}