function GetCPUSpeed(var CpuSpeed: TFreqInfo): Boolean;
var
  T0, T1: TULargeInteger;
  CountFreq: TULargeInteger;
  Freq, Freq2, Freq3, Total: Integer;
  TotalCycles, Cycles: Int64;
  Stamp0, Stamp1: Int64;
  TotalTicks, Ticks: Cardinal;
  Tries, Priority: Integer;
  Thread: THandle;
begin
  Stamp0 := 0;
  Stamp1 := 0;
  Freq  := 0;
  Freq2 := 0;
  Freq3 := 0;
  Tries := 0;
  TotalCycles := 0;
  TotalTicks := 0;
  Total := 0;

  Thread := GetCurrentThread();
  Result := QueryPerformanceFrequency(Int64(CountFreq));
  if Result then
  begin
    while ((Tries < 3 ) or ((Tries < 20) and ((Abs(3 * Freq - Total) > 3) or
      (Abs(3 * Freq2 - Total) > 3) or (Abs(3 * Freq3 - Total) > 3)))) do
    begin
      Inc(Tries);
      Freq3 := Freq2;
      Freq2 := Freq;
      QueryPerformanceCounter(Int64(T0));
      T1.LowPart := T0.LowPart;
      T1.HighPart := T0.HighPart;

      Priority := GetThreadPriority(Thread);
      if Priority <> THREAD_PRIORITY_ERROR_RETURN then
        SetThreadPriority(Thread, THREAD_PRIORITY_TIME_CRITICAL);
      try
        while (T1.LowPart - T0.LowPart) < 50 do
        begin
          QueryPerformanceCounter(Int64(T1));
          Stamp0 := ReadTimeStampCounter;
        end;
        T0.LowPart := T1.LowPart;
        T0.HighPart := T1.HighPart;

        while (T1.LowPart - T0.LowPart) < 1000 do
        begin
          QueryPerformanceCounter(Int64(T1));
          Stamp1 := ReadTimeStampCounter;
        end;
      finally
        if Priority <> THREAD_PRIORITY_ERROR_RETURN then
          SetThreadPriority(Thread, Priority);
      end;

      Cycles := Stamp1 - Stamp0;
      Ticks := T1.LowPart - T0.LowPart;
      Ticks := Ticks * 100000;

      if ((CountFreq.LowPart / 10) <> 0) then                            // No division by 0
        Ticks := Round(Ticks / (CountFreq.LowPart / 10));

      TotalTicks := TotalTicks + Ticks;
      TotalCycles := TotalCycles + Cycles;
      if Ticks = 0 then                                                 // No division by 0
        Ticks := 1;
      Freq := Round(Cycles / Ticks);
      Total := Freq + Freq2 + Freq3;
    end;
    if TotalTicks = 0 then                                              // No division by 0
      TotalTicks := 1;
    Freq3 := Round((TotalCycles * 10) / TotalTicks);

    Freq2 := Round((TotalCycles * 100) / TotalTicks);

    if Freq2 - (Freq3 * 10) >= 6 then
      Inc(Freq3);

    CpuSpeed.RawFreq := Round(TotalCycles / TotalTicks);
    CpuSpeed.NormFreq := CpuSpeed.RawFreq;

    Freq := CpuSpeed.RawFreq * 10;
    if (Freq3 - Freq) >= 6 then
      Inc(CpuSpeed.NormFreq);

    CpuSpeed.ExTicks := TotalTicks;
    CpuSpeed.InCycles := TotalCycles;

    CpuSpeed.NormFreq := RoundFrequency(CpuSpeed.NormFreq);
    Result := True;
  end;
end;