⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 benchmarkdialog.cpp

📁 免费压缩软件7zip的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// BenchmarkDialog.cpp

#include "StdAfx.h"

#include "Common/IntToString.h"
#include "Common/StringToInt.h"
#include "Common/Exception.h"
#include "Windows/Thread.h"
#include "Windows/PropVariant.h"
#include "Windows/Error.h"
#include "Windows/DLL.h"
#include "Windows/FileFind.h"
#include "../../ProgramLocation.h"
#include "../../HelpUtils.h"
#include "../../../Common/StreamObjects.h"
#include "resource.h"
#include "BenchmarkDialog.h"
#include "Common/CRC.h"

using namespace NWindows;

static LPCWSTR kHelpTopic = L"fm/benchmark.htm";

static const UINT_PTR kTimerID = 4;
static const UINT kTimerElapse = 1000;

static const UInt32 kAdditionalSize = (6 << 20);
static const UInt32 kCompressedAdditionalSize = (1 << 10);
static const int kSubBits = 8;

#ifdef LANG        
#include "../../LangUtils.h"
#endif

using namespace NWindows;

#ifdef LANG        
static CIDLangPair kIDLangPairs[] = 
{
  { IDC_BENCHMARK_DICTIONARY, 0x02000D0C },
  { IDC_BENCHMARK_MEMORY, 0x03080001 },
  { IDC_BENCHMARK_MULTITHREADING, 0x02000D09 },
  { IDC_BENCHMARK_SPEED_LABEL, 0x03080004 },
  { IDC_BENCHMARK_RATING_LABEL, 0x03080005 },
  { IDC_BENCHMARK_COMPRESSING, 0x03080002 },
  { IDC_BENCHMARK_DECOMPRESSING, 0x03080003 },
  { IDC_BENCHMARK_CURRENT, 0x03080007 },
  { IDC_BENCHMARK_RESULTING, 0x03080008 },
  { IDC_BENCHMARK_CURRENT2, 0x03080007 },
  { IDC_BENCHMARK_RESULTING2, 0x03080008 },
  { IDC_BENCHMARK_TOTAL_RATING, 0x03080006 },
  { IDC_BENCHMARK_ELAPSED, 0x02000C01 },
  { IDC_BENCHMARK_SIZE, 0x02000C03 },
  { IDC_BENCHMARK_PASSES, 0x03080009 },
  { IDC_BENCHMARK_ERRORS, 0x0308000A },
  { IDC_BUTTON_STOP, 0x02000714 },
  { IDC_BUTTON_RESTART, 0x02000715 },
  { IDHELP, 0x02000720 },
  { IDCANCEL, 0x02000710 }
};
#endif

static void MyMessageBoxError(HWND hwnd, LPCWSTR message)
{
  MessageBoxW(hwnd, message, L"7-Zip", MB_ICONERROR);
}

UInt64 GetTimeCount()
{
  return GetTickCount();
  /*
  LARGE_INTEGER value;
  if (::QueryPerformanceCounter(&value))
    return value.QuadPart;
  return GetTickCount();
  */
}

UInt64 GetFreq()
{
  return 1000;
  /*
  LARGE_INTEGER value;
  if (::QueryPerformanceFrequency(&value))
    return value.QuadPart;
  return 1000;
  */
}

class CRandomGenerator
{
  UInt32 A1;
  UInt32 A2;
public:
  CRandomGenerator() { Init(); }
  void Init() { A1 = 362436069; A2 = 521288629;}
  UInt32 GetRnd() 
  {
    return 
      ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^
      ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) );
  }
};

class CBitRandomGenerator
{
  CRandomGenerator RG;
  UInt32 Value;
  int NumBits;
public:
  void Init()
  {
    Value = 0;
    NumBits = 0;
  }
  UInt32 GetRnd(int numBits) 
  {
    if (NumBits > numBits)
    {
      UInt32 result = Value & ((1 << numBits) - 1);
      Value >>= numBits;
      NumBits -= numBits;
      return result;
    }
    numBits -= NumBits;
    UInt32 result = (Value << numBits);
    Value = RG.GetRnd();
    result |= Value & ((1 << numBits) - 1);
    Value >>= numBits;
    NumBits = 32 - numBits;
    return result;
  }
};

class CBenchRandomGenerator
{
  CBitRandomGenerator RG;
  UInt32 Pos;
public:
  UInt32 BufferSize;
  Byte *Buffer;
  CBenchRandomGenerator(): Buffer(0) {} 
  ~CBenchRandomGenerator() { delete []Buffer; }
  void Init() { RG.Init(); }
  void Set(UInt32 bufferSize) 
  {
    delete []Buffer;
    Buffer = 0;
    Buffer = new Byte[bufferSize];
    Pos = 0;
    BufferSize = bufferSize;
  }
  UInt32 GetRndBit() { return RG.GetRnd(1); }
  /*
  UInt32 GetLogRand(int maxLen)
  {
    UInt32 len = GetRnd() % (maxLen + 1);
    return GetRnd() & ((1 << len) - 1);
  }
  */
  UInt32 GetLogRandBits(int numBits)
  {
    UInt32 len = RG.GetRnd(numBits);
    return RG.GetRnd(len);
  }
  UInt32 GetOffset()
  {
    if (GetRndBit() == 0)
      return GetLogRandBits(4);
    return (GetLogRandBits(4) << 10) | RG.GetRnd(10);
  }
  UInt32 GetLen()
  {
    if (GetRndBit() == 0)
      return RG.GetRnd(2);
    if (GetRndBit() == 0)
      return 4 + RG.GetRnd(3);
    return 12 + RG.GetRnd(4);
  }
  void Generate()
  {
    while(Pos < BufferSize)
    {
      if (GetRndBit() == 0 || Pos < 1)
        Buffer[Pos++] = Byte(RG.GetRnd(8));
      else
      {
        UInt32 offset = GetOffset();
        while (offset >= Pos)
          offset >>= 1;
        offset += 1;
        UInt32 len = 2 + GetLen();
        for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++)
          Buffer[Pos] = Buffer[Pos - offset];
      }
    }
  }
};

const LPCTSTR kProcessingString = TEXT("...");
const LPCTSTR kMB = TEXT(" MB");
const LPCTSTR kMIPS =  TEXT(" MIPS");
const LPCTSTR kKBs = TEXT(" KB/s");

bool CBenchmarkDialog::OnInit() 
{
  #ifdef LANG        
  LangSetWindowText(HWND(*this), 0x03080000);
  LangSetDlgItemsText(HWND(*this), kIDLangPairs, sizeof(kIDLangPairs) / sizeof(kIDLangPairs[0]));
  #endif

  m_Dictionary.Attach(GetItem(IDC_BENCHMARK_COMBO_DICTIONARY));
  for (int i = kNumBenchDictionaryBitsStart; i < 28; i++)
    for (int j = 0; j < 2; j++)
    {
      UInt32 dictionary = (1 << i) + (j << (i - 1));
      TCHAR s[40];
      ConvertUInt64ToString((dictionary >> 20), s);
      lstrcat(s, kMB);
      int index = m_Dictionary.AddString(s);
      m_Dictionary.SetItemData(index, dictionary);
    }
  m_Dictionary.SetCurSel(0);
  OnChangeSettings();

  _syncInfo.Init();
  _syncInfo.InitSettings();
 
  _syncInfo._startEvent.Set();
  _timer = SetTimer(kTimerID, kTimerElapse);
	return CModalDialog::OnInit();
}

static UInt64 GetLZMAUsage(UInt32 dictionary)
  { return ((UInt64)dictionary * 19 / 2) + (8 << 20); }

static UInt64 GetMemoryUsage(UInt32 dictionary)
{
  const UInt32 kBufferSize = dictionary + kAdditionalSize;
  const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
  return kBufferSize + kCompressedBufferSize +
    GetLZMAUsage(dictionary) + dictionary + (1 << 20);
}

UInt32 CBenchmarkDialog::OnChangeDictionary()
{
  UInt64 dictionary = m_Dictionary.GetItemData(m_Dictionary.GetCurSel());
  UInt64 memUsage = GetMemoryUsage(dictionary);
  memUsage = (memUsage + (1 << 20) - 1) >> 20;
  TCHAR s[40];
  ConvertUInt64ToString(memUsage, s);
  lstrcat(s, kMB);
  SetItemText(IDC_BENCHMARK_MEMORY_VALUE, s);
  return dictionary;
}

void CBenchmarkDialog::OnChangeSettings()
{
  EnableItem(IDC_BUTTON_STOP, true);
  UInt32 dictionary = OnChangeDictionary();
  SetItemText(IDC_BENCHMARK_COMPRESSING_SPEED, kProcessingString);
  SetItemText(IDC_BENCHMARK_COMPRESSING_SPEED2, kProcessingString);
  SetItemText(IDC_BENCHMARK_COMPRESSING_RATING, kProcessingString);
  SetItemText(IDC_BENCHMARK_COMPRESSING_RATING2, kProcessingString);
  SetItemText(IDC_BENCHMARK_DECOMPRESSING_SPEED, kProcessingString);
  SetItemText(IDC_BENCHMARK_DECOMPRESSING_SPEED2, kProcessingString);
  SetItemText(IDC_BENCHMARK_DECOMPRESSING_RATING, kProcessingString);
  SetItemText(IDC_BENCHMARK_DECOMPRESSING_RATING2, kProcessingString);
  SetItemText(IDC_BENCHMARK_TOTAL_RATING_VALUE, kProcessingString);
  _startTime = GetTickCount();
  PrintTime();
  NWindows::NSynchronization::CCriticalSectionLock lock(_syncInfo.CS);
  _syncInfo.Init();
  _syncInfo.DictionarySize = dictionary;
  _syncInfo.Changed = true;
  _syncInfo.MultiThread = IsButtonCheckedBool(IDC_BENCHMARK_MULTITHREADING);
}

void CBenchmarkDialog::OnRestartButton()
{
  OnChangeSettings();
}

void CBenchmarkDialog::OnStopButton()
{
  EnableItem(IDC_BUTTON_STOP, false);
  _syncInfo.Pause();
}

void CBenchmarkDialog::OnHelp() 
{
  ShowHelpWindow(NULL, kHelpTopic);
}

void CBenchmarkDialog::OnCancel() 
{
  _syncInfo.Stop();
  KillTimer(_timer);
  CModalDialog::OnCancel();
}

static void GetTimeString(UInt64 timeValue, TCHAR *s)
{
  wsprintf(s, TEXT("%02d:%02d:%02d"), 
      UInt32(timeValue / 3600),
      UInt32((timeValue / 60) % 60), 
      UInt32(timeValue % 60));
}

void CBenchmarkDialog::PrintTime()
{
  UInt32 curTime = ::GetTickCount();
  UInt32 elapsedTime = (curTime - _startTime);
  UInt32 elapsedSec = elapsedTime / 1000;
  TCHAR s[40];
  GetTimeString(elapsedSec, s);
  SetItemText(IDC_BENCHMARK_ELAPSED_VALUE, s);
}

static UInt32 GetLogSize(UInt32 size)
{
  for (int i = kSubBits; i < 32; i++)
    for (UInt32 j = 0; j < (1 << kSubBits); j++)
      if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))
        return (i << kSubBits) + j;
  return (32 << kSubBits);
}

static UInt64 GetCompressRating(UInt32 dictionarySize, 
    UInt64 elapsedTime, UInt64 size)
{
  if (elapsedTime == 0)
    elapsedTime = 1;
  UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits);
  UInt64 numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits));
  UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
  return numCommands * GetFreq() / elapsedTime;
}

static UInt64 GetDecompressRating(UInt64 elapsedTime, 
    UInt64 outSize, UInt64 inSize)
{
  if (elapsedTime == 0)
    elapsedTime = 1;
  UInt64 numCommands = inSize * 250 + outSize * 21;
  return numCommands * GetFreq() / elapsedTime;
}

static UInt64 GetTotalRating(
    UInt32 dictionarySize, 
    UInt64 elapsedTimeEn, UInt64 sizeEn,
    UInt64 elapsedTimeDe, 
    UInt64 inSizeDe, UInt64 outSizeDe)
{
  return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + 
    GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2;
}

void CBenchmarkDialog::PrintRating(UInt64 rating, UINT controlID)
{
  TCHAR s[40];
  ConvertUInt64ToString(rating / 1000000, s);
  lstrcat(s, kMIPS);
  SetItemText(controlID, s);
}

void CBenchmarkDialog::PrintResults(
    UInt32 dictionarySize,
    UInt64 elapsedTime, 
    UInt64 size, UINT speedID, UINT ratingID,
    bool decompressMode, UInt64 secondSize)
{
  TCHAR s[40];
  UInt64 speed = size * GetFreq() / elapsedTime;
  ConvertUInt64ToString(speed / 1024, s);
  lstrcat(s, kKBs);
  SetItemText(speedID, s);
  UInt64 rating;
  if (decompressMode)
    rating = GetDecompressRating(elapsedTime, size, secondSize);
  else
    rating = GetCompressRating(dictionarySize, elapsedTime, size);
  PrintRating(rating, ratingID);
}

bool CBenchmarkDialog::OnTimer(WPARAM timerID, LPARAM callback)
{
  PrintTime();
  NWindows::NSynchronization::CCriticalSectionLock lock(_syncInfo.CS);

  TCHAR s[40];
  ConvertUInt64ToString((_syncInfo.ProcessedSize >> 20), s);
  lstrcat(s, kMB);
  SetItemText(IDC_BENCHMARK_SIZE_VALUE, s);

  ConvertUInt64ToString(_syncInfo.NumPasses, s);
  SetItemText(IDC_BENCHMARK_PASSES_VALUE, s);

  ConvertUInt64ToString(_syncInfo.NumErrors, s);
  SetItemText(IDC_BENCHMARK_ERRORS_VALUE, s);

  UInt64 elapsedTime = _syncInfo.CompressingInfoTemp.Time;
  if (elapsedTime >= 1)
  {
    UInt32 dicSizeTemp = (UInt32)MyMax(_syncInfo.ProcessedSize, UInt64(1) << 20);
    dicSizeTemp = MyMin(dicSizeTemp, _syncInfo.DictionarySize), 
    PrintResults(dicSizeTemp, elapsedTime, 
      _syncInfo.CompressingInfoTemp.InSize, 
      IDC_BENCHMARK_COMPRESSING_SPEED,
      IDC_BENCHMARK_COMPRESSING_RATING);
  }

  if (_syncInfo.CompressingInfo.Time >= 1)
  {
    PrintResults(
      _syncInfo.DictionarySize, 
      _syncInfo.CompressingInfo.Time, 
      _syncInfo.CompressingInfo.InSize, 
      IDC_BENCHMARK_COMPRESSING_SPEED2,
      IDC_BENCHMARK_COMPRESSING_RATING2);
  }

  if (_syncInfo.DecompressingInfoTemp.Time >= 1)
  {
    PrintResults(
      _syncInfo.DictionarySize, 
      _syncInfo.DecompressingInfoTemp.Time, 
      _syncInfo.DecompressingInfoTemp.OutSize, 
      IDC_BENCHMARK_DECOMPRESSING_SPEED,
      IDC_BENCHMARK_DECOMPRESSING_RATING,
      true,
      _syncInfo.DecompressingInfoTemp.InSize);
  }
  if (_syncInfo.DecompressingInfo.Time >= 1)
  {
    PrintResults(
      _syncInfo.DictionarySize, 
      _syncInfo.DecompressingInfo.Time, 
      _syncInfo.DecompressingInfo.OutSize, 
      IDC_BENCHMARK_DECOMPRESSING_SPEED2,
      IDC_BENCHMARK_DECOMPRESSING_RATING2,
      true,
      _syncInfo.DecompressingInfo.InSize);
    if (_syncInfo.CompressingInfo.Time >= 1)
    {
      PrintRating(GetTotalRating(
        _syncInfo.DictionarySize, 
        _syncInfo.CompressingInfo.Time, 
        _syncInfo.CompressingInfo.InSize, 
        _syncInfo.DecompressingInfo.Time,
        _syncInfo.DecompressingInfo.OutSize, 
        _syncInfo.DecompressingInfo.InSize), 
        IDC_BENCHMARK_TOTAL_RATING_VALUE);
    }
  }
  return true;
}

bool CBenchmarkDialog::OnCommand(int code, int itemID, LPARAM lParam)
{
  if (code == CBN_SELCHANGE && itemID == IDC_BENCHMARK_COMBO_DICTIONARY)
  {
    OnChangeSettings();
    return true;
  }
  return CModalDialog::OnCommand(code, itemID, lParam);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -