1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// Bench.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Bench.h"
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifndef _WIN32
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define USE_POSIX_TIME
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define USE_POSIX_TIME2
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef USE_POSIX_TIME
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <time.h>
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef USE_POSIX_TIME2
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <sys/time.h>
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef _WIN32
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define USE_ALLOCA
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef USE_ALLOCA
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef _WIN32
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <malloc.h>
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#else
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <stdlib.h>
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../../../C/7zCrc.h"
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../../../C/Alloc.h"
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifndef _7ZIP_ST
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../../Windows/Synchronization.h"
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../../Windows/Thread.h"
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../../Windows/PropVariant.h"
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
41baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt32 kUncompressMinBlockSize =
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef UNDER_CE
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync1 << 24;
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#else
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync1 << 26;
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
48baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt32 kCrcBlockSize =
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef UNDER_CE
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync1 << 25;
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#else
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync1 << 30;
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
55baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt32 kAdditionalSize = (1 << 16);
56baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt32 kCompressedAdditionalSize = (1 << 10);
57baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt32 kMaxLzmaPropSize = 5;
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
59baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass CBaseRandomGenerator
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 A1;
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 A2;
63baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic:
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBaseRandomGenerator() { Init(); }
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  void Init() { A1 = 362436069; A2 = 521288629;}
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 GetRnd()
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) +
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) );
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
74baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass CBenchBuffer
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
76baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic:
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t BufferSize;
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Byte *Buffer;
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchBuffer(): Buffer(0) {}
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  virtual ~CBenchBuffer() { Free(); }
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  void Free()
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ::MidFree(Buffer);
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Buffer = 0;
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool Alloc(size_t bufferSize)
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (Buffer != 0 && BufferSize == bufferSize)
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return true;
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Free();
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Buffer = (Byte *)::MidAlloc(bufferSize);
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    BufferSize = bufferSize;
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return (Buffer != 0);
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
97baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass CBenchRandomGenerator: public CBenchBuffer
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBaseRandomGenerator *RG;
100baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic:
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  void Set(CBaseRandomGenerator *rg) { RG = rg; }
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 GetVal(UInt32 &res, int numBits)
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 val = res & (((UInt32)1 << numBits) - 1);
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    res >>= numBits;
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return val;
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 GetLen(UInt32 &res)
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 len = GetVal(res, 2);
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return GetVal(res, 1 + len);
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  void Generate()
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 pos = 0;
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 rep0 = 1;
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    while (pos < BufferSize)
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UInt32 res = RG->GetRnd();
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      res >>= 1;
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (GetVal(res, 1) == 0 || pos < 1024)
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        Buffer[pos++] = (Byte)(res & 0xFF);
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      else
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        UInt32 len;
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        len = 1 + GetLen(res);
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (GetVal(res, 3) != 0)
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          len += GetLen(res);
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          do
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          {
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            UInt32 ppp = GetVal(res, 5) + 6;
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            res = RG->GetRnd();
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            if (ppp > 30)
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync              continue;
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            rep0 = /* (1 << ppp) +*/  GetVal(res, ppp);
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            res = RG->GetRnd();
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          }
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          while (rep0 >= pos);
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          rep0++;
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++)
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          Buffer[pos] = Buffer[pos - rep0];
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
151baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass CBenchmarkInStream:
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public ISequentialInStream,
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public CMyUnknownImp
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const Byte *Data;
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t Pos;
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t Size;
158baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic:
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  MY_UNKNOWN_IMP
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  void Init(const Byte *data, size_t size)
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Data = data;
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Size = size;
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Pos = 0;
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
169baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t remain = Size - Pos;
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 kMaxBlockSize = (1 << 20);
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (size > kMaxBlockSize)
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size = kMaxBlockSize;
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (size > remain)
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size = (UInt32)remain;
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (UInt32 i = 0; i < size; i++)
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ((Byte *)data)[i] = Data[Pos + i];
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Pos += size;
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if(processedSize != NULL)
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = size;
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
185baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass CBenchmarkOutStream:
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public ISequentialOutStream,
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public CBenchBuffer,
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public CMyUnknownImp
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // bool _overflow;
191baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic:
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 Pos;
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // CBenchmarkOutStream(): _overflow(false) {}
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  void Init()
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    // _overflow = false;
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Pos = 0;
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  MY_UNKNOWN_IMP
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
203baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t curSize = BufferSize - Pos;
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (curSize > size)
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    curSize = size;
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  memcpy(Buffer + Pos, data, curSize);
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Pos += (UInt32)curSize;
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if(processedSize != NULL)
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = (UInt32)curSize;
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (curSize != size)
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    // _overflow = true;
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
220baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass CCrcOutStream:
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public ISequentialOutStream,
222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public CMyUnknownImp
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
224baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic:
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 Crc;
226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  MY_UNKNOWN_IMP
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  void Init() { Crc = CRC_INIT_VAL; }
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
231baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Crc = CrcUpdate(Crc, data, size);
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (processedSize != NULL)
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = size;
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
239baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic UInt64 GetTimeCount()
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_POSIX_TIME
242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_POSIX_TIME2
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  timeval v;
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (gettimeofday(&v, 0) == 0)
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec;
246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (UInt64)time(NULL) * 1000000;
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return time(NULL);
249baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  /*
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LARGE_INTEGER value;
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (::QueryPerformanceCounter(&value))
254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return value.QuadPart;
255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  */
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return GetTickCount();
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
260baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic UInt64 GetFreq()
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_POSIX_TIME
263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_POSIX_TIME2
264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return 1000000;
265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return 1;
267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
269baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  /*
270baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  LARGE_INTEGER value;
271baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (::QueryPerformanceFrequency(&value))
272baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return value.QuadPart;
273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  */
274baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return 1000;
275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
276baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
277baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
278baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifndef USE_POSIX_TIME
279baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }
280baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
282baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic UInt64 GetUserTime()
283baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_POSIX_TIME
285baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return clock();
286baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  FILETIME creationTime, exitTime, kernelTime, userTime;
288baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (
289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef UNDER_CE
290baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ::GetThreadTimes(::GetCurrentThread()
291baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ::GetProcessTimes(::GetCurrentProcess()
293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    , &creationTime, &exitTime, &kernelTime, &userTime) != 0)
295baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return GetTime64(userTime) + GetTime64(kernelTime);
296baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (UInt64)GetTickCount() * 10000;
297baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
298baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
299baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
300baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic UInt64 GetUserFreq()
301baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
302baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_POSIX_TIME
303baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return CLOCKS_PER_SEC;
304baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
305baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return 10000000;
306baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
307baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
308baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
309baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass CBenchProgressStatus
310baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
311baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifndef _7ZIP_ST
312baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NWindows::NSynchronization::CCriticalSection CS;
313baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
314baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic:
315baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT Res;
316baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool EncodeMode;
317baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  void SetResult(HRESULT res)
318baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
319baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _7ZIP_ST
320baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NWindows::NSynchronization::CCriticalSectionLock lock(CS);
321baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
322baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Res = res;
323baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
324baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT GetResult()
325baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
326baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _7ZIP_ST
327baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NWindows::NSynchronization::CCriticalSectionLock lock(CS);
328baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
329baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return Res;
330baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
331baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
332baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
333baa3858d3f5d128a5c8466b700098109edcad5f2repo syncclass CBenchProgressInfo:
334baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public ICompressProgressInfo,
335baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  public CMyUnknownImp
336baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
337baa3858d3f5d128a5c8466b700098109edcad5f2repo syncpublic:
338baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchProgressStatus *Status;
339baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchInfo BenchInfo;
340baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT Res;
341baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  IBenchCallback *callback;
342baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchProgressInfo(): callback(0) {}
343baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  MY_UNKNOWN_IMP
344baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
345baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
346baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
347baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void SetStartTime(CBenchInfo &bi)
348baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
349baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bi.GlobalFreq = GetFreq();
350baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bi.UserFreq = GetUserFreq();
351baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bi.GlobalTime = ::GetTimeCount();
352baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bi.UserTime = ::GetUserTime();
353baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
354baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
355baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest)
356baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
357baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  dest.GlobalFreq = GetFreq();
358baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  dest.UserFreq = GetUserFreq();
359baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime;
360baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  dest.UserTime = ::GetUserTime() - biStart.UserTime;
361baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
362baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
363baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
364baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
365baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT res = Status->GetResult();
366baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res != S_OK)
367baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return res;
368baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!callback)
369baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return res;
370baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchInfo info = BenchInfo;
371baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  SetFinishTime(BenchInfo, info);
372baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (Status->EncodeMode)
373baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
374baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    info.UnpackSize = *inSize;
375baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    info.PackSize = *outSize;
376baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    res = callback->SetEncodeResult(info, false);
377baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
378baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
379baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
380baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    info.PackSize = BenchInfo.PackSize + *inSize;
381baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    info.UnpackSize = BenchInfo.UnpackSize + *outSize;
382baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    res = callback->SetDecodeResult(info, false);
383baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
384baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res != S_OK)
385baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Status->SetResult(res);
386baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return res;
387baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
388baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
389baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const int kSubBits = 8;
390baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
391baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic UInt32 GetLogSize(UInt32 size)
392baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
393baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = kSubBits; i < 32; i++)
394baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (UInt32 j = 0; j < (1 << kSubBits); j++)
395baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))
396baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return (i << kSubBits) + j;
397baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (32 << kSubBits);
398baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
399baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
400baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void NormalizeVals(UInt64 &v1, UInt64 &v2)
401baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
402baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  while (v1 > 1000000)
403baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
404baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    v1 >>= 1;
405baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    v2 >>= 1;
406baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
407baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
408baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
409baa3858d3f5d128a5c8466b700098109edcad5f2repo syncUInt64 GetUsage(const CBenchInfo &info)
410baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
411baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 userTime = info.UserTime;
412baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 userFreq = info.UserFreq;
413baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 globalTime = info.GlobalTime;
414baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 globalFreq = info.GlobalFreq;
415baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NormalizeVals(userTime, userFreq);
416baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NormalizeVals(globalFreq, globalTime);
417baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (userFreq == 0)
418baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    userFreq = 1;
419baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (globalTime == 0)
420baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    globalTime = 1;
421baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return userTime * globalFreq * 1000000 / userFreq / globalTime;
422baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
423baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
424baa3858d3f5d128a5c8466b700098109edcad5f2repo syncUInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating)
425baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
426baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 userTime = info.UserTime;
427baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 userFreq = info.UserFreq;
428baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 globalTime = info.GlobalTime;
429baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 globalFreq = info.GlobalFreq;
430baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NormalizeVals(userFreq, userTime);
431baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NormalizeVals(globalTime, globalFreq);
432baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (globalFreq == 0)
433baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    globalFreq = 1;
434baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (userTime == 0)
435baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    userTime = 1;
436baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return userFreq * globalTime / globalFreq *  rating / userTime;
437baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
438baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
439baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
440baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
441baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 elTime = elapsedTime;
442baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NormalizeVals(freq, elTime);
443baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (elTime == 0)
444baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    elTime = 1;
445baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return value * freq / elTime;
446baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
447baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
448baa3858d3f5d128a5c8466b700098109edcad5f2repo syncUInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size)
449baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
450baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits);
451baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits));
452baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
453baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return MyMultDiv64(numCommands, elapsedTime, freq);
454baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
455baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
456baa3858d3f5d128a5c8466b700098109edcad5f2repo syncUInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations)
457baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
458baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 numCommands = (inSize * 200 + outSize * 4) * numIterations;
459baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return MyMultDiv64(numCommands, elapsedTime, freq);
460baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
461baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
462baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstruct CEncoderInfo;
463baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
464baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstruct CEncoderInfo
465baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
466baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifndef _7ZIP_ST
467baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NWindows::CThread thread[2];
468baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
469baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ICompressCoder> encoder;
470baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchProgressInfo *progressInfoSpec[2];
471baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ICompressProgressInfo> progressInfo[2];
472baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 NumIterations;
473baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_ALLOCA
474baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t AllocaSize;
475baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
476baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
477baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  struct CDecoderInfo
478baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
479baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CEncoderInfo *Encoder;
480baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 DecoderIndex;
481baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifdef USE_ALLOCA
482baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size_t AllocaSize;
483baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
484baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bool CallbackMode;
485baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  };
486baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CDecoderInfo decodersInfo[2];
487baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
488baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ICompressCoder> decoders[2];
489baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT Results[2];
490baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchmarkOutStream *outStreamSpec;
491baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ISequentialOutStream> outStream;
492baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  IBenchCallback *callback;
493baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 crc;
494baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 kBufferSize;
495baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 compressedSize;
496baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchRandomGenerator rg;
497baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchmarkOutStream *propStreamSpec;
498baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ISequentialOutStream> propStream;
499baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg);
500baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT Encode();
501baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT Decode(UInt32 decoderIndex);
502baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
503baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {}
504baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
505baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifndef _7ZIP_ST
506baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  static THREAD_FUNC_DECL EncodeThreadFunction(void *param)
507baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
508baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CEncoderInfo *encoder = (CEncoderInfo *)param;
509baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifdef USE_ALLOCA
510baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    alloca(encoder->AllocaSize);
511baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
512baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    HRESULT res = encoder->Encode();
513baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    encoder->Results[0] = res;
514baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (res != S_OK)
515baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      encoder->progressInfoSpec[0]->Status->SetResult(res);
516baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
517baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return 0;
518baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
519baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  static THREAD_FUNC_DECL DecodeThreadFunction(void *param)
520baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
521baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CDecoderInfo *decoder = (CDecoderInfo *)param;
522baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifdef USE_ALLOCA
523baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    alloca(decoder->AllocaSize);
524baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
525baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CEncoderInfo *encoder = decoder->Encoder;
526baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex);
527baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return 0;
528baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
529baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
530baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT CreateEncoderThread()
531baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
532baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return thread[0].Create(EncodeThreadFunction, this);
533baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
534baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
535baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT CreateDecoderThread(int index, bool callbackMode
536baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      #ifdef USE_ALLOCA
537baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      , size_t allocaSize
538baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      #endif
539baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      )
540baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
541baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CDecoderInfo &decoder = decodersInfo[index];
542baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    decoder.DecoderIndex = index;
543baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    decoder.Encoder = this;
544baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifdef USE_ALLOCA
545baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    decoder.AllocaSize = allocaSize;
546baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
547baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    decoder.CallbackMode = callbackMode;
548baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return thread[index].Create(DecodeThreadFunction, &decoder);
549baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
550baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
551baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
552baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
553baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc)
554baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
555baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  rg.Set(rgLoc);
556baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  kBufferSize = dictionarySize + kAdditionalSize;
557baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
558baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!rg.Alloc(kBufferSize))
559baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_OUTOFMEMORY;
560baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  rg.Generate();
561baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  crc = CrcCalc(rg.Buffer, rg.BufferSize);
562baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
563baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  outStreamSpec = new CBenchmarkOutStream;
564baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!outStreamSpec->Alloc(kCompressedBufferSize))
565baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_OUTOFMEMORY;
566baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
567baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  outStream = outStreamSpec;
568baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
569baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  propStreamSpec = 0;
570baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!propStream)
571baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
572baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    propStreamSpec = new CBenchmarkOutStream;
573baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    propStream = propStreamSpec;
574baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
575baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!propStreamSpec->Alloc(kMaxLzmaPropSize))
576baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_OUTOFMEMORY;
577baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  propStreamSpec->Init();
578baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
579baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  PROPID propIDs[] =
580baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
581baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NCoderPropID::kDictionarySize,
582baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NCoderPropID::kNumThreads
583baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  };
584baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
585baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  PROPVARIANT props[kNumProps];
586baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  props[0].vt = VT_UI4;
587baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  props[0].ulVal = dictionarySize;
588baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
589baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  props[1].vt = VT_UI4;
590baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  props[1].ulVal = numThreads;
591baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
592baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
593baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
594baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties));
595baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!setCoderProperties)
596baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
597baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(setCoderProperties->SetCoderProperties(propIDs, props, kNumProps));
598baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
599baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
600baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties);
601baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (writeCoderProperties)
602baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
603baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(writeCoderProperties->WriteCoderProperties(propStream));
604baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
605baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
606baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
607baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
608baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
609baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CEncoderInfo::Encode()
610baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
611baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
612baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
613baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  inStreamSpec->Init(rg.Buffer, rg.BufferSize);
614baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  outStreamSpec->Init();
615baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
616baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0]));
617baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  compressedSize = outStreamSpec->Pos;
618baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  encoder.Release();
619baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
620baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
621baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
622baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CEncoderInfo::Decode(UInt32 decoderIndex)
623baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
624baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
625baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
626baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex];
627baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
628baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;
629baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties);
630baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!compressSetDecoderProperties)
631baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
632baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
633baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CCrcOutStream *crcOutStreamSpec = new CCrcOutStream;
634baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec;
635baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
636baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchProgressInfo *pi = progressInfoSpec[decoderIndex];
637baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  pi->BenchInfo.UnpackSize = 0;
638baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  pi->BenchInfo.PackSize = 0;
639baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
640baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (UInt32 j = 0; j < NumIterations; j++)
641baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
642baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);
643baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    crcOutStreamSpec->Init();
644baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
645baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));
646baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 outSize = kBufferSize;
647baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex]));
648baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc)
649baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return S_FALSE;
650baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    pi->BenchInfo.UnpackSize += kBufferSize;
651baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    pi->BenchInfo.PackSize += compressedSize;
652baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
653baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  decoder.Release();
654baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
655baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
656baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
657baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt32 kNumThreadsMax = (1 << 16);
658baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
659baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstruct CBenchEncoders
660baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
661baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CEncoderInfo *encoders;
662baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; }
663baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ~CBenchEncoders() { delete []encoders; }
664baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
665baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
666baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT LzmaBench(
667baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  DECL_EXTERNAL_CODECS_LOC_VARS
668baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback)
669baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
670baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 numEncoderThreads =
671baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _7ZIP_ST
672baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    (numThreads > 1 ? numThreads / 2 : 1);
673baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #else
674baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    1;
675baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
676baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 numSubDecoderThreads =
677baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _7ZIP_ST
678baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    (numThreads > 1 ? 2 : 1);
679baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #else
680baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    1;
681baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
682baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax)
683baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
684baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_INVALIDARG;
685baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
686baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
687baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchEncoders encodersSpec(numEncoderThreads);
688baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CEncoderInfo *encoders = encodersSpec.encoders;
689baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
690baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
691baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 i;
692baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numEncoderThreads; i++)
693baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
694baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CEncoderInfo &encoder = encoders[i];
695baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    encoder.callback = (i == 0) ? callback : 0;
696baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
697baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UInt32 kLzmaId = 0x030101;
698baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.encoder, true));
699baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!encoder.encoder)
700baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_NOTIMPL;
701baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (UInt32 j = 0; j < numSubDecoderThreads; j++)
702baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
703baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS kLzmaId, encoder.decoders[j], false));
704baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!encoder.decoders[j])
705baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return E_NOTIMPL;
706baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
707baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
708baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
709baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBaseRandomGenerator rg;
710baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  rg.Init();
711baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numEncoderThreads; i++)
712baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
713baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(encoders[i].Init(dictionarySize, numThreads, &rg));
714baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
715baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
716baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchProgressStatus status;
717baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  status.Res = S_OK;
718baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  status.EncodeMode = true;
719baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
720baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numEncoderThreads; i++)
721baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
722baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CEncoderInfo &encoder = encoders[i];
723baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (int j = 0; j < 2; j++)
724baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
725baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo;
726baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      encoder.progressInfoSpec[j]->Status = &status;
727baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
728baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (i == 0)
729baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
730baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      encoder.progressInfoSpec[0]->callback = callback;
731baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads;
732baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);
733baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
734baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
735baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _7ZIP_ST
736baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (numEncoderThreads > 1)
737baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
738baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      #ifdef USE_ALLOCA
739baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      encoder.AllocaSize = (i * 16 * 21) & 0x7FF;
740baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      #endif
741baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(encoder.CreateEncoderThread())
742baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
743baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
744baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
745baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
746baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(encoder.Encode());
747baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
748baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
749baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifndef _7ZIP_ST
750baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (numEncoderThreads > 1)
751baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < numEncoderThreads; i++)
752baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      encoders[i].thread[0].Wait();
753baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
754baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
755baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(status.Res);
756baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
757baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchInfo info;
758baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
759baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);
760baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  info.UnpackSize = 0;
761baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  info.PackSize = 0;
762baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  info.NumIterations = 1; // progressInfoSpec->NumIterations;
763baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numEncoderThreads; i++)
764baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
765baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CEncoderInfo &encoder = encoders[i];
766baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    info.UnpackSize += encoder.kBufferSize;
767baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    info.PackSize += encoder.compressedSize;
768baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
769baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(callback->SetEncodeResult(info, true));
770baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
771baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
772baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  status.Res = S_OK;
773baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  status.EncodeMode = false;
774baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
775baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads;
776baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numEncoderThreads; i++)
777baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
778baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CEncoderInfo &encoder = encoders[i];
779baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize;
780baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
781baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (i == 0)
782baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
783baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      encoder.progressInfoSpec[0]->callback = callback;
784baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads;
785baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);
786baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
787baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
788baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _7ZIP_ST
789baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (numDecoderThreads > 1)
790baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
791baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (UInt32 j = 0; j < numSubDecoderThreads; j++)
792baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
793baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0)
794baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            #ifdef USE_ALLOCA
795baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            , ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF
796baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            #endif
797baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            );
798baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(res);
799baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
800baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
801baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
802baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
803baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
804baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(encoder.Decode(0));
805baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
806baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
807baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifndef _7ZIP_ST
808baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  HRESULT res = S_OK;
809baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (numDecoderThreads > 1)
810baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < numEncoderThreads; i++)
811baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (UInt32 j = 0; j < numSubDecoderThreads; j++)
812baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
813baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        CEncoderInfo &encoder = encoders[i];
814baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        encoder.thread[j].Wait();
815baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (encoder.Results[j] != S_OK)
816baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          res = encoder.Results[j];
817baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
818baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(res);
819baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
820baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(status.Res);
821baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);
822baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifndef _7ZIP_ST
823baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef UNDER_CE
824baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (numDecoderThreads > 1)
825baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < numEncoderThreads; i++)
826baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (UInt32 j = 0; j < numSubDecoderThreads; j++)
827baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
828baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        FILETIME creationTime, exitTime, kernelTime, userTime;
829baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (::GetThreadTimes(encoders[i].thread[j], &creationTime, &exitTime, &kernelTime, &userTime) != 0)
830baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          info.UserTime += GetTime64(userTime) + GetTime64(kernelTime);
831baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
832baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
833baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
834baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  info.UnpackSize = 0;
835baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  info.PackSize = 0;
836baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations;
837baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numEncoderThreads; i++)
838baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
839baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CEncoderInfo &encoder = encoders[i];
840baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    info.UnpackSize += encoder.kBufferSize;
841baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    info.PackSize += encoder.compressedSize;
842baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
843baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(callback->SetDecodeResult(info, false));
844baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(callback->SetDecodeResult(info, true));
845baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
846baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
847baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
848baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
849baa3858d3f5d128a5c8466b700098109edcad5f2repo syncinline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary)
850baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
851baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 hs = dictionary - 1;
852baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  hs |= (hs >> 1);
853baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  hs |= (hs >> 2);
854baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  hs |= (hs >> 4);
855baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  hs |= (hs >> 8);
856baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  hs >>= 1;
857baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  hs |= 0xFFFF;
858baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (hs > (1 << 24))
859baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    hs >>= 1;
860baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  hs++;
861baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 +
862baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      (1 << 20) + (multiThread ? (6 << 20) : 0);
863baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
864baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
865baa3858d3f5d128a5c8466b700098109edcad5f2repo syncUInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary)
866baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
867baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const UInt32 kBufferSize = dictionary;
868baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const UInt32 kCompressedBufferSize = (kBufferSize / 2);
869baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 numSubThreads = (numThreads > 1) ? 2 : 1;
870baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 numBigThreads = numThreads / numSubThreads;
871baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return (kBufferSize + kCompressedBufferSize +
872baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads;
873baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
874baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
875baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase)
876baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
877baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (UInt32 i = 0; i < numCycles; i++)
878baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (CrcCalc(data, size) != crcBase)
879baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return false;
880baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return true;
881baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
882baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
883baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifndef _7ZIP_ST
884baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstruct CCrcInfo
885baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
886baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  NWindows::CThread Thread;
887baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const Byte *Data;
888baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 Size;
889baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 NumCycles;
890baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 Crc;
891baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool Res;
892baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  void Wait()
893baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
894baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Thread.Wait();
895baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    Thread.Close();
896baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
897baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
898baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
899baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic THREAD_FUNC_DECL CrcThreadFunction(void *param)
900baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
901baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CCrcInfo *p = (CCrcInfo *)param;
902baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc);
903baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return 0;
904baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
905baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
906baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstruct CCrcThreads
907baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
908baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 NumThreads;
909baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CCrcInfo *Items;
910baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CCrcThreads(): Items(0), NumThreads(0) {}
911baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  void WaitAll()
912baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
913baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (UInt32 i = 0; i < NumThreads; i++)
914baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      Items[i].Wait();
915baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NumThreads = 0;
916baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
917baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ~CCrcThreads()
918baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
919baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    WaitAll();
920baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    delete []Items;
921baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
922baa3858d3f5d128a5c8466b700098109edcad5f2repo sync};
923baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
924baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
925baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic UInt32 CrcCalc1(const Byte *buf, UInt32 size)
926baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
927baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 crc = CRC_INIT_VAL;;
928baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (UInt32 i = 0; i < size; i++)
929baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    crc = CRC_UPDATE_BYTE(crc, buf[i]);
930baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return CRC_GET_DIGEST(crc);
931baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
932baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
933baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)
934baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
935baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (UInt32 i = 0; i < size; i++)
936baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    buf[i] = (Byte)RG.GetRnd();
937baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
938baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
939baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)
940baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
941baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RandGen(buf, size, RG);
942baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return CrcCalc1(buf, size);
943baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
944baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
945baa3858d3f5d128a5c8466b700098109edcad5f2repo syncbool CrcInternalTest()
946baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
947baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchBuffer buffer;
948baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const UInt32 kBufferSize0 = (1 << 8);
949baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const UInt32 kBufferSize1 = (1 << 10);
950baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  const UInt32 kCheckSize = (1 << 5);
951baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!buffer.Alloc(kBufferSize0 + kBufferSize1))
952baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
953baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Byte *buf = buffer.Buffer;
954baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 i;
955baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < kBufferSize0; i++)
956baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    buf[i] = (Byte)i;
957baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 crc1 = CrcCalc1(buf, kBufferSize0);
958baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (crc1 != 0x29058C73)
959baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return false;
960baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBaseRandomGenerator RG;
961baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RandGen(buf + kBufferSize0, kBufferSize1, RG);
962baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++)
963baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (UInt32 j = 0; j < kCheckSize; j++)
964baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j))
965baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return false;
966baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return true;
967baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
968baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
969baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed)
970baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
971baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (numThreads == 0)
972baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    numThreads = 1;
973baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
974baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBenchBuffer buffer;
975baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t totalSize = (size_t)bufferSize * numThreads;
976baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (totalSize / numThreads != bufferSize)
977baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_OUTOFMEMORY;
978baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!buffer.Alloc(totalSize))
979baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_OUTOFMEMORY;
980baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
981baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  Byte *buf = buffer.Buffer;
982baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CBaseRandomGenerator RG;
983baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 numCycles = (kCrcBlockSize) / ((bufferSize >> 2) + 1) + 1;
984baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
985baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 timeVal;
986baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifndef _7ZIP_ST
987baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CCrcThreads threads;
988baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (numThreads > 1)
989baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
990baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    threads.Items = new CCrcInfo[numThreads];
991baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 i;
992baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < numThreads; i++)
993baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
994baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CCrcInfo &info = threads.Items[i];
995baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      Byte *data = buf + (size_t)bufferSize * i;
996baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      info.Data = data;
997baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      info.NumCycles = numCycles;
998baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      info.Size = bufferSize;
999baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      info.Crc = RandGenCrc(data, bufferSize, RG);
1000baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
1001baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    timeVal = GetTimeCount();
1002baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < numThreads; i++)
1003baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
1004baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CCrcInfo &info = threads.Items[i];
1005baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(info.Thread.Create(CrcThreadFunction, &info));
1006baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      threads.NumThreads++;
1007baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
1008baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    threads.WaitAll();
1009baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < numThreads; i++)
1010baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!threads.Items[i].Res)
1011baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return S_FALSE;
1012baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
1013baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
1014baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
1015baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
1016baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 crc = RandGenCrc(buf, bufferSize, RG);
1017baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    timeVal = GetTimeCount();
1018baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!CrcBig(buf, bufferSize, numCycles, crc))
1019baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return S_FALSE;
1020baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
1021baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  timeVal = GetTimeCount() - timeVal;
1022baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (timeVal == 0)
1023baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    timeVal = 1;
1024baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
1025baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 size = (UInt64)numCycles * totalSize;
1026baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  speed = MyMultDiv64(size, timeVal, GetFreq());
1027baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
1028baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
1029