9 #define USE_POSIX_TIME2
14 #ifdef USE_POSIX_TIME2
33 #include "../../../../C/Alloc.h"
34 #include "../../../../C/7zCrc.h"
36 #include "../../../Common/MyCom.h"
37 #include "../../ICoder.h"
40 #include "../../../Windows/Thread.h"
41 #include "../../../Windows/Synchronization.h"
45 #include "../../../Windows/PropVariant.h"
47 #include "../LZMA/LZMADecoder.h"
48 #include "../LZMA/LZMAEncoder.h"
51 static const UInt32 kUncompressMinBlockSize = 1 << 26;
52 static const UInt32 kAdditionalSize = (1 << 16);
53 static const UInt32 kCompressedAdditionalSize = (1 << 10);
54 static const UInt32 kMaxLzmaPropSize = 5;
56 class CBaseRandomGenerator
61 CBaseRandomGenerator() { Init(); }
62 void Init() { A1 = 362436069; A2 = 521288629;}
66 ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) +
67 ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) );
76 CBenchBuffer(): Buffer(0) {}
77 virtual ~CBenchBuffer() { Free(); }
83 bool Alloc(size_t bufferSize)
85 if (Buffer != 0 && BufferSize == bufferSize)
88 Buffer = (Byte *)::MidAlloc(bufferSize);
89 BufferSize = bufferSize;
94 class CBenchRandomGenerator: public CBenchBuffer
96 CBaseRandomGenerator *RG;
98 void Set(CBaseRandomGenerator *rg) { RG = rg; }
99 UInt32 GetVal(UInt32 &res, int numBits)
101 UInt32 val = res & (((UInt32)1 << numBits) - 1);
105 UInt32 GetLen(UInt32 &res)
107 UInt32 len = GetVal(res, 2);
108 return GetVal(res, 1 + len);
114 while (pos < BufferSize)
116 UInt32 res = RG->GetRnd();
118 if (GetVal(res, 1) == 0 || pos < 1024)
119 Buffer[pos++] = (Byte)(res & 0xFF);
123 len = 1 + GetLen(res);
124 if (GetVal(res, 3) != 0)
129 UInt32 ppp = GetVal(res, 5) + 6;
133 rep0 = /* (1 << ppp) +*/ GetVal(res, ppp);
140 for (UInt32 i = 0; i < len && pos < BufferSize; i++, pos++)
141 Buffer[pos] = Buffer[pos - rep0];
148 class CBenchmarkInStream:
149 public ISequentialInStream,
157 void Init(const Byte *data, size_t size)
163 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
166 STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
168 size_t remain = Size - Pos;
169 UInt32 kMaxBlockSize = (1 << 20);
170 if (size > kMaxBlockSize)
171 size = kMaxBlockSize;
173 size = (UInt32)remain;
174 for (UInt32 i = 0; i < size; i++)
175 ((Byte *)data)[i] = Data[Pos + i];
177 if(processedSize != NULL)
178 *processedSize = size;
182 class CBenchmarkOutStream:
183 public ISequentialOutStream,
190 // CBenchmarkOutStream(): _overflow(false) {}
193 // _overflow = false;
197 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
200 STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
202 size_t curSize = BufferSize - Pos;
205 memcpy(Buffer + Pos, data, curSize);
206 Pos += (UInt32)curSize;
207 if(processedSize != NULL)
208 *processedSize = (UInt32)curSize;
218 public ISequentialOutStream,
224 void Init() { Crc = CRC_INIT_VAL; }
225 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
228 STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
230 Crc = CrcUpdate(Crc, data, size);
231 if (processedSize != NULL)
232 *processedSize = size;
236 static UInt64 GetTimeCount()
238 #ifdef USE_POSIX_TIME
239 #ifdef USE_POSIX_TIME2
241 if (gettimeofday(&v, 0) == 0)
242 return (UInt64)(v.tv_sec) * 1000000 + v.tv_usec;
243 return (UInt64)time(NULL) * 1000000;
250 if (::QueryPerformanceCounter(&value))
251 return value.QuadPart;
253 return GetTickCount();
257 static UInt64 GetFreq()
259 #ifdef USE_POSIX_TIME
260 #ifdef USE_POSIX_TIME2
268 if (::QueryPerformanceFrequency(&value))
269 return value.QuadPart;
275 #ifndef USE_POSIX_TIME
276 static inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }
278 static UInt64 GetUserTime()
280 #ifdef USE_POSIX_TIME
283 FILETIME creationTime, exitTime, kernelTime, userTime;
284 if (::GetProcessTimes(::GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime) != 0)
285 return GetTime64(userTime) + GetTime64(kernelTime);
286 return (UInt64)GetTickCount() * 10000;
290 static UInt64 GetUserFreq()
292 #ifdef USE_POSIX_TIME
293 return CLOCKS_PER_SEC;
299 class CBenchProgressStatus
302 NWindows::NSynchronization::CCriticalSection CS;
307 void SetResult(HRESULT res)
310 NWindows::NSynchronization::CCriticalSectionLock lock(CS);
317 NWindows::NSynchronization::CCriticalSectionLock lock(CS);
323 class CBenchProgressInfo:
324 public ICompressProgressInfo,
328 CBenchProgressStatus *Status;
329 CBenchInfo BenchInfo;
331 IBenchCallback *callback;
332 CBenchProgressInfo(): callback(0) {}
334 STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
337 void SetStartTime(CBenchInfo &bi)
339 bi.GlobalFreq = GetFreq();
340 bi.UserFreq = GetUserFreq();
341 bi.GlobalTime = ::GetTimeCount();
342 bi.UserTime = ::GetUserTime();
345 void SetFinishTime(const CBenchInfo &biStart, CBenchInfo &dest)
347 dest.GlobalFreq = GetFreq();
348 dest.UserFreq = GetUserFreq();
349 dest.GlobalTime = ::GetTimeCount() - biStart.GlobalTime;
350 dest.UserTime = ::GetUserTime() - biStart.UserTime;
353 STDMETHODIMP CBenchProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
355 HRESULT res = Status->GetResult();
360 CBenchInfo info = BenchInfo;
361 SetFinishTime(BenchInfo, info);
362 if (Status->EncodeMode)
364 info.UnpackSize = *inSize;
365 info.PackSize = *outSize;
366 res = callback->SetEncodeResult(info, false);
370 info.PackSize = BenchInfo.PackSize + *inSize;
371 info.UnpackSize = BenchInfo.UnpackSize + *outSize;
372 res = callback->SetDecodeResult(info, false);
375 Status->SetResult(res);
379 static const int kSubBits = 8;
381 static UInt32 GetLogSize(UInt32 size)
383 for (int i = kSubBits; i < 32; i++)
384 for (UInt32 j = 0; j < (1 << kSubBits); j++)
385 if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))
386 return (i << kSubBits) + j;
387 return (32 << kSubBits);
390 static void NormalizeVals(UInt64 &v1, UInt64 &v2)
399 UInt64 GetUsage(const CBenchInfo &info)
401 UInt64 userTime = info.UserTime;
402 UInt64 userFreq = info.UserFreq;
403 UInt64 globalTime = info.GlobalTime;
404 UInt64 globalFreq = info.GlobalFreq;
405 NormalizeVals(userTime, userFreq);
406 NormalizeVals(globalFreq, globalTime);
411 return userTime * globalFreq * 1000000 / userFreq / globalTime;
414 UInt64 GetRatingPerUsage(const CBenchInfo &info, UInt64 rating)
416 UInt64 userTime = info.UserTime;
417 UInt64 userFreq = info.UserFreq;
418 UInt64 globalTime = info.GlobalTime;
419 UInt64 globalFreq = info.GlobalFreq;
420 NormalizeVals(userFreq, userTime);
421 NormalizeVals(globalTime, globalFreq);
426 return userFreq * globalTime / globalFreq * rating / userTime;
429 static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
431 UInt64 elTime = elapsedTime;
432 NormalizeVals(freq, elTime);
435 return value * freq / elTime;
438 UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 freq, UInt64 size)
440 UInt64 t = GetLogSize(dictionarySize) - (kBenchMinDicLogSize << kSubBits);
441 // UInt64 numCommandsForOne = 1000 + ((t * t * 7) >> (2 * kSubBits)); // AMD K8
442 UInt64 numCommandsForOne = 870 + ((t * t * 5) >> (2 * kSubBits)); // Intel Core2
444 UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
445 return MyMultDiv64(numCommands, elapsedTime, freq);
448 UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 freq, UInt64 outSize, UInt64 inSize, UInt32 numIterations)
450 // UInt64 numCommands = (inSize * 216 + outSize * 14) * numIterations; // AMD K8
451 UInt64 numCommands = (inSize * 220 + outSize * 8) * numIterations; // Intel Core2
452 return MyMultDiv64(numCommands, elapsedTime, freq);
456 typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID,
457 const GUID *interfaceID, void **outObject);
465 NWindows::CThread thread[2];
467 CMyComPtr<ICompressCoder> encoder;
468 CBenchProgressInfo *progressInfoSpec[2];
469 CMyComPtr<ICompressProgressInfo> progressInfo[2];
470 UInt32 NumIterations;
477 CEncoderInfo *Encoder;
484 CDecoderInfo decodersInfo[2];
486 CMyComPtr<ICompressCoder> decoders[2];
488 CBenchmarkOutStream *outStreamSpec;
489 CMyComPtr<ISequentialOutStream> outStream;
490 IBenchCallback *callback;
493 UInt32 compressedSize;
494 CBenchRandomGenerator rg;
495 CBenchmarkOutStream *propStreamSpec;
496 CMyComPtr<ISequentialOutStream> propStream;
497 HRESULT Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rg);
499 HRESULT Decode(UInt32 decoderIndex);
501 CEncoderInfo(): outStreamSpec(0), callback(0), propStreamSpec(0) {}
504 static THREAD_FUNC_DECL EncodeThreadFunction(void *param)
506 CEncoderInfo *encoder = (CEncoderInfo *)param;
508 alloca(encoder->AllocaSize);
510 HRESULT res = encoder->Encode();
511 encoder->Results[0] = res;
513 encoder->progressInfoSpec[0]->Status->SetResult(res);
517 static THREAD_FUNC_DECL DecodeThreadFunction(void *param)
519 CDecoderInfo *decoder = (CDecoderInfo *)param;
521 alloca(decoder->AllocaSize);
523 CEncoderInfo *encoder = decoder->Encoder;
524 encoder->Results[decoder->DecoderIndex] = encoder->Decode(decoder->DecoderIndex);
528 HRESULT CreateEncoderThread()
530 return thread[0].Create(EncodeThreadFunction, this);
533 HRESULT CreateDecoderThread(int index, bool callbackMode
539 CDecoderInfo &decoder = decodersInfo[index];
540 decoder.DecoderIndex = index;
541 decoder.Encoder = this;
543 decoder.AllocaSize = allocaSize;
545 decoder.CallbackMode = callbackMode;
546 return thread[index].Create(DecodeThreadFunction, &decoder);
551 HRESULT CEncoderInfo::Init(UInt32 dictionarySize, UInt32 numThreads, CBaseRandomGenerator *rgLoc)
554 kBufferSize = dictionarySize + kAdditionalSize;
555 UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
556 if (!rg.Alloc(kBufferSize))
557 return E_OUTOFMEMORY;
559 crc = CrcCalc(rg.Buffer, rg.BufferSize);
561 outStreamSpec = new CBenchmarkOutStream;
562 if (!outStreamSpec->Alloc(kCompressedBufferSize))
563 return E_OUTOFMEMORY;
565 outStream = outStreamSpec;
570 propStreamSpec = new CBenchmarkOutStream;
571 propStream = propStreamSpec;
573 if (!propStreamSpec->Alloc(kMaxLzmaPropSize))
574 return E_OUTOFMEMORY;
575 propStreamSpec->Init();
579 NCoderPropID::kDictionarySize,
580 NCoderPropID::kMultiThread
582 const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
583 PROPVARIANT properties[kNumProps];
584 properties[0].vt = VT_UI4;
585 properties[0].ulVal = (UInt32)dictionarySize;
587 properties[1].vt = VT_BOOL;
588 properties[1].boolVal = (numThreads > 1) ? VARIANT_TRUE : VARIANT_FALSE;
591 CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
592 RINOK(encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties));
593 if (!setCoderProperties)
595 RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, kNumProps));
597 CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
598 encoder.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties);
599 if (writeCoderProperties)
601 RINOK(writeCoderProperties->WriteCoderProperties(propStream));
607 HRESULT CEncoderInfo::Encode()
609 CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
610 CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
611 inStreamSpec->Init(rg.Buffer, rg.BufferSize);
612 outStreamSpec->Init();
614 RINOK(encoder->Code(inStream, outStream, 0, 0, progressInfo[0]));
615 compressedSize = outStreamSpec->Pos;
620 HRESULT CEncoderInfo::Decode(UInt32 decoderIndex)
622 CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
623 CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
624 CMyComPtr<ICompressCoder> &decoder = decoders[decoderIndex];
626 CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;
627 decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties);
628 if (!compressSetDecoderProperties)
631 CCrcOutStream *crcOutStreamSpec = new CCrcOutStream;
632 CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec;
634 CBenchProgressInfo *pi = progressInfoSpec[decoderIndex];
635 pi->BenchInfo.UnpackSize = 0;
636 pi->BenchInfo.PackSize = 0;
638 for (UInt32 j = 0; j < NumIterations; j++)
640 inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);
641 crcOutStreamSpec->Init();
643 RINOK(compressSetDecoderProperties->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos));
644 UInt64 outSize = kBufferSize;
645 RINOK(decoder->Code(inStream, crcOutStream, 0, &outSize, progressInfo[decoderIndex]));
646 if (CRC_GET_DIGEST(crcOutStreamSpec->Crc) != crc)
648 pi->BenchInfo.UnpackSize += kBufferSize;
649 pi->BenchInfo.PackSize += compressedSize;
655 static const UInt32 kNumThreadsMax = (1 << 16);
657 struct CBenchEncoders
659 CEncoderInfo *encoders;
660 CBenchEncoders(UInt32 num): encoders(0) { encoders = new CEncoderInfo[num]; }
661 ~CBenchEncoders() { delete []encoders; }
668 UInt32 numThreads, UInt32 dictionarySize, IBenchCallback *callback)
670 UInt32 numEncoderThreads =
672 (numThreads > 1 ? numThreads / 2 : 1);
676 UInt32 numSubDecoderThreads =
678 (numThreads > 1 ? 2 : 1);
682 if (dictionarySize < (1 << kBenchMinDicLogSize) || numThreads < 1 || numEncoderThreads > kNumThreadsMax)
687 CBenchEncoders encodersSpec(numEncoderThreads);
688 CEncoderInfo *encoders = encodersSpec.encoders;
691 UString name = L"LZMA";
695 for (i = 0; i < numEncoderThreads; i++)
697 CEncoderInfo &encoder = encoders[i];
698 encoder.callback = (i == 0) ? callback : 0;
701 RINOK(codecs->CreateCoder(name, true, encoder.encoder));
703 encoder.encoder = new NCompress::NLZMA::CEncoder;
705 for (UInt32 j = 0; j < numSubDecoderThreads; j++)
708 RINOK(codecs->CreateCoder(name, false, encoder.decoders[j]));
710 encoder.decoders[j] = new NCompress::NLZMA::CDecoder;
715 CBaseRandomGenerator rg;
717 for (i = 0; i < numEncoderThreads; i++)
719 RINOK(encoders[i].Init(dictionarySize, numThreads, &rg));
722 CBenchProgressStatus status;
724 status.EncodeMode = true;
726 for (i = 0; i < numEncoderThreads; i++)
728 CEncoderInfo &encoder = encoders[i];
729 for (int j = 0; j < 2; j++)
731 encoder.progressInfo[j] = encoder.progressInfoSpec[j] = new CBenchProgressInfo;
732 encoder.progressInfoSpec[j]->Status = &status;
736 encoder.progressInfoSpec[0]->callback = callback;
737 encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numEncoderThreads;
738 SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);
742 if (numEncoderThreads > 1)
745 encoder.AllocaSize = (i * 16 * 21) & 0x7FF;
747 RINOK(encoder.CreateEncoderThread())
752 RINOK(encoder.Encode());
756 if (numEncoderThreads > 1)
757 for (i = 0; i < numEncoderThreads; i++)
758 encoders[i].thread[0].Wait();
765 SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);
768 info.NumIterations = 1; // progressInfoSpec->NumIterations;
769 for (i = 0; i < numEncoderThreads; i++)
771 CEncoderInfo &encoder = encoders[i];
772 info.UnpackSize += encoder.kBufferSize;
773 info.PackSize += encoder.compressedSize;
775 RINOK(callback->SetEncodeResult(info, true));
779 status.EncodeMode = false;
781 UInt32 numDecoderThreads = numEncoderThreads * numSubDecoderThreads;
782 for (i = 0; i < numEncoderThreads; i++)
784 CEncoderInfo &encoder = encoders[i];
785 encoder.NumIterations = 2 + kUncompressMinBlockSize / encoder.kBufferSize;
789 encoder.progressInfoSpec[0]->callback = callback;
790 encoder.progressInfoSpec[0]->BenchInfo.NumIterations = numDecoderThreads;
791 SetStartTime(encoder.progressInfoSpec[0]->BenchInfo);
795 if (numDecoderThreads > 1)
797 for (UInt32 j = 0; j < numSubDecoderThreads; j++)
799 size_t allocaSize = ((i * numSubDecoderThreads + j) * 16 * 21) & 0x7FF;
800 HRESULT res = encoder.CreateDecoderThread(j, (i == 0 && j == 0)
811 RINOK(encoder.Decode(0));
816 if (numDecoderThreads > 1)
817 for (i = 0; i < numEncoderThreads; i++)
818 for (UInt32 j = 0; j < numSubDecoderThreads; j++)
820 CEncoderInfo &encoder = encoders[i];
821 encoder.thread[j].Wait();
822 if (encoder.Results[j] != S_OK)
823 res = encoder.Results[j];
828 SetFinishTime(encoders[0].progressInfoSpec[0]->BenchInfo, info);
831 info.NumIterations = numSubDecoderThreads * encoders[0].NumIterations;
832 for (i = 0; i < numEncoderThreads; i++)
834 CEncoderInfo &encoder = encoders[i];
835 info.UnpackSize += encoder.kBufferSize;
836 info.PackSize += encoder.compressedSize;
838 RINOK(callback->SetDecodeResult(info, false));
839 RINOK(callback->SetDecodeResult(info, true));
844 inline UInt64 GetLZMAUsage(bool multiThread, UInt32 dictionary)
846 UInt32 hs = dictionary - 1;
856 return ((hs + (1 << 16)) + (UInt64)dictionary * 2) * 4 + (UInt64)dictionary * 3 / 2 +
857 (1 << 20) + (multiThread ? (6 << 20) : 0);
860 UInt64 GetBenchMemoryUsage(UInt32 numThreads, UInt32 dictionary)
862 const UInt32 kBufferSize = dictionary;
863 const UInt32 kCompressedBufferSize = (kBufferSize / 2);
864 UInt32 numSubThreads = (numThreads > 1) ? 2 : 1;
865 UInt32 numBigThreads = numThreads / numSubThreads;
866 return (kBufferSize + kCompressedBufferSize +
867 GetLZMAUsage((numThreads > 1), dictionary) + (2 << 20)) * numBigThreads;
870 static bool CrcBig(const void *data, UInt32 size, UInt32 numCycles, UInt32 crcBase)
872 for (UInt32 i = 0; i < numCycles; i++)
873 if (CrcCalc(data, size) != crcBase)
881 NWindows::CThread Thread;
894 static THREAD_FUNC_DECL CrcThreadFunction(void *param)
896 CCrcInfo *p = (CCrcInfo *)param;
897 p->Res = CrcBig(p->Data, p->Size, p->NumCycles, p->Crc);
905 CCrcThreads(): Items(0), NumThreads(0) {}
908 for (UInt32 i = 0; i < NumThreads; i++)
920 static UInt32 CrcCalc1(const Byte *buf, UInt32 size)
922 UInt32 crc = CRC_INIT_VAL;;
923 for (UInt32 i = 0; i < size; i++)
924 crc = CRC_UPDATE_BYTE(crc, buf[i]);
925 return CRC_GET_DIGEST(crc);
928 static void RandGen(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)
930 for (UInt32 i = 0; i < size; i++)
931 buf[i] = (Byte)RG.GetRnd();
934 static UInt32 RandGenCrc(Byte *buf, UInt32 size, CBaseRandomGenerator &RG)
936 RandGen(buf, size, RG);
937 return CrcCalc1(buf, size);
940 bool CrcInternalTest()
943 const UInt32 kBufferSize0 = (1 << 8);
944 const UInt32 kBufferSize1 = (1 << 10);
945 const UInt32 kCheckSize = (1 << 5);
946 if (!buffer.Alloc(kBufferSize0 + kBufferSize1))
948 Byte *buf = buffer.Buffer;
950 for (i = 0; i < kBufferSize0; i++)
952 UInt32 crc1 = CrcCalc1(buf, kBufferSize0);
953 if (crc1 != 0x29058C73)
955 CBaseRandomGenerator RG;
956 RandGen(buf + kBufferSize0, kBufferSize1, RG);
957 for (i = 0; i < kBufferSize0 + kBufferSize1 - kCheckSize; i++)
958 for (UInt32 j = 0; j < kCheckSize; j++)
959 if (CrcCalc1(buf + i, j) != CrcCalc(buf + i, j))
964 HRESULT CrcBench(UInt32 numThreads, UInt32 bufferSize, UInt64 &speed)
970 size_t totalSize = (size_t)bufferSize * numThreads;
971 if (totalSize / numThreads != bufferSize)
972 return E_OUTOFMEMORY;
973 if (!buffer.Alloc(totalSize))
974 return E_OUTOFMEMORY;
976 Byte *buf = buffer.Buffer;
977 CBaseRandomGenerator RG;
978 UInt32 numCycles = ((UInt32)1 << 30) / ((bufferSize >> 2) + 1) + 1;
985 threads.Items = new CCrcInfo[numThreads];
987 for (i = 0; i < numThreads; i++)
989 CCrcInfo &info = threads.Items[i];
990 Byte *data = buf + (size_t)bufferSize * i;
992 info.NumCycles = numCycles;
993 info.Size = bufferSize;
994 info.Crc = RandGenCrc(data, bufferSize, RG);
996 timeVal = GetTimeCount();
997 for (i = 0; i < numThreads; i++)
999 CCrcInfo &info = threads.Items[i];
1000 RINOK(info.Thread.Create(CrcThreadFunction, &info));
1001 threads.NumThreads++;
1004 for (i = 0; i < numThreads; i++)
1005 if (!threads.Items[i].Res)
1011 UInt32 crc = RandGenCrc(buf, bufferSize, RG);
1012 timeVal = GetTimeCount();
1013 if (!CrcBig(buf, bufferSize, numCycles, crc))
1016 timeVal = GetTimeCount() - timeVal;
1020 UInt64 size = (UInt64)numCycles * totalSize;
1021 speed = MyMultDiv64(size, timeVal, GetFreq());