2010-06-29 10 views

risposta

7

di Windows non vuole sprecare energia elettrica aggiornando l'orologio di sistema 1000 volte al secondo, in modo che il valore predefinito è quello di aggiornare solo 60-100 volte al secondo. Se imposti il ​​timer multimediale su 1ms, puoi ottenere una risoluzione di 1ms dall'orologio, ma non è consigliabile.

Per ulteriori informazioni sul risparmio di energia elettrica, ciò che accade quando la CPU è inattiva per un periodo di tempo è che può passare a uno stato di alimentazione molto bassa. Ogni volta che viene interrotto (ad esempio per incrementare i tic-tac dell'orologio), deve lasciare il suo stato di potenza molto bassa e usare molta energia elettrica per alimentare l'intera CPU al servizio dell'interruzione. In altre parole, la potenza aggiuntiva non sta aumentando i tic-tac dell'orologio, è nel mantenere la CPU sveglia per farlo.

Dal momento che il mio laptop utilizza 10 W in modalità inattiva quando la frequenza di clock è 60Hz e 11W quando è 1000Hz, e ottengo 300 minuti di durata della batteria, quell'orologio più lento mi dà quasi 30 minuti in più di durata della batteria!

+0

Stai parlando degli interrupt del kernel? http://lwn.net/Articles/145973/ – Nitrodist

+0

Nitrodist: Sì, questa è una spiegazione dello stesso problema. – Gabe

+0

Sta parlando di kernel tick, un tick del kernel è un 'timer timer' hardware (CPU) programmato. Windows è ben lungi dall'essere bravo nell'efficienza dell'elettricità (50% meno efficiente di Android e 20% in meno di Mac OS), ma non c'è motivo di peggiorarlo. I tick del kernel vengono utilizzati per richiamare i callback di timer scaduti (o coalescati), aggiornare di nuovo la pianificazione di thread/processi e incrementare il conteggio dei tick OS globale. –

6

Prova System.Diagnostics.Stopwatch per tempi ad alta risoluzione.

Se l'hardware installato e sistema operativo supportano un contatore delle prestazioni -alta risoluzione, allora la classe cronometro usi che contatore per misurare il tempo trascorso. In caso contrario, la classe Cronometro utilizza il timer di sistema per misurare il tempo trascorso .

Provate il nativo DateTime.Ticks per la precisione il tempo di sistema fino a un centinaio di nanosecondi; 1 millisecondo = 10000 zecche.

while (true) 
{ 
    System.Threading.Thread.Sleep(1); 

    Console.WriteLine("{0} {1}", 
     System.DateTime.Now.Ticks, 
     System.DateTime.Now.ToString("ss:fff")); 
} 

PS > .\test.exe 
    634134152924322129 52:432 
    634134152924332129 52:433 
    634134152924342130 52:434 
    634134152924352130 52:435 
    634134152924362131 52:436 
    634134152924372131 52:437 
    634134152924382132 52:438 
    634134152924392133 52:439 
    634134152924402133 52:440 
    634134152924412134 52:441 
    634134152924422134 52:442 
    634134152924432135 52:443 
+3

ha chiesto per l'ora del sistema. Il cronometro dà solo un tempo trascorso. – Gabe

+3

La chiamata di 'DateTime.Ticks' non è più accurata di' DateTime.Millisecond'. Internamente, 'DateTime.Millisecond' chiama' DateTime.Ticks' –

+0

Right.Stavo solo sottolineando che, secondo MSDN e questo test approssimativo, è accurato almeno il millisecondo risoluzione richiesto dall'interrogante; da qui l'affiancamento Console.Output di DateTime come una stringa a fianco di Ticks. – xcud

8

Si potrebbe utilizzare this DateTimePrecise class per ottenere un tempo di grande precisione in .NET

UPDATE
Il collegamento CodeProject non funziona più. Ho estratto il codice from archive.org e lo ho incorporato qui per riferimento futuro. Questo codice è incluso qui "così com'è", esattamente come è stato incluso nella pagina CodeProject.

DateTimePrecise è facile da usare come DateTime.Now, tranne che DateTimePrecise.Now è un metodo invece di un metodo statico esempio, quindi bisogna istanziare prima una DateTimePrecise.

using System.Diagnostics; 

/// DateTimePrecise provides a way to get a DateTime that exhibits the 
/// relative precision of 
/// System.Diagnostics.Stopwatch, and the absolute accuracy of DateTime.Now. 
public class DateTimePrecise 
{ 
    /// Creates a new instance of DateTimePrecise. 
    /// A large value of synchronizePeriodSeconds may cause arithmetic overthrow 
    /// exceptions to be thrown. A small value may cause the time to be unstable. 
    /// A good value is 10. 
    /// synchronizePeriodSeconds = The number of seconds after which the 
    /// DateTimePrecise will synchronize itself with the system clock. 
    public DateTimePrecise(long synchronizePeriodSeconds) 
    { 
     Stopwatch = Stopwatch.StartNew(); 
     this.Stopwatch.Start(); 

     DateTime t = DateTime.UtcNow; 
     _immutable = new DateTimePreciseSafeImmutable(t, t, Stopwatch.ElapsedTicks, 
      Stopwatch.Frequency); 

     _synchronizePeriodSeconds = synchronizePeriodSeconds; 
     _synchronizePeriodStopwatchTicks = synchronizePeriodSeconds * 
      Stopwatch.Frequency; 
     _synchronizePeriodClockTicks = synchronizePeriodSeconds * 
      _clockTickFrequency; 
    } 

    /// Returns the current date and time, just like DateTime.UtcNow. 
    public DateTime UtcNow 
    { 
     get 
     { 
      long s = this.Stopwatch.ElapsedTicks; 
      DateTimePreciseSafeImmutable immutable = _immutable; 

      if (s < immutable._s_observed + _synchronizePeriodStopwatchTicks) 
      { 
       return immutable._t_base.AddTicks(((
        s - immutable._s_observed) * _clockTickFrequency)/(
        immutable._stopWatchFrequency)); 
      } 
      else 
      { 
       DateTime t = DateTime.UtcNow; 

       DateTime t_base_new = immutable._t_base.AddTicks(((
        s - immutable._s_observed) * _clockTickFrequency)/(
        immutable._stopWatchFrequency)); 

       _immutable = new DateTimePreciseSafeImmutable(
        t, 
        t_base_new, 
        s, 
        ((s - immutable._s_observed) * _clockTickFrequency * 2) 
        /
        (t.Ticks - immutable._t_observed.Ticks + t.Ticks + 
         t.Ticks - t_base_new.Ticks - immutable._t_observed.Ticks) 
       ); 

       return t_base_new; 
      } 
     } 
    } 

    /// Returns the current date and time, just like DateTime.Now. 
    public DateTime Now 
    { 
     get 
     { 
      return this.UtcNow.ToLocalTime(); 
     } 
    } 

    /// The internal System.Diagnostics.Stopwatch used by this instance. 
    public Stopwatch Stopwatch; 

    private long _synchronizePeriodStopwatchTicks; 
    private long _synchronizePeriodSeconds; 
    private long _synchronizePeriodClockTicks; 
    private const long _clockTickFrequency = 10000000; 
    private DateTimePreciseSafeImmutable _immutable; 
} 

internal sealed class DateTimePreciseSafeImmutable 
{ 
    internal DateTimePreciseSafeImmutable(DateTime t_observed, DateTime t_base, 
     long s_observed, long stopWatchFrequency) 
    { 
     _t_observed = t_observed; 
     _t_base = t_base; 
     _s_observed = s_observed; 
     _stopWatchFrequency = stopWatchFrequency; 
    } 
    internal readonly DateTime _t_observed; 
    internal readonly DateTime _t_base; 
    internal readonly long _s_observed; 
    internal readonly long _stopWatchFrequency; 
} 
+0

Hai la classe? Il link non funziona più. Grazie –

+0

@ Răzvan Ho resuscitato il codice da archive.org e l'ho aggiunto alla mia risposta. Grazie per aver sottolineato che si trattava di un collegamento morto. –

+2

+1 per resurrection –