QElapsedTimer 計時器

QElapsedTimer提供了一種快捷的計算流逝時間的方法。它通常被用來計算兩個事件或操作之間過去了多久。並且,該類的方法非常類似於我們之前講過的QTime類的三個計時函數,所以,我們可以很快速的在使用這兩個類的代碼之間進行移植。但是,不像QTime,QElapsedTimer會盡可能的使用某種單調時鐘。這也就意味着,沒辦法將QElapsedTimer對象轉換成人類可讀的時間格式。

這個類的典型使用方法就是測量一個耗時操作花了多少時間。最簡單的例子如下:

      QElapsedTimer timer;
      timer.start();

      slowOperation1();

      qDebug() << "The slow operation took" << timer.elapsed() << "milliseconds";
在這個例子中,我們下定義了一個QElapsedTimer的對象,然後調用它的start() 方法開始計時,完成一個耗時操作後,再調用它的elapsed() 方法,得到耗時操作所花費的具體時間,以毫秒計算。

我們也可以在一個耗時操作完成後,通過elapsed() 函數的返回值來決定下一個耗時操作可以運行的時間。這對於需要在一定的時間週期內完成幾個耗時操作來說是至關重要的。比如下面代碼所展現的案例:

  void executeSlowOperations(int timeout)
  {
      QElapsedTimer timer;
      timer.start();
      slowOperation1();

      int remainingTime = timeout - timer.elapsed();
      if (remainingTime > 0)
          slowOperation2(remainingTime);
  }

另一個QElapsedTimer的使用案例是,一個具體的操作需要運行一定的時間長度。對於這種需求,QElapsedTimer提供了hasExpired() 函數,這個函數可以判斷自從上次調用start() 或restart() 之後,是否過去了多少毫秒。如下代碼所示:

  void executeOperationsForTime(int ms)
  {
      QElapsedTimer timer;
      timer.start();

      while (!timer.hasExpired(ms))
          slowOperation1();
  }

上面我們說,QElapsedTimer會使用運行平臺所支持的某種單調參考時鐘。這具有額外的好處,它可以使QElapsedTimer不受系統時間調整的影響,也不受系統時區設置的影響。當然,相對的,這也意味着我們只能把QElapsedTimer的值和那些使用了同樣參考時鐘的值相比較。特別是,當我們把QElapsedTimer的自從參考點以來的值序列化到某個變量中後,更應該注意這點。並且,不應該把這些值通過網絡進行交換或存儲到磁盤,因爲無法保證接收端的計算機和產生該值的計算機是否使用同一種參考時鐘和參考點,也無法保證其自從參考點以來是否發生過重啓。但是,我們可以將這些值在運行在同一太機器上的不同進程間進行交換,條件是他們都使用相同的參考時鐘。QElapsedTimer在同一臺機器上總是使用相同的參考時鐘,所以,在一個進程中比較來自另一個進程的QElapsedTimer值是安全的。

注意,QElapsedTimer所使用的時鐘類型,有一些是有範圍限制的,通常是32-bit,當達到上限時會發生溢出。QElapsedTimer會處理這種情況並提供一致時間。但是,當從QElapsedTimer中提取時間時,同一機器上的兩個不同的進程會對實際逝去的時間有不同的理解。


下面,我們就來具體看下QElapsedTimer所使用的集中時鐘類型:

SystemTime

該類型的時鐘是唯一一種表示實時時間的時鐘,它表示子1970.1.1零點以來的毫秒數。它就相當於C或POSIX中的time() 函數,外加毫秒值。這種時鐘類型目前只用於不支持 單調時鐘的Unix系統。它也是QElapsedTimer可能使用的唯一一種非單調時鐘。

MonotonicClock

表示系統的單調時鐘,表示的是自過去任意時間點以來的毫秒數。這種時鐘類型用於支持POSIX時鐘類型的Unix系統(_POSIX_MONOTONIC_CLOCK)。並且,這種時鐘類型不會發生溢出。

TickCounter

這種時鐘類型的計時基於系統的或處理器的tick數,然後再乘以一個tick的週期。這種時鐘類型用於Windows系統。並且,當高精度的性能計數器可用時,會自動使用PerformanceCounter替代這種時鐘類型。TickCounter是唯一一種可能發生溢出的時鐘類型。但在Windows Vista 和 Windows server 2008上,由於它們支持擴展的64-bit  tick  counter,可以避免溢出。

在Windows平臺,時鐘會在2^32毫秒,即大約49.7天后溢出。這也意味着兩個不同的進程通過乘以2^32毫秒來計算逝去的時間,得到的結果可能是不同的。當進行這類數值得比較時,我們建議將毫秒的高32位屏蔽掉。

MachAbsoluteTime

這種時鐘類型是基於Mach kernels 表示的絕對時間,例如 OS X。把這種時鐘類型和MonotonicClock區分開是因爲OS X 和 IOS也是Unix系統,也可能支持一種和Mach絕對 時間具有不同值的POSIX單調時鐘。這種時鐘是單調的並且不會發生溢出。

PerformanceCounter

這種時鐘類型使用Windows的QueryPerformanceCounter() 和 QueryPerformanceFrequency() 函數訪問系統的高精度性能計數器。但因爲這種計數器並不是在所有平臺上都可用,所以,QElapsedTimer會在該時鐘類型不可用時,自動使用TickCounter作爲替代。這種時鐘類型也是單調的並且不會發生溢出。

搞明白每一種可用的時鐘類型和單調性後,我們可以在程序中使用clockType() 函數來獲得一個QElapsedTimer對象所使用的底層時鐘類型;使用isMonotonic() 函數判斷一個QElapsedTimer對象的單調性。


最後,至於該類的使用方式,上面的例子也說的差不多了,最常用的就是start()、restart()、elapsed()這些函數。其他的函數,大家在需要時可以參考Qt幫助文檔。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章