timer fix

This commit is contained in:
goksu 2023-08-29 10:25:11 +03:00
parent f3dfede62f
commit a13ad841db
No known key found for this signature in database
3 changed files with 49 additions and 124 deletions

View File

@ -3,7 +3,7 @@ FTBENCH_DIR = $(TOP_DIR)/src/tools/ftbench
FTBENCH_SRC = $(FTBENCH_DIR)/ftbench.c FTBENCH_SRC = $(FTBENCH_DIR)/ftbench.c
FTBENCH_OBJ = $(OBJ_DIR)/bench.$(SO) FTBENCH_OBJ = $(OBJ_DIR)/bench.$(SO)
FTBENCH_BIN = $(OBJ_DIR)/bench$E FTBENCH_BIN = $(OBJ_DIR)/bench$E
FTBENCH_FLAG ?= -c 550 -w 50 FTBENCH_FLAG ?= -c 750 -w 50
INCLUDES = $(TOP_DIR)/include INCLUDES = $(TOP_DIR)/include
FONTS = $(wildcard $(FTBENCH_DIR)/fonts/*.ttf) FONTS = $(wildcard $(FTBENCH_DIR)/fonts/*.ttf)
BASELINE_DIR = $(OBJ_DIR)/baseline/ BASELINE_DIR = $(OBJ_DIR)/baseline/

View File

@ -66,8 +66,7 @@
typedef int typedef int
(*bcall_t)( btimer_t* timer, (*bcall_t)( FT_Face face,
FT_Face face,
void* user_data ); void* user_data );
@ -260,7 +259,7 @@
#define TIMER_GET( timer ) ( timer )->total #define TIMER_GET( timer ) ( timer )->total
#define TIMER_RESET( timer ) ( timer )->total = 0 #define TIMER_RESET( timer ) ( timer )->total = 0
#define CHUNK_SIZE 100 #define CHUNK_SIZE 50
int compare(const void* a, const void* b) { int compare(const void* a, const void* b) {
if (*(double*)a > *(double*)b) return 1; if (*(double*)a > *(double*)b) return 1;
@ -271,53 +270,44 @@ int compare(const void* a, const void* b) {
static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time, double warmup) { static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time, double warmup) {
int n, done; int n, done;
int total_done = 0; // track total iterations done across all chunks int total_done = 0; // track total iterations done across all chunks
btimer_t timer, elapsed; double total_time = 0.0;
btimer_t timer;
int NUM_CHUNKS = max_iter / CHUNK_SIZE; int NUM_CHUNKS = max_iter / CHUNK_SIZE;
double medians[NUM_CHUNKS]; double medians[NUM_CHUNKS];
double errors[NUM_CHUNKS];
if (test->cache_first) { // Cache and warmup
TIMER_RESET(&timer); if (test->cache_first) {
test->bench(&timer, face, test->user_data); TIMER_START(&timer);
for(int i = 0; i<1+warmup; i++)
test->bench(face, test->user_data);
TIMER_STOP(&timer);
} }
// Initial warm-up
for (n = 0; n < warmup; n++) {
test->bench(&timer, face, test->user_data);
}
printf(" %-25s ", test->title); printf(" %-25s ", test->title);
fflush(stdout); fflush(stdout);
for (int chunk = 0; chunk < NUM_CHUNKS; chunk++) { for (int chunk = 0; chunk < NUM_CHUNKS; chunk++) {
double chunk_results[CHUNK_SIZE];
TIMER_RESET(&timer); TIMER_RESET(&timer);
TIMER_RESET(&elapsed); TIMER_START(&timer);
// Execute a chunk of iterations // Execute a chunk of iterations
for (n = 0, done = 0; n < CHUNK_SIZE; n++) { for (n = 0, done = 0; n < CHUNK_SIZE; n++) {
TIMER_START(&elapsed); done += test->bench(face, test->user_data);
done += test->bench(&timer, face, test->user_data);
TIMER_STOP(&elapsed);
chunk_results[n] = TIMER_GET(&elapsed);
// Check max_time for each iteration, break if exceeded
if (TIMER_GET(&elapsed) > 1E6 * max_time) {
break;
}
} }
TIMER_STOP(&timer);
medians[chunk] = TIMER_GET(&timer);
total_time += medians[chunk];
total_done += done; total_done += done;
qsort(chunk_results, CHUNK_SIZE, sizeof(double), compare); // Check max_time for each iteration, break if exceeded
if (CHUNK_SIZE % 2 == 0) { if (total_time > 1E6 * max_time)
medians[chunk] = (chunk_results[CHUNK_SIZE / 2 - 1] + chunk_results[CHUNK_SIZE / 2]) / 2.0; break;
} else {
medians[chunk] = chunk_results[CHUNK_SIZE / 2];
}
errors[chunk] = chunk_results[91 * CHUNK_SIZE / 100] - chunk_results[10 * CHUNK_SIZE / 100];
} }
qsort(medians, NUM_CHUNKS, sizeof(double), compare); qsort(medians, NUM_CHUNKS, sizeof(double), compare);
double final_median; double final_median;
if (NUM_CHUNKS % 2 == 0) { if (NUM_CHUNKS % 2 == 0) {
@ -326,7 +316,7 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
final_median = medians[NUM_CHUNKS / 2]; final_median = medians[NUM_CHUNKS / 2];
} }
printf("%10.1f microseconds %10d done\n", final_median, total_done); printf("%10.1f microseconds %10d done\n", final_median/CHUNK_SIZE, total_done);
} }
/* /*
@ -334,8 +324,7 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
*/ */
static int static int
test_load( btimer_t* timer, test_load( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
int i, done = 0; int i, done = 0;
@ -343,23 +332,18 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
FT_UNUSED( user_data ); FT_UNUSED( user_data );
TIMER_START( timer );
FOREACH( i ) FOREACH( i )
{ {
if ( !FT_Load_Glyph( face, (FT_UInt)i, load_flags ) ) if ( !FT_Load_Glyph( face, (FT_UInt)i, load_flags ) )
done++; done++;
} }
TIMER_STOP( timer );
return done; return done;
} }
static int static int
test_load_advances( btimer_t* timer, test_load_advances( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
int done = 0; int done = 0;
@ -381,15 +365,11 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
advances = (FT_Fixed *)calloc( sizeof ( FT_Fixed ), (size_t)count ); advances = (FT_Fixed *)calloc( sizeof ( FT_Fixed ), (size_t)count );
TIMER_START( timer );
FT_Get_Advances( face, FT_Get_Advances( face,
(FT_UInt)start, (FT_UInt)count, (FT_UInt)start, (FT_UInt)count,
(FT_Int32)flags, advances ); (FT_Int32)flags, advances );
done += (int)count; done += (int)count;
TIMER_STOP( timer );
free( advances ); free( advances );
return done; return done;
@ -397,8 +377,7 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
static int static int
test_render( btimer_t* timer, test_render( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
int i, done = 0; int i, done = 0;
@ -411,10 +390,8 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
if ( FT_Load_Glyph( face, (FT_UInt)i, load_flags ) ) if ( FT_Load_Glyph( face, (FT_UInt)i, load_flags ) )
continue; continue;
TIMER_START( timer );
if ( !FT_Render_Glyph( face->glyph, render_mode ) ) if ( !FT_Render_Glyph( face->glyph, render_mode ) )
done++; done++;
TIMER_STOP( timer );
} }
return done; return done;
@ -422,8 +399,7 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
static int static int
test_embolden( btimer_t* timer, test_embolden( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
int i, done = 0; int i, done = 0;
@ -436,10 +412,8 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
if ( FT_Load_Glyph( face, (FT_UInt)i, load_flags ) ) if ( FT_Load_Glyph( face, (FT_UInt)i, load_flags ) )
continue; continue;
TIMER_START( timer );
FT_GlyphSlot_Embolden( face->glyph ); FT_GlyphSlot_Embolden( face->glyph );
done++; done++;
TIMER_STOP( timer );
} }
return done; return done;
@ -447,8 +421,7 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
static int static int
test_stroke( btimer_t* timer, test_stroke( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
FT_Glyph glyph; FT_Glyph glyph;
@ -472,9 +445,7 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
FT_Get_Glyph( face->glyph, &glyph ) ) FT_Get_Glyph( face->glyph, &glyph ) )
continue; continue;
TIMER_START( timer );
FT_Glyph_Stroke( &glyph, stroker, 1 ); FT_Glyph_Stroke( &glyph, stroker, 1 );
TIMER_STOP( timer );
FT_Done_Glyph( glyph ); FT_Done_Glyph( glyph );
done++; done++;
@ -487,8 +458,7 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
static int static int
test_get_glyph( btimer_t* timer, test_get_glyph( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
FT_Glyph glyph; FT_Glyph glyph;
@ -503,13 +473,11 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
if ( FT_Load_Glyph( face, (FT_UInt)i, load_flags ) ) if ( FT_Load_Glyph( face, (FT_UInt)i, load_flags ) )
continue; continue;
TIMER_START( timer );
if ( !FT_Get_Glyph( face->glyph, &glyph ) ) if ( !FT_Get_Glyph( face->glyph, &glyph ) )
{ {
FT_Done_Glyph( glyph ); FT_Done_Glyph( glyph );
done++; done++;
} }
TIMER_STOP( timer );
} }
return done; return done;
@ -517,8 +485,7 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
static int static int
test_get_cbox( btimer_t* timer, test_get_cbox( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
FT_Glyph glyph; FT_Glyph glyph;
@ -537,10 +504,8 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
if ( FT_Get_Glyph( face->glyph, &glyph ) ) if ( FT_Get_Glyph( face->glyph, &glyph ) )
continue; continue;
TIMER_START( timer );
FT_Glyph_Get_CBox( glyph, FT_GLYPH_BBOX_PIXELS, &bbox ); FT_Glyph_Get_CBox( glyph, FT_GLYPH_BBOX_PIXELS, &bbox );
TIMER_STOP( timer );
FT_Done_Glyph( glyph ); FT_Done_Glyph( glyph );
done++; done++;
} }
@ -550,8 +515,7 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
static int static int
test_get_bbox( btimer_t* timer, test_get_bbox( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
FT_BBox bbox; FT_BBox bbox;
@ -566,9 +530,7 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
if ( FT_Load_Glyph( face, (FT_UInt)i, load_flags ) ) if ( FT_Load_Glyph( face, (FT_UInt)i, load_flags ) )
continue; continue;
TIMER_START( timer );
FT_Outline_Get_BBox( &face->glyph->outline, &bbox ); FT_Outline_Get_BBox( &face->glyph->outline, &bbox );
TIMER_STOP( timer );
done++; done++;
} }
@ -578,31 +540,25 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
static int static int
test_get_char_index( btimer_t* timer, test_get_char_index( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
bcharset_t* charset = (bcharset_t*)user_data; bcharset_t* charset = (bcharset_t*)user_data;
int i, done = 0; int i, done = 0;
TIMER_START( timer );
for ( i = 0; i < charset->size; i++ ) for ( i = 0; i < charset->size; i++ )
{ {
if ( FT_Get_Char_Index(face, charset->code[i]) ) if ( FT_Get_Char_Index(face, charset->code[i]) )
done++; done++;
} }
TIMER_STOP( timer );
return done; return done;
} }
static int static int
test_cmap_cache( btimer_t* timer, test_cmap_cache( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
bcharset_t* charset = (bcharset_t*)user_data; bcharset_t* charset = (bcharset_t*)user_data;
@ -611,8 +567,6 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
FT_UNUSED( face ); FT_UNUSED( face );
TIMER_START( timer );
for ( i = 0; i < charset->size; i++ ) for ( i = 0; i < charset->size; i++ )
{ {
if ( FTC_CMapCache_Lookup( cmap_cache, if ( FTC_CMapCache_Lookup( cmap_cache,
@ -622,15 +576,12 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
done++; done++;
} }
TIMER_STOP( timer );
return done; return done;
} }
static int static int
test_image_cache( btimer_t* timer, test_image_cache( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
FT_Glyph glyph; FT_Glyph glyph;
@ -640,9 +591,6 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
FT_UNUSED( face ); FT_UNUSED( face );
FT_UNUSED( user_data ); FT_UNUSED( user_data );
TIMER_START( timer );
FOREACH( i ) FOREACH( i )
{ {
if ( !FTC_ImageCache_Lookup( image_cache, if ( !FTC_ImageCache_Lookup( image_cache,
@ -653,15 +601,12 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
done++; done++;
} }
TIMER_STOP( timer );
return done; return done;
} }
static int static int
test_sbit_cache( btimer_t* timer, test_sbit_cache( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
FTC_SBit glyph; FTC_SBit glyph;
@ -671,9 +616,6 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
FT_UNUSED( face ); FT_UNUSED( face );
FT_UNUSED( user_data ); FT_UNUSED( user_data );
TIMER_START( timer );
FOREACH( i ) FOREACH( i )
{ {
if ( !FTC_SBitCache_Lookup( sbit_cache, if ( !FTC_SBitCache_Lookup( sbit_cache,
@ -684,15 +626,12 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
done++; done++;
} }
TIMER_STOP( timer );
return done; return done;
} }
static int static int
test_cmap_iter( btimer_t* timer, test_cmap_iter( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
FT_UInt idx; FT_UInt idx;
@ -702,23 +641,18 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
FT_UNUSED( user_data ); FT_UNUSED( user_data );
TIMER_START( timer );
charcode = FT_Get_First_Char( face, &idx ); charcode = FT_Get_First_Char( face, &idx );
done = ( idx != 0 ); done = ( idx != 0 );
while ( idx != 0 ) while ( idx != 0 )
charcode = FT_Get_Next_Char( face, charcode, &idx ); charcode = FT_Get_Next_Char( face, charcode, &idx );
TIMER_STOP( timer );
return done; return done;
} }
static int static int
test_new_face( btimer_t* timer, test_new_face( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
FT_Face bench_face; FT_Face bench_face;
@ -727,20 +661,15 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
FT_UNUSED( user_data ); FT_UNUSED( user_data );
TIMER_START( timer );
if ( !get_face( &bench_face ) ) if ( !get_face( &bench_face ) )
FT_Done_Face( bench_face ); FT_Done_Face( bench_face );
TIMER_STOP( timer );
return 1; return 1;
} }
static int static int
test_new_face_and_load_glyph( btimer_t* timer, test_new_face_and_load_glyph( FT_Face face,
FT_Face face,
void* user_data ) void* user_data )
{ {
FT_Face bench_face; FT_Face bench_face;
@ -751,8 +680,6 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
FT_UNUSED( user_data ); FT_UNUSED( user_data );
TIMER_START( timer );
if ( !get_face( &bench_face ) ) if ( !get_face( &bench_face ) )
{ {
FOREACH( i ) FOREACH( i )
@ -764,8 +691,6 @@ static void benchmark(FT_Face face, btest_t* test, int max_iter, double max_time
FT_Done_Face( bench_face ); FT_Done_Face( bench_face );
} }
TIMER_STOP( timer );
return done; return done;
} }

View File

@ -108,7 +108,7 @@ def generate_info_table(html_file, baseline_info, benchmark_info):
), ),
) )
write_to_html(html_file, "</table><br/>") write_to_html(html_file, "</table><br/>")
write_to_html(html_file, "<p>* Average time for all iterations. Smaller values are better.</p>") write_to_html(html_file, "<p>* Average time for single iteration. Smaller values are better.</p>")
write_to_html(html_file, "<p>** N count in (x | y) format is for showing baseline and benchmark N counts seperately when they differs.</p>") write_to_html(html_file, "<p>** N count in (x | y) format is for showing baseline and benchmark N counts seperately when they differs.</p>")
@ -181,8 +181,8 @@ def generate_total_results_table(html_file, baseline_dir, benchmark_dir):
write_to_html( write_to_html(
html_file, html_file,
f'<tr><td class="col1">{test}</td><td>{n_display}</td>\ f'<tr><td class="col1">{test}</td><td>{n_display}</td>\
<td class="{baseline_color}">{baseline:.0f}</td>\ <td class="{baseline_color}">{baseline:.1f}</td>\
<td class="{benchmark_color}">{benchmark:.0f}</td><td>{diff:.1f}</td></tr>\n' <td class="{benchmark_color}">{benchmark:.1f}</td><td>{diff:.1f}</td></tr>\n'
) )
total_diff = ((total_baseline - total_benchmark) / total_baseline) * 100 total_diff = ((total_baseline - total_benchmark) / total_baseline) * 100
@ -191,7 +191,7 @@ def generate_total_results_table(html_file, baseline_dir, benchmark_dir):
write_to_html( write_to_html(
html_file, html_file,
f'<tr><td class="col1">TOTAL</td><td class="col1">{total_n_display}</td>\ f'<tr><td class="col1">TOTAL</td><td class="col1">{total_n_display}</td>\
<td class="col1">{total_baseline:.0f}</td><td class="col1">{total_benchmark:.0f}</td>\ <td class="col1">{total_baseline:.1f}</td><td class="col1">{total_benchmark:.1f}</td>\
<td class="col1">{total_diff:.1f}</td></tr>\n' <td class="col1">{total_diff:.1f}</td></tr>\n'
) )
@ -258,7 +258,7 @@ def generate_results_table(html_file, baseline_results, benchmark_results, filen
write_to_html( write_to_html(
html_file, html_file,
'<tr><td class="col1">{}</td><td>{}</td>\ '<tr><td class="col1">{}</td><td>{}</td>\
<td class="lowlight">{:.0f}</td><td class="highlight">{:.0f}</td><td>{:.1f}</td></tr>\n'.format( <td class="lowlight">{:.1f}</td><td class="highlight">{:.1f}</td><td>{:.1f}</td></tr>\n'.format(
baseline_match.group(1), baseline_match.group(1),
n, n,
baseline_value, baseline_value,
@ -270,7 +270,7 @@ def generate_results_table(html_file, baseline_results, benchmark_results, filen
write_to_html( write_to_html(
html_file, html_file,
'<tr><td class="col1">{}</td><td>{}</td>\ '<tr><td class="col1">{}</td><td>{}</td>\
<td class="highlight">{:.0f}</td><td class="lowlight">{:.0f}</td><td>{:.1f}</td></tr>\n'.format( <td class="highlight">{:.1f}</td><td class="lowlight">{:.1f}</td><td>{:.1f}</td></tr>\n'.format(
baseline_match.group(1), baseline_match.group(1),
n, n,
baseline_value, baseline_value,
@ -282,7 +282,7 @@ def generate_results_table(html_file, baseline_results, benchmark_results, filen
write_to_html( write_to_html(
html_file, html_file,
'<tr><td class="col1">TOTAL</td><td class="col1">{}</td>\ '<tr><td class="col1">TOTAL</td><td class="col1">{}</td>\
<td class="col1">{:.0f}</td><td class="col1">{:.0f}</td><td class="col1">{:.1f}</td></tr>\n'.format( <td class="col1">{:.1f}</td><td class="col1">{:.1f}</td><td class="col1">{:.1f}</td></tr>\n'.format(
total_n, total_time_baseline, total_time_benchmark, (total_time_baseline - total_time_benchmark) / total_time_baseline * -100 total_n, total_time_baseline, total_time_benchmark, (total_time_baseline - total_time_benchmark) / total_time_baseline * -100
), ),
) )