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

📄 benchmarkdialog.cpp

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

bool CBenchmarkDialog::OnButtonClicked(int buttonID, HWND buttonHWND) 
{ 
  switch(buttonID)
  {
    case IDC_BUTTON_RESTART:
      OnRestartButton();
      return true;
    case IDC_BUTTON_STOP:
      OnStopButton();
      return true;
    case IDC_BENCHMARK_MULTITHREADING:
      OnChangeSettings();
      return true;
  }
  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
}

class CBenchmarkInStream: 
  public ISequentialInStream,
  public CMyUnknownImp
{
  const Byte *Data;
  UInt32 Pos;
  UInt32 Size;
public:
  MY_UNKNOWN_IMP
  void Init(const Byte *data, UInt32 size)
  {
    Data = data;
    Size = size;
    Pos = 0;
  }
  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
  STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
};

STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
  UInt32 remain = Size - Pos;
  if (size > remain)
    size = remain;
  for (UInt32 i = 0; i < size; i++)
  {
    ((Byte *)data)[i] = Data[Pos + i];
  }
  Pos += size;
  if(processedSize != NULL)
    *processedSize = size;
  return S_OK;
}
  
STDMETHODIMP CBenchmarkInStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
{
  return Read(data, size, processedSize);
}

class CBenchmarkOutStream: 
  public ISequentialOutStream,
  public CMyUnknownImp
{
  UInt32 BufferSize;
public:
  UInt32 Pos;
  Byte *Buffer;
  CBenchmarkOutStream(): Buffer(0) {} 
  ~CBenchmarkOutStream() { delete []Buffer; }
  void Init(UInt32 bufferSize) 
  {
    delete []Buffer;
    Buffer = 0;
    Buffer = new Byte[bufferSize];
    Pos = 0;
    BufferSize = bufferSize;
  }
  MY_UNKNOWN_IMP
  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
  STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
};

STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
  UInt32 i;
  for (i = 0; i < size && Pos < BufferSize; i++)
    Buffer[Pos++] = ((const Byte *)data)[i];
  if(processedSize != NULL)
    *processedSize = i;
  if (i != size)
  {
    MessageBoxW(0, L"Buffer is full", L"7-zip error", 0);
    return E_FAIL;
  }
  return S_OK;
}
  
STDMETHODIMP CBenchmarkOutStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
{
  return Write(data, size, processedSize);
}

class CCompareOutStream: 
  public ISequentialOutStream,
  public CMyUnknownImp
{
public:
  CCRC CRC;
  MY_UNKNOWN_IMP
  void Init() { CRC.Init(); }
  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
  STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
};

STDMETHODIMP CCompareOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
  CRC.Update(data, size);
  if(processedSize != NULL)
    *processedSize = size;
  return S_OK;
}
  
STDMETHODIMP CCompareOutStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
{
  return Write(data, size, processedSize);
}

typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID, 
    const GUID *interfaceID, void **outObject);

struct CDecoderProgressInfo:
  public ICompressProgressInfo,
  public CMyUnknownImp
{
  CProgressSyncInfo *SyncInfo;
  MY_UNKNOWN_IMP
  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};

STDMETHODIMP CDecoderProgressInfo::SetRatioInfo(
    const UInt64 *inSize, const UInt64 *outSize)
{
  NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
  if (SyncInfo->Changed)
    return E_ABORT;
  return S_OK;
}

struct CThreadBenchmark:
  public ICompressProgressInfo,
  public CMyUnknownImp
{
  CProgressSyncInfo *SyncInfo;
  UInt64 _startTime;
  UInt64 _approvedStart;
  NDLL::CLibrary Library;
  CMyComPtr<ICompressCoder> Encoder;
  CMyComPtr<ICompressCoder> Decoder;
  DWORD Process();
  static DWORD WINAPI MyThreadFunction(void *param)
  {
    return ((CThreadBenchmark *)param)->Process();
  }
  MY_UNKNOWN_IMP
  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};

DWORD CThreadBenchmark::Process()
{
  try
  {
  SyncInfo->WaitCreating();
  CBenchRandomGenerator randomGenerator;
  randomGenerator.Init();
  CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
  Encoder.QueryInterface(IID_ICompressWriteCoderProperties, 
      &writeCoderProperties);
  CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;
  Decoder.QueryInterface(
        IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties);
  CSequentialOutStreamImp *propStreamSpec = 0;
  CMyComPtr<ISequentialOutStream> propStream;
  if (writeCoderProperties != NULL)
  {
    propStreamSpec = new CSequentialOutStreamImp;
    propStream = propStreamSpec;
  }

  CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
  Encoder.QueryInterface(IID_ICompressSetCoderProperties, 
      &setCoderProperties);

  CDecoderProgressInfo *decoderProgressInfoSpec = new 
      CDecoderProgressInfo;
  CMyComPtr<ICompressProgressInfo> decoderProgress = decoderProgressInfoSpec;
  decoderProgressInfoSpec->SyncInfo = SyncInfo;
    
  while(true)
  {
    if (SyncInfo->WasStopped())
      return 0;
    if (SyncInfo->WasPaused())
    {
      Sleep(200);
      continue;
    }
    UInt32 dictionarySize;
    bool multiThread;
    {
      NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
      dictionarySize = SyncInfo->DictionarySize;
      multiThread = SyncInfo->MultiThread;
      if (SyncInfo->Changed)
        SyncInfo->Init();
    }

    const UInt32 kBufferSize = dictionarySize + kAdditionalSize;
    const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;

    if (setCoderProperties)
    {
      PROPID propIDs[] = 
      {
        NCoderPropID::kDictionarySize,
        NCoderPropID::kMultiThread
      };
      const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
      NWindows::NCOM::CPropVariant properties[kNumProps];
      properties[0] = UInt32(dictionarySize);
      properties[1] = bool(multiThread);
      RINOK(setCoderProperties->SetCoderProperties(propIDs,
          properties, kNumProps));
    }
      
    if (propStream)
    {
      propStreamSpec->Init();
      writeCoderProperties->WriteCoderProperties(propStream);
    }

    randomGenerator.Set(kBufferSize);
    randomGenerator.Generate();
    CCRC crc;

    // randomGenerator.BufferSize
    crc.Update(randomGenerator.Buffer, randomGenerator.BufferSize);

    {
      NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
      if (SyncInfo->Changed)
        continue;
    }
    
    CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
    inStreamSpec->Init(randomGenerator.Buffer, randomGenerator.BufferSize);
    CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
    CBenchmarkOutStream *outStreamSpec = new CBenchmarkOutStream;
    outStreamSpec->Init(kCompressedBufferSize);
    CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
    _approvedStart = dictionarySize;
    _startTime = ::GetTimeCount();
    HRESULT result = Encoder->Code(inStream, outStream, 0, 0, this);
    UInt64 tickCount = ::GetTimeCount() - _startTime;
    UInt32 compressedSize = outStreamSpec->Pos;
    {
      NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
      if (result == S_OK)
      {
        if (SyncInfo->ApprovedInfo.InSize != 0)
        {
          SyncInfo->CompressingInfoTemp.InSize = kBufferSize - SyncInfo->ApprovedInfo.InSize;
          SyncInfo->CompressingInfoTemp.OutSize = compressedSize - SyncInfo->ApprovedInfo.OutSize;
          SyncInfo->CompressingInfoTemp.Time = tickCount - SyncInfo->ApprovedInfo.Time;
          if (SyncInfo->CompressingInfo.Time == 0)
            SyncInfo->CompressingInfo = SyncInfo->CompressingInfoTemp;
        }
      }
      SyncInfo->ApprovedInfo.Init();
    }
    if(result != S_OK)
    {
      if (result != E_ABORT)
      {
        SyncInfo->Pause();
        MessageBox(0, NError::MyFormatMessage(result), TEXT("7-Zip"), MB_ICONERROR);
      }
      continue;
    }
    {
      NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
      SyncInfo->NumPasses++;
    }
    
    ///////////////////////
    // Decompressing


    CCompareOutStream *outCompareStreamSpec = new CCompareOutStream;
    CMyComPtr<ISequentialOutStream> outCompareStream = outCompareStreamSpec;

    for (int i = 0; i < 2; i++)
    {
      inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);
      outCompareStreamSpec->Init();

      if (compressSetDecoderProperties)
      {
        RINOK(compressSetDecoderProperties->SetDecoderProperties2(
          propStreamSpec->GetBuffer(), propStreamSpec->GetSize()));
      }
      
      UInt64 outSize = kBufferSize;
      UInt64 startTime = ::GetTimeCount();
      result = Decoder->Code(inStream, outCompareStream, 0, &outSize, decoderProgress);
      tickCount = ::GetTimeCount() - startTime;
      {
        NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
        if (result == S_OK)
        {
          SyncInfo->DecompressingInfoTemp.InSize = compressedSize;
          SyncInfo->DecompressingInfoTemp.OutSize = kBufferSize;
          SyncInfo->DecompressingInfoTemp.Time = tickCount;
          if (SyncInfo->DecompressingInfo.Time == 0 && i >= 1)
            SyncInfo->DecompressingInfo = SyncInfo->DecompressingInfoTemp;
          if (outCompareStreamSpec->CRC.GetDigest() != crc.GetDigest())
          {
            SyncInfo->NumErrors++;
            break;
          }
        }
        else
        {
          if(result != E_ABORT)
          {
            SyncInfo->NumErrors++;
            break;
          }
        }
      }
    }
  }
  }
  catch(CSystemException &e)
  {
    MessageBox(0, NError::MyFormatMessage(e.ErrorCode), TEXT("7-Zip"), MB_ICONERROR);
    return E_FAIL;
  }
  catch(...)
  {
    MyMessageBoxError(0, L"Some error");
    return E_FAIL;
  }
}

STDMETHODIMP CThreadBenchmark::SetRatioInfo(
    const UInt64 *inSize, const UInt64 *outSize)
{
  NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
  if (SyncInfo->Changed || SyncInfo->WasPaused() || SyncInfo->WasStopped())
    return E_ABORT;
  CProgressInfo ci;
  ci.InSize = *inSize;
  ci.OutSize = *outSize;
  ci.Time = ::GetTimeCount() - _startTime;
  SyncInfo->ProcessedSize = *inSize;

  UInt64 deltaTime = ci.Time - SyncInfo->CompressingInfoPrev.Time;
  if (deltaTime >= GetFreq())
  {
    SyncInfo->CompressingInfoTemp.Time = deltaTime;
    SyncInfo->CompressingInfoTemp.InSize = ci.InSize - SyncInfo->CompressingInfoPrev.InSize;
    SyncInfo->CompressingInfoTemp.OutSize = ci.InSize - SyncInfo->CompressingInfoPrev.OutSize;
    SyncInfo->CompressingInfoPrev = ci;
  }
  if (*inSize >= _approvedStart && SyncInfo->ApprovedInfo.InSize == 0)
    SyncInfo->ApprovedInfo = ci;
  return S_OK;
}

static bool GetCoderPath(UString &path)
{
  if (!GetProgramFolderPath(path))
    return false;
  path += L"Codecs\\LZMA.dll";
  return true;
}
  
typedef UInt32 (WINAPI *GetMethodPropertyFunc)(
    UInt32 index, PROPID propID, PROPVARIANT *value);

static bool LoadCoder(
  const UString &filePath, 
  NWindows::NDLL::CLibrary &library,
  CLSID &encoder, CLSID &decoder)
{
  if (!library.Load(filePath))
    return false;
  GetMethodPropertyFunc getMethodProperty = (GetMethodPropertyFunc)
        library.GetProcAddress("GetMethodProperty");
  if (getMethodProperty == NULL)
    return false;

  NWindows::NCOM::CPropVariant propVariant;
  if (getMethodProperty (0, NMethodPropID::kEncoder, &propVariant) != S_OK)
    return false;
  if (propVariant.vt != VT_BSTR)
    return false;
  encoder = *(const GUID *)propVariant.bstrVal;
  propVariant.Clear();
      
  if (getMethodProperty (0, NMethodPropID::kDecoder, &propVariant) != S_OK)
    return false;
  if (propVariant.vt != VT_BSTR)
    return false;
  decoder = *(const GUID *)propVariant.bstrVal;
  propVariant.Clear();
  return true;
}

void Benchmark(HWND hwnd)
{
  UString path;
  if (!GetCoderPath(path))
  {
    MyMessageBoxError(hwnd, L"Can't find LZMA.dll");
    return;
  }
  CLSID encoder;
  CLSID decoder;
  CThreadBenchmark benchmarker;
  if (!LoadCoder(path, benchmarker.Library, encoder, decoder))
  {
    MyMessageBoxError(hwnd, L"Can't load LZMA.dll");
    return;
  }

  CreateObjectPointer createObject = (CreateObjectPointer)
      benchmarker.Library.GetProcAddress("CreateObject");
  if (createObject == NULL)
  {
    MyMessageBoxError(hwnd, L"Incorrect LZMA.dll");
    return;
  }
  if (createObject(&encoder, &IID_ICompressCoder, (void **)&benchmarker.Encoder) != S_OK)
  {
    MyMessageBoxError(hwnd, L"Can't create codec");
    return;
  }
  if (createObject(&decoder, &IID_ICompressCoder, (void **)&benchmarker.Decoder) != S_OK)
  {
    MyMessageBoxError(hwnd, L"Can't create codec");
    return;
  }

  CBenchmarkDialog benchmarkDialog;
  benchmarker.SyncInfo = &benchmarkDialog._syncInfo;
  CThread thread;
  if (!thread.Create(CThreadBenchmark::MyThreadFunction, &benchmarker))
  {
    MyMessageBoxError(hwnd, L"error");
    return;
  }
  benchmarkDialog.Create(hwnd);
  WaitForSingleObject(thread, INFINITE);
}

⌨️ 快捷键说明

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