Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/test/benchmark/base64.c
4130 views
1
// Copyright 2017 The Emscripten Authors. All rights reserved.
2
// Emscripten is available under two separate licenses, the MIT license and the
3
// University of Illinois/NCSA Open Source License. Both these licenses can be
4
// found in the LICENSE file.
5
6
// https://github.com/kostya/benchmarks/blob/master/base64/test.c
7
8
#include "stdlib.h"
9
#include "stdio.h"
10
#include "time.h"
11
#include <stdint.h>
12
13
typedef unsigned int uint;
14
const char* chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
15
static char decode_table[256];
16
17
int encode_size(int size) {
18
return (int)(size * 4 / 3.0) + 6;
19
}
20
21
int decode_size(int size) {
22
return (int)(size * 3 / 4.0) + 6;
23
}
24
25
void init_decode_table() {
26
for (int i = 0; i < 256; i++) {
27
char ch = (char)i;
28
char code = -1;
29
if (ch >= 'A' && ch <= 'Z') code = ch - 0x41;
30
if (ch >= 'a' && ch <= 'z') code = ch - 0x47;
31
if (ch >= '0' && ch <= '9') code = ch + 0x04;
32
if (ch == '+' || ch == '-') code = 0x3E;
33
if (ch == '/' || ch == '_') code = 0x3F;
34
decode_table[i] = code;
35
}
36
}
37
38
#define next_char(x) char x = decode_table[(unsigned char)*str++]; if (x < 0) return 1;
39
40
int decode(int size, const char* str, int* out_size, char** output) {
41
*output = (char*) malloc( decode_size(size) );
42
char *out = *output;
43
while (size > 0 && (str[size - 1] == '\n' || str[size - 1] == '\r' || str[size - 1] == '=')) size--;
44
const char* ends = str + size - 4;
45
while (1) {
46
if (str > ends) break;
47
while (*str == '\n' || *str == '\r') str++;
48
49
if (str > ends) break;
50
next_char(a); next_char(b); next_char(c); next_char(d);
51
52
*out++ = (char)(a << 2 | b >> 4);
53
*out++ = (char)(b << 4 | c >> 2);
54
*out++ = (char)(c << 6 | d >> 0);
55
}
56
57
int mod = (str - ends) % 4;
58
if (mod == 2) {
59
next_char(a); next_char(b);
60
*out++ = (char)(a << 2 | b >> 4);
61
} else if (mod == 3) {
62
next_char(a); next_char(b); next_char(c);
63
*out++ = (char)(a << 2 | b >> 4);
64
*out++ = (char)(b << 4 | c >> 2);
65
}
66
67
*out = '\0';
68
*out_size = out - *output;
69
return 0;
70
}
71
72
void encode(int size, const char* str, int* out_size, char** output) {
73
*output = (char*) malloc( encode_size(size) );
74
char *out = *output;
75
const char* ends = str + (size - size % 3);
76
uint n;
77
while (str != ends) {
78
uint32_t n = __builtin_bswap32(*(uint32_t*)str);
79
*out++ = chars[(n >> 26) & 63];
80
*out++ = chars[(n >> 20) & 63];
81
*out++ = chars[(n >> 14) & 63];
82
*out++ = chars[(n >> 8) & 63];
83
str += 3;
84
}
85
int pd = size % 3;
86
if (pd == 1) {
87
n = (uint)*str << 16;
88
*out++ = chars[(n >> 18) & 63];
89
*out++ = chars[(n >> 12) & 63];
90
*out++ = '=';
91
*out++ = '=';
92
} else if (pd == 2) {
93
n = (uint)*str++ << 16;
94
n |= (uint)*str << 8;
95
*out++ = chars[(n >> 18) & 63];
96
*out++ = chars[(n >> 12) & 63];
97
*out++ = chars[(n >> 6) & 63];
98
*out++ = '=';
99
}
100
*out = '\0';
101
*out_size = out - *output;
102
}
103
104
int main(int argc, char **argv) {
105
int TRIES;
106
107
int arg = argc > 1 ? argv[1][0] - '0' : 3;
108
switch(arg) {
109
case 0: return 0; break;
110
case 1: TRIES = 3; break;
111
case 2: TRIES = 15; break;
112
case 3: TRIES = 25; break;
113
case 4: TRIES = 50; break;
114
case 5: TRIES = 100; break;
115
default: printf("error: %d\\n", arg); return -1;
116
}
117
118
init_decode_table();
119
120
const int STR_SIZE = 10000000;
121
122
char *str = (char*) malloc(STR_SIZE + 1);
123
for (int i = 0; i < STR_SIZE; i++) { str[i] = 'a'; }
124
str[STR_SIZE] = '\0';
125
126
int s = 0;
127
clock_t t = clock();
128
for (int i = 0; i < TRIES; i++) {
129
char *str2;
130
int str2_size;
131
encode(STR_SIZE, str, &str2_size, &str2);
132
s += str2_size;
133
free(str2);
134
}
135
printf("encode: %d, %.2f\n", s, (float)(clock() - t)/CLOCKS_PER_SEC);
136
137
char *str2;
138
int str2_size;
139
encode(STR_SIZE, str, &str2_size, &str2);
140
141
s = 0;
142
t = clock();
143
for (int i = 0; i < TRIES; i++) {
144
char *str3;
145
int str3_size;
146
if (decode(str2_size, str2, &str3_size, &str3) != 0) {
147
printf("error when decoding");
148
}
149
s += str3_size;
150
free(str3);
151
}
152
printf("decode: %d, %.2f\n", s, (float)(clock() - t)/CLOCKS_PER_SEC);
153
return 0;
154
}
155
156