千分求最快的Base64编码函数

housisong 2007-07-20 11:39:48
为了便于查看和讨论,请移步到 “ http://community.csdn.net/Expert/topic/5665/5665480.xml?temp=.9847528 ” 查看或发帖

我有上万的可用分,可以开新贴给分

Base64编码是很常用的一种把二进制数据转换为字符串的算法;
(它把3个8bit数据分成4组6bit数据,然后拿6bit数映射到64个可显示字符集合中的一个)

我开贴征集最快的Base64编码函数,要求如下:
1.使用200MB随机数据来测试编码函数 (数据量最少的话也要20MB上)
2.测试单位时间(秒)编码出的字符数据量 (假设200MB数据用了2秒钟编码时间,那速度就是:200MB/3*4/2s=133.3MB/s)
3.必须说明测试使用的CPU型号(运行频率)、最好说明内存型号(运行频率) 、语言和编译器类型
4.可以测试已有的Base64编码函数(比如各种库中的、开源的等等),注明来源(可以不提供源代码),也可以是自己写的(最好能给出源代码)
5.可以补充测试一下Base64解码函数的速度
(如果是自己写的 看函数速度 给分时酌情加分)


==========================================================================
//testBase64.cpp
//一个简单的base64_encode编码函数例子,和测试框架
#include <time.h>
#include <iostream>
#include <vector>
#include <string>

// 3x8bit to 4x6bit
// |----------------------|----------------------|----------------------|
// | a[0..7] | b[0..7] | c[0..7] |
// |----------------------|----------------------|----------------------|
//
// |----------------------|----------------------|----------------------|----------------------|
// | a[2..7] | b[4..7] + a[0..1]<<4 | c[6..7] + b[0..3]<<2 | c[0..5] |
// |----------------------|----------------------|----------------------|----------------------|

const unsigned char BASE64_PADDING='='; //输入数据不足3的倍数时 输出字符后面填充'='号


inline unsigned char to_base64char(const unsigned char code6bit)
{
if (code6bit<26) //[ 0..25] => ['A'..'Z']
return code6bit+'A';
else if (code6bit<52) //[26..51] => ['a'..'z']
return code6bit+('a'-26);
else if (code6bit<62) //[52..61] => ['0'..'9']
return code6bit+('0'-52);
else if (code6bit==62) //62 => '+'
return '+';
else //if (code6bit==63) //63 => '/'
return '/';
}

void base64_encode(const void* pdata,const unsigned long data_size,void* out_pcode)
{
if (data_size<=0) return;
const unsigned char* input=(const unsigned char*)pdata;
const unsigned char* input_end=&input[data_size];
unsigned char* output=(unsigned char*)out_pcode;

const unsigned char* input_end_sub_2=input_end-2;
for(;input<input_end_sub_2;input+=3,output+=4)
{
output[0]=to_base64char(input[0]/4);
output[1]=to_base64char(input[0]%4*16 + input[1]/16);
output[2]=to_base64char(input[1]%16*4 + input[2]/64);
output[3]=to_base64char(input[2]%64);
}

unsigned long bord_width=input_end-input;
if (bord_width==1)
{
output[0]=to_base64char(input[0]/4);
output[1]=to_base64char(input[0]%4*16);
output[2]=BASE64_PADDING;
output[3]=BASE64_PADDING;
}
else if (bord_width==2)
{
output[0]=to_base64char(input[0]/4);
output[1]=to_base64char(input[0]%4*16 + input[1]/16);
output[2]=to_base64char(input[1]%16*4);
output[3]=BASE64_PADDING;
}
}


typedef void (*Tbase64_encode_proc)(const void* pdata,const unsigned long data_size,void* out_pcode);

inline unsigned long base64_code_size(const unsigned long data_size)
{
return (data_size+2)/3*4;
}


void testSpeed(const char* proc_name_str,Tbase64_encode_proc base64_encode,const long DATA_SIZE)
{
std::cout<<">> 编码函数: "<<proc_name_str<<std::endl;

const long DATA_SIZE_MAX=DATA_SIZE+12;

std::vector<unsigned char> data_buf(DATA_SIZE_MAX); //data_buf保存需要编码的数据
for (long r=0;r<DATA_SIZE_MAX;++r)
data_buf[r]=rand(); //data_buf填充随机数据 用以测试

const long code_size_MAX=base64_code_size(DATA_SIZE_MAX);
std::string code_str;//code_str用以储存编码后的字符串数据
code_str.resize(code_size_MAX,' ');

long RunCount=0;
double SumSpeed=0;
for (long data_size=DATA_SIZE;data_size<DATA_SIZE_MAX;++data_size)
{

const long code_size=base64_code_size(data_size);
double start_time=(double)clock();

base64_encode(&data_buf[0],data_size,&code_str[0]);//编码测试

double run_time=((double)clock()-start_time)*(1.0/CLOCKS_PER_SEC);

double encode_speed=code_size*(1.0/1024/1024)/run_time;//编码速度(MB/秒)
++RunCount;
SumSpeed+=encode_speed;

std::cout<<" 编码前数据大小(MB): "<<data_size*(1.0/1024/1024)<<" 编码速度(MB/秒): "<<encode_speed<<std::endl;
//if (data_size<=1000) std::cout<<code_str<<std::endl; //
}
std::cout<<std::endl<<" 平均编码速度(MB/秒): "<<SumSpeed/RunCount<<std::endl;
std::cout<<std::endl;

}

int main()
{
std::cout<<" 请输入任意字符开始测试(可以把进程优先级设置为“实时”)> ";
getchar();
std::cout<<std::endl;

const long DATA_SIZE=80*1024*1024;

testSpeed("base64_encode" ,base64_encode ,DATA_SIZE);
return 0;
}
===========================================================================


例子的结果说明:
1.测试数据集80MB
2.base64_encode编码函数速度(进程为"实时"优先级): 90.8MB/s
3.CPU: AMD64x2 3600+(2.01G); 内存: DDR2 667(334.9MHz); 语言:C++; 编译器:VC2005


为了便于查看和讨论,请移步到 “ http://community.csdn.net/Expert/topic/5665/5665480.xml?temp=.9847528 ” 查看或发帖
...全文
417 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
housisong 2007-07-31
  • 打赏
  • 举报
回复
"千分求最快的Base64编码函数"的帖子已经好久没有新帖,开贴目的也已经基本达到,所以结贴
《千分求最快的Base64编码函数》帖子参见:
http://community.csdn.net/Expert/topic/5665/5665480.xml?temp=.3156092
http://community.csdn.net/Expert/topic/5665/5665503.xml?temp=.4164087
http://community.csdn.net/Expert/topic/5665/5665498.xml?temp=.3687403

谢谢大家的参与,1千分的分配:

maozefa(阿发伯) --150
cczlp(不惑) --100
ERR0RC0DE() --150
DelphiGuy() --150
zyl910(编程的乐趣在于编程控制硬件,与用图形学实现绚丽效果) --150
constantine(飘遥的安吉儿) -- 40
SafeF8(A++.NET) -- 75
beelzebub918(ww) -- 10
unsigned(僵哥(发站内消息,请附上链接或问题说明,否则不予回复)) -- 15
cheer2008() -- 75
mLee79() -- 10
quark(夸克) -- 75



cczlp(不惑) 领分请到:
http://community.csdn.net/Expert/topic/5686/5686121.xml?temp=.2338526
maozefa(阿发伯) 领分请到:
http://community.csdn.net/Expert/topic/5686/5686126.xml?temp=.8005335
http://community.csdn.net/Expert/topic/5686/5686128.xml?temp=5.535525E-02
ERR0RC0DE() 领分请到:
http://community.csdn.net/Expert/topic/5686/5686136.xml?temp=.3937189
http://community.csdn.net/Expert/topic/5686/5686137.xml?temp=.6492426
DelphiGuy() 领分请到:
http://community.csdn.net/Expert/topic/5686/5686138.xml?temp=.3677179
http://community.csdn.net/Expert/topic/5686/5686139.xml?temp=.565838
zyl910 领分请到:
http://community.csdn.net/Expert/topic/5686/5686140.xml?temp=.2164118
http://community.csdn.net/Expert/topic/5686/5686142.xml?temp=.8785059


我也写了一篇blog文章《代码优化-之-Base64编码函数的极限优化挑战》,
地址: http://blog.csdn.net/housisong/archive/2007/07/27/1711153.aspx
(文章中有源代码下载,欢迎大家提供其测试成绩,我会把结果合并到文章中)
housisong 2007-07-26
  • 打赏
  • 举报
回复
to:cheer2008()
感谢你的参与,测试成绩请到这里察看:
http://community.csdn.net/Expert/topic/5665/5665480.xml?temp=.9847528
cheer2008 2007-07-25
  • 打赏
  • 举报
回复
// base64.cpp - written and placed in the public domain by Wei Dai
#include "stdafx.h"
#include <iostream.h>

#include "base64.h"

static const int MAX_LINE_LENGTH = 72;

static const unsigned char vec[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static const unsigned char padding = '=';

Base64Encoder::Base64Encoder(ostream& str, int lb) :
ostr(str)
{
line_breaks = lb;
inBufSize=0;
lineLength=0;
}

void Base64Encoder::LineBreak()
{
ostr << '\n';
lineLength=0;
}

void Base64Encoder::EncodeQuantum()
{
unsigned char out;

out=(unsigned char)((inBuf[0] & 0xFC) >> 2);
ostr << vec[out];

out=(unsigned char)(((inBuf[0] & 0x03) << 4) | (inBuf[1] >> 4));
ostr << vec[out];

out=(unsigned char)(((inBuf[1] & 0x0F) << 2) | (inBuf[2] >> 6));
ostr << (inBufSize > 1 ? vec[out] : padding);

out=(unsigned char)(inBuf[2] & 0x3F);
ostr << (inBufSize > 2 ? vec[out] : padding);

inBufSize=0;
lineLength+=4;

if (line_breaks && (lineLength>=MAX_LINE_LENGTH))
LineBreak();
}

void Base64Encoder::Put(unsigned char inByte)
{
inBuf[inBufSize++]=inByte;
if (inBufSize==3)
EncodeQuantum();
}

void Base64Encoder::Put(const unsigned char* inString, unsigned int len)
{
while (len--)
Base64Encoder::Put(*inString++);
}

void Base64Encoder::InputFinished()
{
if (inBufSize)
{
for (int i=inBufSize;i<3;i++)
inBuf[i]=0;

EncodeQuantum();
}

if (lineLength) // force a line break unless the current line is empty
LineBreak();
}

Base64Decoder::Base64Decoder(ostream& str) :
ostr(str)
{
inBufSize=0;
}

void Base64Decoder::DecodeQuantum()
{
unsigned char out;

out = (unsigned char)((inBuf[0] << 2) | (inBuf[1] >> 4));
ostr << out;

out = (unsigned char)((inBuf[1] << 4) | (inBuf[2] >> 2));
if (inBufSize > 2) ostr << out;

out = (unsigned char)((inBuf[2] << 6) | inBuf[3]);
if (inBufSize > 3) ostr << out;

inBufSize=0;
}

int Base64Decoder::ConvToNumber(unsigned char inByte)
{
if (inByte >= 'A' && inByte <= 'Z')
return (inByte - 'A');

if (inByte >= 'a' && inByte <= 'z')
return (inByte - 'a' + 26);

if (inByte >= '0' && inByte <= '9')
return (inByte - '0' + 52);

if (inByte == '+')
return (62);

if (inByte == '/')
return (63);

return (-1);
}

void Base64Decoder::Put(unsigned char inByte)
{
int i=ConvToNumber(inByte);
if (i >= 0)
inBuf[inBufSize++]=(unsigned char) i;
if (inBufSize==4)
DecodeQuantum();
}

void Base64Decoder::Put(const unsigned char* inString, unsigned int len)
{

while (len--)
Base64Decoder::Put(*inString++);
}

void Base64Decoder::InputFinished()
{
if (inBufSize)
{
for (int i=inBufSize;i<4;i++)
inBuf[i]=0;

DecodeQuantum();
}
}


-------------------------------------------------------------------------

#ifndef BASE64_H
#define BASE64_H


class ostream;

class Base64Encoder
{
public:

Base64Encoder(ostream&, int line_breaks = 1);

void Put(const unsigned char* inString, unsigned int length);
void InputFinished();

private:

void Put(unsigned char inByte);
void LineBreak();
void EncodeQuantum();

int line_breaks;
int inBufSize;
int lineLength;
unsigned char inBuf[3];
ostream& ostr;
};

class Base64Decoder
{
public:

Base64Decoder(ostream&);

void Put(const unsigned char* inString, unsigned int length);
void InputFinished();

private:

static int ConvToNumber(unsigned char inByte);
void DecodeQuantum();
void Put(unsigned char inByte);

int inBufSize;
unsigned char inBuf[4];
ostream& ostr;
};

#endif



housisong 2007-07-21
  • 打赏
  • 举报
回复
to: emptyness(问题事小,结帐事大~)
毕业几年了,上大学的时候注册的csdn帐号,很少问问题,所以可用分都没有怎么用;
>>引用"上万都没散过,那岂不是很不厚道?" 这次不就是散分吗?:D

to:unsigned(僵哥(发站内消息,请附上链接或问题说明,否则不予回复))
>>引用"采用多线程并行运算" 这个问题并行肯定能成倍提高,而且很容易把算法改成并行
模式; 如果已经有了串行函数版本,在我的测试环境下只要加一行代码(把函数地址当作参数填入)就能测试其多核并行后的成绩;所以测试成绩大家给串行的结果就可以了.

to: beelzebub918(ww)
没有测试结果或源代码 我不好送分啊

to: cczlp(不惑)
期待
housisong 2007-07-20
  • 打赏
  • 举报
回复
为了便于查看和讨论,请移步到 “ http://community.csdn.net/Expert/topic/5665/5665480.xml?temp=.9847528 ” 查看或发帖
cczlp 2007-07-20
  • 打赏
  • 举报
回复
mark一下, 有时间就来拿个第一.
emptyness 2007-07-20
  • 打赏
  • 举报
回复
可用分上万??? 难道他已注册了十几年了...
再说上万都没散过,那岂不是很不厚道? 呵呵.
兴趣不大,能力有限,路过..
Jackie 2007-07-20
  • 打赏
  • 举报
回复
atl源代码里面有的
i_love_pc 2007-07-20
  • 打赏
  • 举报
回复
我是为了上万的可用分来的!
僵哥 2007-07-20
  • 打赏
  • 举报
回复
要想快,最好是能采用多线程并行运算

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧