Created
February 13, 2025 04:02
-
-
Save msg7086/f0cf87f73b4e4affa5e02a4f7c2973f4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <inttypes.h> | |
#include <time.h> | |
#include "../common/lwindex_sscanf_unrolled.h" | |
#define ASSERT_EQ(a, b) \ | |
if (a != b) { \ | |
printf("Test failed: %s expected %d, got %d\n", #a, b, a); \ | |
assert(a == b); \ | |
return; \ | |
} | |
static void test_main_index(void) { | |
// Test normal case | |
{ | |
int stream_index = 0; | |
int64_t pos = 0, pts = 0, dts = 0; | |
int extradata_index = 0; | |
const char *input = "Index=1,POS=1000,PTS=2000,DTS=1900,EDI=5"; | |
int result = sscanf_unrolled_main_index(input, &stream_index, &pos, &pts, &dts, &extradata_index); | |
ASSERT_EQ(result, 5); | |
ASSERT_EQ(stream_index, 1); | |
ASSERT_EQ(pos, 1000); | |
ASSERT_EQ(pts, 2000); | |
ASSERT_EQ(dts, 1900); | |
ASSERT_EQ(extradata_index, 5); | |
} | |
// Test invalid format | |
{ | |
int stream_index = 0; | |
int64_t pos = 0, pts = 0, dts = 0; | |
int extradata_index = 0; | |
const char *input = "Invalid=1,POS=1000,PTS=2000,DTS=1900,EDI=5"; | |
int result = sscanf_unrolled_main_index(input, &stream_index, &pos, &pts, &dts, &extradata_index); | |
ASSERT_EQ(result, 0); | |
} | |
// Test boundary values | |
{ | |
int stream_index = 0; | |
int64_t pos = 0, pts = 0, dts = 0; | |
int extradata_index = 0; | |
const char *input = "Index=2147483647,POS=9223372036854775807,PTS=0,DTS=-9223372036854775808,EDI=-2147483648"; | |
int result = sscanf_unrolled_main_index(input, &stream_index, &pos, &pts, &dts, &extradata_index); | |
ASSERT_EQ(result, 5); | |
ASSERT_EQ(stream_index, INT_MAX); | |
ASSERT_EQ(pos, LLONG_MAX); | |
ASSERT_EQ(pts, 0); | |
ASSERT_EQ(dts, LLONG_MIN); | |
ASSERT_EQ(extradata_index, INT_MIN); | |
} | |
} | |
static void test_video_index(void) { | |
// Test normal case | |
{ | |
int key = 0, pict_type = 0, poc = 0, repeat_pict = 0, field_info = 0; | |
const char *input = "Key=1,Pic=2,POC=3,Repeat=1,Field=0"; | |
int result = sscanf_unrolled_video_index(input, &key, &pict_type, &poc, &repeat_pict, &field_info); | |
ASSERT_EQ(result, 5); | |
ASSERT_EQ(key, 1); | |
ASSERT_EQ(pict_type, 2); | |
ASSERT_EQ(poc, 3); | |
ASSERT_EQ(repeat_pict, 1); | |
ASSERT_EQ(field_info, 0); | |
} | |
} | |
static void test_audio_index(void) { | |
// Test normal case | |
{ | |
int frame_length = 0; | |
const char *input = "Length=1024"; | |
int result = sscanf_unrolled_audio_index(input, &frame_length); | |
ASSERT_EQ(result, 1); | |
ASSERT_EQ(frame_length, 1024); | |
} | |
} | |
static void test_strto_functions(void) { | |
// Test my_strto_int | |
{ | |
char *endptr; | |
ASSERT_EQ(my_strto_int("123", &endptr), 123); | |
ASSERT_EQ(my_strto_int("-123", &endptr), -123); | |
ASSERT_EQ(my_strto_int("-2147483648", &endptr), INT_MIN); | |
ASSERT_EQ(my_strto_int("2147483647", &endptr), INT_MAX); | |
} | |
// Test my_strto_int64_t | |
{ | |
char *endptr; | |
ASSERT_EQ(my_strto_int64_t("123", &endptr), 123); | |
ASSERT_EQ(my_strto_int64_t("-123", &endptr), -123); | |
ASSERT_EQ(my_strto_int64_t("-9223372036854775808", &endptr), LLONG_MIN); | |
ASSERT_EQ(my_strto_int64_t("9223372036854775807", &endptr), LLONG_MAX); | |
} | |
} | |
// Add original sscanf functions for comparison | |
static int sscanf_original_main_index(const char *input, int *stream_index, int64_t *pos, | |
int64_t *pts, int64_t *dts, int *extradata_index) { | |
return sscanf(input, "Index=%d,POS=%" SCNd64 ",PTS=%" SCNd64 ",DTS=%" SCNd64 ",EDI=%d", | |
stream_index, pos, pts, dts, extradata_index); | |
} | |
static int sscanf_original_video_index(const char *input, int *key, int *pict_type, | |
int *poc, int *repeat_pict, int *field_info) { | |
return sscanf(input, "Key=%d,Pic=%d,POC=%d,Repeat=%d,Field=%d", | |
key, pict_type, poc, repeat_pict, field_info); | |
} | |
static int sscanf_original_audio_index(const char *input, int *frame_length) { | |
return sscanf(input, "Length=%d", frame_length); | |
} | |
static volatile int data = 0; | |
// Benchmark function | |
static void benchmark_parsing(int randomness) { | |
const int ITERATIONS = 2000000ull; | |
clock_t start, end; | |
double cpu_time_used; | |
double ops_original, ops_unrolled; | |
// Test data | |
const char *main_input = randomness == 1 ? "Index=1,POS=100023456,PTS=200023456,DTS=23456,EDI=5" : "Index=1,POS=1000,PTS=2000,DTS=1900,EDI=2"; | |
const char *video_input = randomness == 1 ? "Key=1,Pic=2,POC=3,Repeat=1,Field=0" : "Key=1,Pic=2,POC=3,Repeat=0,Field=0"; | |
const char *audio_input = randomness == 1 ? "Length=1024" : "Length=1000"; | |
// Variables for parsing | |
int stream_index, extradata_index; | |
int64_t pos, pts, dts; | |
int key, pict_type, poc, repeat_pict, field_info; | |
int frame_length; | |
printf("\nPerformance Benchmark (%d iterations):\n", ITERATIONS); | |
printf("----------------------------------------\n"); | |
// Benchmark main index parsing - Original | |
start = clock(); | |
for (int i = 0; i < ITERATIONS; i++) { | |
sscanf_original_main_index(main_input, &stream_index, &pos, &pts, &dts, &extradata_index); | |
data += extradata_index; | |
} | |
end = clock(); | |
ops_original = ITERATIONS * CLOCKS_PER_SEC / ((double) (end - start)); | |
printf("Original main_index: %.2f ops/sec\n", ops_original); | |
// Benchmark main index parsing - Unrolled | |
start = clock(); | |
for (int i = 0; i < ITERATIONS; i++) { | |
sscanf_unrolled_main_index(main_input, &stream_index, &pos, &pts, &dts, &extradata_index); | |
data += extradata_index; | |
} | |
end = clock(); | |
ops_unrolled = ITERATIONS * CLOCKS_PER_SEC / ((double) (end - start)); | |
printf("Unrolled main_index: %.2f ops/sec (%.1fx faster)\n", ops_unrolled, ops_unrolled/ops_original); | |
// Benchmark video index parsing - Original | |
start = clock(); | |
for (int i = 0; i < ITERATIONS; i++) { | |
sscanf_original_video_index(video_input, &key, &pict_type, &poc, &repeat_pict, &field_info); | |
data += repeat_pict; | |
} | |
end = clock(); | |
ops_original = ITERATIONS * CLOCKS_PER_SEC / ((double) (end - start)); | |
printf("Original video_index: %.2f ops/sec\n", ops_original); | |
// Benchmark video index parsing - Unrolled | |
start = clock(); | |
for (int i = 0; i < ITERATIONS; i++) { | |
sscanf_unrolled_video_index(video_input, &key, &pict_type, &poc, &repeat_pict, &field_info); | |
data += repeat_pict; | |
} | |
end = clock(); | |
ops_unrolled = ITERATIONS * CLOCKS_PER_SEC / ((double) (end - start)); | |
printf("Unrolled video_index: %.2f ops/sec (%.1fx faster)\n", ops_unrolled, ops_unrolled/ops_original); | |
// Benchmark audio index parsing - Original | |
start = clock(); | |
for (int i = 0; i < ITERATIONS; i++) { | |
sscanf_original_audio_index(audio_input, &frame_length); | |
data += frame_length; | |
} | |
end = clock(); | |
ops_original = ITERATIONS * CLOCKS_PER_SEC / ((double) (end - start)); | |
printf("Original audio_index: %.2f ops/sec\n", ops_original); | |
// Benchmark audio index parsing - Unrolled | |
start = clock(); | |
for (int i = 0; i < ITERATIONS; i++) { | |
sscanf_unrolled_audio_index(audio_input, &frame_length); | |
data += frame_length; | |
} | |
end = clock(); | |
ops_unrolled = ITERATIONS * CLOCKS_PER_SEC / ((double) (end - start)); | |
printf("Unrolled audio_index: %.2f ops/sec (%.1fx faster)\n", ops_unrolled, ops_unrolled/ops_original); | |
printf("----------------------------------------\n"); | |
} | |
int main(int argc, char **argv) { | |
#if defined(__SSE4_1__) | |
printf("SSE4_1 is defined\n"); | |
#endif | |
#if defined(__ARM_NEON) | |
printf("ARM NEON is defined\n"); | |
#endif | |
// Run normal tests first | |
test_main_index(); | |
test_video_index(); | |
test_audio_index(); | |
test_strto_functions(); | |
printf("All tests passed!\n"); | |
// return 0; | |
// Run performance benchmark | |
benchmark_parsing(argc); | |
return 0; | |
} | |
// x86-64 | |
// gcc -O3 -march=core-avx2 -o test_lwindex_sscanf tests/test_lwindex_sscanf_unrolled.c | |
// arm64 | |
// gcc -O3 -march=armv8-a -o test_lwindex_sscanf tests/test_lwindex_sscanf_unrolled.c |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment