Poco::Checksum

Poco::Checksum を紹介します。

このクラスは、CRC-32 か Adler-32 のチェックサムを計算します。

ChecksumTest.cpp

・AdjustAllocationBytes() でバイト数を調整した後、Poco::Buffer で領域を確保。
Poco::Random::nextChar() で領域全体を埋め、Poco::Checksum::update() を呼び、チェックサムを
 計算して、所要時間を計測。

#include <Poco/Buffer.h>
#include <Poco/Random.h>
#include <Poco/Stopwatch.h>
#include <Poco/Format.h>
#include <Poco/Checksum.h>
 
#include <string>
 
#include "ScopedLogMessage.h"
#include "PrepareConsoleLogger.h"
 
const std::size_t kBufferSize = 64*1024*1024;
const int kNumTrial = 4;
 
#if defined(POCO_OS_FAMILY_WINDOWS)
#include <new.h>
 
int ThrowBadAlloc(std::size_t)
{
	throw std::bad_alloc();
	return 0;
}
#endif
 
std::size_t AdjustAllocationBytes(ScopedLogMessage& msg, std::size_t bytesWanted)
{
	std::size_t bufferSize = bytesWanted;
 
	bool memoryAvailable = false;
	char* tempPtr = NULL;
 
#if defined(POCO_OS_FAMILY_WINDOWS)
	_set_new_handler(ThrowBadAlloc);
#endif
 
	while(!memoryAvailable)
	{
		try
		{
			tempPtr = new char [bufferSize];
			memoryAvailable = true;
		}
		catch(...)
		{
			bufferSize /= 2;
		}
		delete [] tempPtr;
		tempPtr = NULL;
	}
	msg.Message(Poco::format(" Number of buffer allocation bytes: %z", bufferSize));
	return bufferSize;
}
 
int main(int /*argc*/, char** /*argv*/)
{
	PrepareConsoleLogger logger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION);
 
	ScopedLogMessage msg("ChecksumTest ", "start", "end");
 
	Poco::Checksum checksum[] = {	Poco::Checksum(Poco::Checksum::TYPE_ADLER32)
				,	Poco::Checksum(Poco::Checksum::TYPE_CRC32)	};
	const int kNumChecksumTypes = sizeof(checksum)/sizeof(checksum[0]);
 
	double time[kNumChecksumTypes][kNumTrial];
	Poco::UInt32 sum[kNumChecksumTypes][kNumTrial];
 
	Poco::Stopwatch stopwatch;
	Poco::Random random;
	Poco::Buffer<char> buffer(AdjustAllocationBytes(msg, kBufferSize));
 
	for(int trial=0; trial<kNumTrial; ++trial)
	{
		std::fill(buffer.begin(), buffer.end(), random.nextChar());
 
		for(int type=0; type<kNumChecksumTypes; ++type)
		{
			stopwatch.restart();
			checksum[type].update(buffer.begin(), static_cast<unsigned>(buffer.size()));
			stopwatch.stop();
			time[type][trial] = (1000.0 * stopwatch.elapsed()) / stopwatch.resolution();
			sum[type][trial] = checksum[type].checksum();
		}
	}
 
	msg.Message("         TYPE_ADLER32                 TYPE_CRC32");
	msg.Message("      checksum     time           checksum     time");
	msg.Message(" =============================+=======================");
	for(int trial=0; trial<kNumTrial; ++trial)
	{
		msg.Message(Poco::format(" #%d: 0x%08X  %7.3fmSec     0x%08X  %7.3fmSec"
					, trial+1
					,  sum[Poco::Checksum::TYPE_ADLER32][trial]
					, time[Poco::Checksum::TYPE_ADLER32][trial]
					,  sum[Poco::Checksum::TYPE_CRC32][trial]
					, time[Poco::Checksum::TYPE_CRC32][trial]));
	}
 
	return 0;
}

Results of execution

Poco::Checksum のページには、Adler-32 は “significantly faster to calculate in software” と書いてある
 けれども、下の結果を見ると CRC-32 の方が高速な場合もあるので、実際に使うプラットフォーム上
 での確認が必要。

– On Linux debian 2.6.26-2-686

[0] ChecksumTest start
[0]  Number of buffer allocation bytes: 67108864
[0]          TYPE_ADLER32                 TYPE_CRC32
[0]       checksum     time           checksum     time
[0]  =============================+=======================
[0]  #1: 0xCD6D8E59  167.299mSec     0x4D50B53A   91.137mSec
[0]  #2: 0xF7775AC2  166.580mSec     0xE4AC4D84   91.140mSec
[0]  #3: 0x5C97CDDD  164.049mSec     0x0990709C   91.713mSec
[0]  #4: 0x3880ADFB  164.859mSec     0xFB78DA54   92.857mSec
[0] ChecksumTest end

– On Linux Ubuntu 2.6.32-23-generic

[0] ChecksumTest start
[0]  Number of buffer allocation bytes: 67108864
[0]          TYPE_ADLER32                 TYPE_CRC32
[0]       checksum     time           checksum     time
[0]  =============================+=======================
[0]  #1: 0xECEE89B4   57.698mSec     0x7DAB7CE2  104.128mSec
[0]  #2: 0x4C30E1D2   56.870mSec     0xD717AEEA  100.885mSec
[0]  #3: 0x2EBA68B1   60.547mSec     0x38BDDB51  102.593mSec
[0]  #4: 0x8E4E0709   57.288mSec     0xE22F107F  100.440mSec
[0] ChecksumTest end

– On Macintosh OSX 10.6.3

[0] ChecksumTest start
[0]  Number of buffer allocation bytes: 67108864
[0]          TYPE_ADLER32                 TYPE_CRC32
[0]       checksum     time           checksum     time
[0]  =============================+=======================
[0]  #1: 0x1775DEEF   66.666mSec     0xE27BDE31   98.712mSec
[0]  #2: 0xE94BD1A1   66.495mSec     0x67207840   98.127mSec
[0]  #3: 0x55F24F36   66.585mSec     0x9C132C3D   98.556mSec
[0]  #4: 0xC7F3EBBD   66.626mSec     0xEFBD54DF   98.468mSec
[0] ChecksumTest end

– On Windows XP sp3

[0] ChecksumTest start
[0]  Number of buffer allocation bytes: 67108864
[0]          TYPE_ADLER32                 TYPE_CRC32
[0]       checksum     time           checksum     time
[0]  =============================+=======================
[0]  #1: 0xFF741C1F  359.375mSec     0xC2936697  234.375mSec
[0]  #2: 0x0CDF5178  296.875mSec     0xD83702E5  218.750mSec
[0]  #3: 0x39D2C695  296.875mSec     0x69841458  218.750mSec
[0]  #4: 0x1B1E9F2B  312.500mSec     0x5FBC44AD  218.750mSec
[0] ChecksumTest end

Downloads

ここをクリックすると、makefile や VC++ プロジェクトなど一式がダウンロードできます。
(2013.05.31 updated)
・2010年7月15日からのダウンロード数:829

Subversion

・フリーの Subversion ホスティングサービス Assemblaで、ソースコードを管理しています。

Powered by POCO Copyright © 2010 Round Square Inc. All rights reserved.


  1. こんにちは。
    試していないので、机上チェックの観点だけであることを申し上げます。

    AdjustAllocationBytes関数ですが、
    Visual C++ では bad_alloc 例外出力が標準ではない為、常に true になるかと思われます。
    あと、new/delete の区間ですが、最適化が働くとtempPtr は関数内では NULL 一定である為、new と delete を行っている行は不要なコードとみなされ、パスがなくなってしまい、常に true となってしまう可能性があるように見受けられます。
    char* tempPtr に volatile 修飾子が必要なのではないのかなぁ?と思いました。

    char* tempPtr = NULL;

    while(!memoryAvailable)
    {
    try
    {
    tempPtr = new char [bufferSize];
    delete [] tempPtr;
    tempPtr = NULL;
    memoryAvailable = true;
    }
    catch(…)
    {
    bufferSize /= 2;
    }
    }

    間違っていたらごめんなさい。

  2. コメントありがとうございます。
    私は VC++ にはちっとも詳しくないので、こういったチェックを入れて頂けるととても助かります。

    bad_alloc の件はロベールのC++教室 – 第49章 破壊と創造 –を参考にさせて頂き、最適化の件については、delete を new とは別のスコープに移すことで対応しました。

    (同様のコードが MemoryPool の記事の方にもありましたので、そちらも修正しました)

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>