Skip to content

Commit

Permalink
Implement benchmarking heatshrink
Browse files Browse the repository at this point in the history
  • Loading branch information
kripton committed Jun 7, 2021
1 parent 82221f8 commit ddb51b9
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 4 deletions.
9 changes: 9 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,18 @@ include(../lib/heatshrink/CMakeLists.txt)
## Sorted alphabetically
add_executable(${CMAKE_PROJECT_NAME}
${TINYUSB_LIBNETWORKING_SOURCES}
algo-heatshrink.c
main.c
)

## Config for the heatshrink library
target_compile_definitions(${CMAKE_PROJECT_NAME}
PUBLIC HEATSHRINK_DYNAMIC_ALLOC=0
PUBLIC HEATSHRINK_STATIC_INPUT_BUFFER_SIZE=600
PUBLIC HEATSHRINK_STATIC_WINDOW_BITS=9
PUBLIC HEATSHRINK_STATIC_LOOKAHEAD_BITS=6
)

## Needed so tusb_config.h is found by the tinyUSB-library included in the pico-sdk
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}
Expand Down
42 changes: 42 additions & 0 deletions src/algo-heatshrink.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "algo-heatshrink.h"

#include "../lib/heatshrink/heatshrink_common.h"
#include "../lib/heatshrink/heatshrink_encoder.h"
#include "../lib/heatshrink/heatshrink_decoder.h"

static heatshrink_decoder dec;
static heatshrink_encoder enc;

void heatshrink_init()
{
heatshrink_decoder_reset(&dec);
heatshrink_encoder_reset(&enc);
}

void heatshrink_compress(uint8_t *input, size_t insize, uint8_t *output, size_t *outsize)
{
heatshrink_encoder_reset(&enc);

size_t sunk = 0;
size_t polled = 0;
size_t count = 0;
size_t comp_sz = *outsize;
while (sunk < insize) {
heatshrink_encoder_sink(&enc, &input[sunk], insize - sunk, &count);
sunk += count;
if (sunk == insize) {
heatshrink_encoder_finish(&enc);
}

HSE_poll_res pres;
do {
pres = heatshrink_encoder_poll(&enc, &output[polled], comp_sz - polled, &count);
polled += count;
} while (pres == HSER_POLL_MORE);
if (sunk == insize) {
heatshrink_encoder_finish(&enc);
}
}

*outsize = polled;
}
9 changes: 9 additions & 0 deletions src/algo-heatshrink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef __ALGO_HEATSHRINK_H__
#define __ALGO_HEATSHRINK_H__

#include "pico/stdlib.h"

void heatshrink_init();
void heatshrink_compress(uint8_t* input, size_t insize, uint8_t* output, size_t* outsize);

#endif // __ALGO_HEATSHRINK_H__
67 changes: 63 additions & 4 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@

#include "picotool_binary_information.h"

#include "algo-heatshrink.h"


// TEST VECTORS
struct testVec {
uint8_t name[32]; // Human-readable name
uint8_t data[512];
uint8_t name[32]; // Human-readable name
size_t size;
uint8_t data[512];
};

enum {
Expand Down Expand Up @@ -45,12 +48,18 @@ enum {
ALGO_NUM_TOTAL
};

struct algo algos[ALGO_NUM_TOTAL];

// Variables used for elapsed time calculation
uint32_t start_time, finish_time, elapsed_time;

uint16_t i;
uint8_t j;

// Buffer to store compressed data
#define OUTBUF_SIZE 1024
uint8_t outbuf[OUTBUF_SIZE];

int main() {
// Overclock the board to 250MHz. According to
// https://www.youtube.com/watch?v=G2BuoFNLo this should be
Expand All @@ -75,14 +84,17 @@ int main() {

// Test vector 0: All zeroes
sprintf(testvecs[TESTVEC_ALL_ZERO].name, "ALL_ZERO");
testvecs[TESTVEC_ALL_ZERO].size = 512;
memset(testvecs[TESTVEC_ALL_ZERO].data, 0, 512);

// Test vector 1: All ones
sprintf(testvecs[TESTVEC_ALL_ONE].name, "TESTVEC_ALL_ONE");
sprintf(testvecs[TESTVEC_ALL_ONE].name, "ALL_ONE");
testvecs[TESTVEC_ALL_ONE].size = 512;
memset(testvecs[TESTVEC_ALL_ONE].data, 0xff, 512);

// Test vector 2: Very small sawtooth: 0, 127, 255, 0, ....
sprintf(testvecs[TESTVEC_SAWTOOTH_SMALL].name, "SAWTOOTH_SMALL");
testvecs[TESTVEC_SAWTOOTH_SMALL].size = 512;
j = 0;
for (i = 0; i < 512; i++) {
testvecs[TESTVEC_SAWTOOTH_SMALL].data[i] = j;
Expand All @@ -91,6 +103,7 @@ int main() {

// Test vector 3: Medium sawtooth: Increases by 16
sprintf(testvecs[TESTVEC_SAWTOOTH_MEDIUM].name, "SAWTOOTH_MEDIUM");
testvecs[TESTVEC_SAWTOOTH_MEDIUM].size = 512;
j = 0;
for (i = 0; i < 512; i++) {
testvecs[TESTVEC_SAWTOOTH_MEDIUM].data[i] = j;
Expand All @@ -99,6 +112,7 @@ int main() {

// Test vector 4: Large sawtooth: Increases by 4
sprintf(testvecs[TESTVEC_SAWTOOTH_LARGE].name, "SAWTOOTH_LARGE");
testvecs[TESTVEC_SAWTOOTH_LARGE].size = 512;
j = 0;
for (i = 0; i < 512; i++) {
testvecs[TESTVEC_SAWTOOTH_LARGE].data[i] = j;
Expand All @@ -107,13 +121,15 @@ int main() {

// Test vector 5: All random
sprintf(testvecs[TESTVEC_ALL_RANDOM].name, "ALL_RANDOM");
testvecs[TESTVEC_ALL_RANDOM].size = 512;
j = 0;
for (i = 0; i < 512; i++) {
testvecs[TESTVEC_ALL_RANDOM].data[i] = rand();
}

// Test vector 6: Random, zero, random, zero, random, ...
sprintf(testvecs[TESTVEC_ALTERNATING_RANDOM_ZERO].name, "ALTERNATING_RANDOM_ZERO");
testvecs[TESTVEC_ALTERNATING_RANDOM_ZERO].size = 512;
j = 0;
memset(testvecs[TESTVEC_ALTERNATING_RANDOM_ZERO].data, 0, 512);
for (i = 0; i < 512; i++) {
Expand All @@ -123,6 +139,7 @@ int main() {

// Test vector 7: 8 times random, 8 times zero, 8 times random, ...
sprintf(testvecs[TESTVEC_BLOCKS_8RANDOM_8ZERO].name, "BLOCKS_8RANDOM_8ZERO");
testvecs[TESTVEC_BLOCKS_8RANDOM_8ZERO].size = 512;
j = 0;
memset(testvecs[TESTVEC_BLOCKS_8RANDOM_8ZERO].data, 0, 512);
for (i = 0; i < 512; i++) {
Expand All @@ -133,10 +150,52 @@ int main() {

finish_time = time_us_32();
elapsed_time = finish_time - start_time;
printf("%lu us\n", elapsed_time);
printf("%luµs\n", elapsed_time);

printf("%d test vectors:\n", TESTVEC_NUM_TOTAL);
for (i = 0; i < TESTVEC_NUM_TOTAL; i++) {
printf("\t%s\n", testvecs[i].name);
}
printf("\n");

////////////////////////////////////////////////////
// INIT ALGORITHMS /////////////////////////////////
////////////////////////////////////////////////////
printf("Initializing compression algorithms ... ");
start_time = time_us_32();

// Algo 0: heatshrink
sprintf(algos[ALGO_HEATSHRINK].name, "HEATSHRINK");
algos[ALGO_HEATSHRINK].init = heatshrink_init;
algos[ALGO_HEATSHRINK].compress = heatshrink_compress;
algos[ALGO_HEATSHRINK].init();

finish_time = time_us_32();
elapsed_time = finish_time - start_time;
printf("%luµs\n", elapsed_time);

printf("%d compression algorithms:\n", ALGO_NUM_TOTAL);
for (i = 0; i < ALGO_NUM_TOTAL; i++) {
printf("\t%s\n", algos[i].name);
}
printf("\n");

////////////////////////////////////////////////////
// Run the benchmark ///////////////////////////////
////////////////////////////////////////////////////
printf("BENCHMARK RUN STARTS HERE ;)\n");
for (i = 0; i < ALGO_NUM_TOTAL; i++) {
printf("\t%s:\n", algos[i].name);
for (j = 0; j < TESTVEC_NUM_TOTAL; j++) {
printf("\t\t%s:\t\t\t", testvecs[j].name);
size_t outsize = OUTBUF_SIZE;
memset(outbuf, 0, OUTBUF_SIZE);
start_time = time_us_32();
algos[i].compress(testvecs[j].data, testvecs[j].size, outbuf, &outsize);
finish_time = time_us_32();
elapsed_time = finish_time - start_time;
float ratio = outsize * 100 / testvecs[j].size;
printf("%luµs; Insize: %u; Outsize: %u, Ratio: %f%%\n", elapsed_time, testvecs[j].size, outsize, ratio);
}
}
};

0 comments on commit ddb51b9

Please sign in to comment.