Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1505 lines (1209 sloc)
49.9 KB
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
| /* | |
| * Mr. 4th Dimention - Allen Webster | |
| * Four Tech | |
| * | |
| * public domain -- no warranty is offered or implied; use this code at your own risk | |
| * | |
| * 06.11.2015 | |
| * | |
| * Buffer experiment testing layer | |
| * | |
| */ | |
| // TOP | |
| #include "4coder_external_name.h" | |
| #include "shared_test_config.cpp" | |
| #ifdef fast_test | |
| #define debug_4tech(x) | |
| #define assert_4tech(x) | |
| #endif | |
| #define hard_assert_4tech(x) assert(x) | |
| #include "4coder_shared.cpp" | |
| #include "4coder_golden_array.cpp" | |
| #include "4coder_gap_buffer.cpp" | |
| #include "4coder_multi_gap_buffer.cpp" | |
| #include "4coder_rope_buffer.cpp" | |
| #define Buffer_Type Buffer | |
| #include "4coder_buffer_abstract.cpp" | |
| #undef Buffer_Type | |
| #define Buffer_Type Gap_Buffer | |
| #include "4coder_buffer_abstract.cpp" | |
| #undef Buffer_Type | |
| #define Buffer_Type Multi_Gap_Buffer | |
| #include "4coder_buffer_abstract.cpp" | |
| #undef Buffer_Type | |
| #define Buffer_Type Rope_Buffer | |
| #include "4coder_buffer_abstract.cpp" | |
| #undef Buffer_Type | |
| #include "shared_test_utils.cpp" | |
| int int_into_str(char *out, int *rem, unsigned int x){ | |
| char *start = out; | |
| int size = *rem; | |
| int result; | |
| char t; | |
| if (x == 0 && size > 1){ | |
| *out = '0'; | |
| ++out; | |
| --size; | |
| } | |
| else{ | |
| for (;x > 0 && size > 1;--size, ++out){ | |
| *out = (x%10 + '0'); | |
| x /= 10; | |
| } | |
| } | |
| *rem = size; | |
| *out = 0; | |
| result = (int)(out - start); | |
| --out; | |
| for (; start < out; ++start, --out){ | |
| t = *out; | |
| *out = *start; | |
| *start = t; | |
| } | |
| return(result); | |
| } | |
| int uscore_into_str(char *out, int *rem){ | |
| int result; | |
| result = 0; | |
| if (*rem > 1){ | |
| --*rem; | |
| *out++ = '_'; | |
| *out = 0; | |
| result = 1; | |
| } | |
| return(result); | |
| } | |
| #if defined(_WIN32) | |
| #include <Windows.h> | |
| typedef unsigned long long time_int; | |
| unsigned long long win32_counts_per_second_4tech; | |
| int time_init(unsigned long long *resolution){ | |
| int result; | |
| LARGE_INTEGER time; | |
| result = 0; | |
| if (QueryPerformanceFrequency(&time)){ | |
| win32_counts_per_second_4tech = (unsigned long long)(time.QuadPart); | |
| result = 1; | |
| *resolution = win32_counts_per_second_4tech; | |
| } | |
| return(result); | |
| } | |
| time_int get_time(){ | |
| LARGE_INTEGER time; | |
| time_int result; | |
| result = 0; | |
| if (QueryPerformanceCounter(&time)){ | |
| result = (time_int)(time.QuadPart); | |
| result = result * 1000000 / win32_counts_per_second_4tech; | |
| } | |
| return(result); | |
| } | |
| void time_into_str(char *out, int max){ | |
| SYSTEMTIME systime; | |
| int pos; | |
| GetSystemTime(&systime); | |
| pos = uscore_into_str(out, &max); | |
| pos += int_into_str(out + pos, &max, systime.wYear); | |
| pos += uscore_into_str(out + pos, &max); | |
| pos += int_into_str(out + pos, &max, systime.wMonth); | |
| pos += uscore_into_str(out + pos, &max); | |
| pos += int_into_str(out + pos, &max, systime.wDay); | |
| pos += uscore_into_str(out + pos, &max); | |
| pos += int_into_str(out + pos, &max, systime.wHour); | |
| pos += uscore_into_str(out + pos, &max); | |
| pos += int_into_str(out + pos, &max, systime.wMinute); | |
| pos += uscore_into_str(out + pos, &max); | |
| pos += int_into_str(out + pos, &max, systime.wSecond); | |
| pos += uscore_into_str(out + pos, &max); | |
| pos += int_into_str(out + pos, &max, systime.wMilliseconds); | |
| } | |
| #elif defined(__linux__) | |
| #include <time.h> | |
| typedef unsigned long long time_int; | |
| int time_init(unsigned long long *resolution){ | |
| int result; | |
| struct timespec res; | |
| result = 0; | |
| if (!clock_getres(CLOCK_MONOTONIC, &res)){ | |
| result = 1; | |
| if (res.tv_sec > 0 || res.tv_nsec == 0) *resolution = 0; | |
| else *resolution = (unsigned long long)(1000000/res.tv_nsec); | |
| } | |
| return(result); | |
| } | |
| time_int get_time(){ | |
| time_int result; | |
| struct timespec time; | |
| result = 0; | |
| if (!clock_gettime(CLOCK_MONOTONIC, &time)){ | |
| result = (time.tv_sec * 1000000) + (time.tv_nsec / 1000); | |
| } | |
| return(result); | |
| } | |
| #else | |
| #error Timer not supported on this platform | |
| #endif | |
| #define STB_TRUETYPE_IMPLEMENTATION | |
| #include "stb_truetype.h" | |
| float* get_font_data(const char *font_file, float *font_height){ | |
| float *data = 0; | |
| stbtt_bakedchar *baked; | |
| File_Data file = get_file(font_file); | |
| if (!file.data) exit(1); | |
| if (file.data){ | |
| int size = sizeof(*baked)*256; | |
| baked = (stbtt_bakedchar*)malloc(size); | |
| memset_4tech(baked, 0, sizeof(*baked)*256); | |
| stbtt_fontinfo font; | |
| if (stbtt_InitFont(&font, (unsigned char*)file.data, 0)){ | |
| float scale; | |
| int a,d,g; | |
| scale = stbtt_ScaleForPixelHeight(&font, 17.f); | |
| stbtt_GetFontVMetrics(&font, &a, &d, &g); | |
| *font_height = scale*(a - d + g); | |
| int w, h; | |
| w = 10*256; | |
| h = 25; | |
| unsigned char *pixels = (unsigned char*)malloc(w * h); | |
| stbtt_BakeFontBitmap((unsigned char*)file.data, 0, 17.f, pixels, w, h, 0, 128, baked); | |
| free(pixels); | |
| free_file(file); | |
| data = (float*)malloc(sizeof(float)*256); | |
| memset_4tech(data, 0, sizeof(float)*256); | |
| stbtt_bakedchar *baked_ptr = baked; | |
| for (int i = 0; i < 128; ++i, ++baked_ptr){ | |
| data[i] = baked_ptr->xadvance; | |
| } | |
| } | |
| free(baked); | |
| } | |
| else{ | |
| printf("error: cannot continue without font\n"); | |
| } | |
| return data; | |
| } | |
| void setup(){ | |
| unsigned long long resolution; | |
| if (!time_init(&resolution)){ | |
| printf("error: could not initialize timer"); | |
| exit(1); | |
| } | |
| if (resolution < 1000000) | |
| printf("warning: timer is not actually at high enough resolution for good measurements!\n"); | |
| } | |
| typedef struct Time_Record{ | |
| time_int buffer; | |
| time_int gap_buffer; | |
| time_int multi_gap_buffer; | |
| time_int rope_buffer; | |
| } Time_Record; | |
| typedef struct Record_Statistics{ | |
| Time_Record max, min; | |
| Time_Record expected; | |
| int count; | |
| } Record_Statistics; | |
| typedef struct Log_Section{ | |
| int *counter; | |
| } Log_Section; | |
| typedef struct Stats_Log{ | |
| char *out; | |
| int size, max; | |
| Log_Section *sections; | |
| int sec_top, sec_max; | |
| unsigned int error; | |
| } Stats_Log; | |
| #define log_er_buffer_overflow 0x1 | |
| #define log_er_stack_overflow 0x2 | |
| #define log_er_stack_underflow 0x4 | |
| #define log_er_time_too_large 0x8 | |
| #define logid_begin_section 0 | |
| #define logid_data_item 1 | |
| #if fast_test | |
| #define use_stats_log 1 | |
| #else | |
| #define use_stats_log 0 | |
| #endif | |
| void log_write_int(Stats_Log *log, int x){ | |
| #if use_stats_log | |
| if (log->error == 0){ | |
| if (log->size+4 <= log->max){ | |
| *(int*)(log->out + log->size) = x; | |
| log->size += 4; | |
| } | |
| else{ | |
| log->error |= log_er_buffer_overflow; | |
| } | |
| } | |
| #endif | |
| } | |
| void log_write_time(Stats_Log *log, time_int x){ | |
| #if use_stats_log | |
| if (log->error == 0){ | |
| if (x < 0x7FFFFFFF){ | |
| if (log->size+4 <= log->max){ | |
| *(int*)(log->out + log->size) = (int)x; | |
| log->size += 4; | |
| } | |
| else{ | |
| log->error |= log_er_buffer_overflow; | |
| } | |
| } | |
| else{ | |
| log->error |= log_er_time_too_large; | |
| } | |
| } | |
| #endif | |
| } | |
| void log_write_str(Stats_Log *log, char *str, int len){ | |
| #if use_stats_log | |
| int up = (len + 3) & ~3; | |
| if (log->error == 0){ | |
| if (log->size+4+up <= log->max){ | |
| *(int*)(log->out + log->size) = up; | |
| memcpy_4tech(log->out + log->size + 4, str, len); | |
| log->size += 4+up; | |
| } | |
| else{ | |
| log->error |= log_er_buffer_overflow; | |
| } | |
| } | |
| #endif | |
| } | |
| void log_begin_section(Stats_Log *log, char *name, int name_len){ | |
| #if use_stats_log | |
| Log_Section *section; | |
| if (log->error == 0){ | |
| if (log->sec_top < log->sec_max){ | |
| if (log->sec_top > 0){ | |
| section = log->sections + log->sec_top - 1; | |
| ++section->counter; | |
| } | |
| section = log->sections + (log->sec_top++); | |
| log_write_int(log, logid_begin_section); | |
| log_write_str(log, name, name_len); | |
| section->counter = (int*)(log->out + log->size); | |
| log_write_int(log, 0); | |
| } | |
| else{ | |
| log->error |= log_er_stack_overflow; | |
| } | |
| } | |
| #endif | |
| } | |
| void log_end_section(Stats_Log *log){ | |
| #if use_stats_log | |
| if (log->error == 0){ | |
| if (log->sec_top > 0){ | |
| --log->sec_top; | |
| } | |
| else{ | |
| log->error |= log_er_stack_underflow; | |
| } | |
| } | |
| #endif | |
| } | |
| void log_data_item(Stats_Log *log, char *name, int name_len, time_int t){ | |
| #if use_stats_log | |
| Log_Section *section; | |
| if (log->error == 0){ | |
| if (log->sec_top > 0){ | |
| section = log->sections + log->sec_top - 1; | |
| ++section->counter; | |
| } | |
| log_write_int(log, logid_data_item); | |
| log_write_str(log, name, name_len); | |
| log_write_time(log, t); | |
| } | |
| #endif | |
| } | |
| void log_finish(Stats_Log *log){ | |
| #if use_stats_log | |
| assert_4tech(sizeof(external_name) < 512); | |
| if (log->error == 0){ | |
| char fname[1024]; | |
| memcpy_4tech(fname, "out/", 4); | |
| memcpy_4tech(fname + 4, external_name, sizeof(external_name)-1); | |
| time_into_str(fname + 4 + sizeof(external_name) - 1, 1023 - sizeof(external_name) + 1); | |
| File_Data log_file; | |
| log_file.data = log->out; | |
| log_file.size = log->size; | |
| save_file(fname, log_file); | |
| } | |
| else{ | |
| printf("\n"); | |
| if (log->error & log_er_buffer_overflow) | |
| printf("log error: buffer overflow\n"); | |
| if (log->error & log_er_stack_overflow) | |
| printf("log error: stack overflow\n"); | |
| if (log->error & log_er_stack_underflow) | |
| printf("log error: stack underflow\n"); | |
| printf("there were log error so the log was not saved\n\n"); | |
| } | |
| #endif | |
| } | |
| #define litstr(s) (char*)(s), (sizeof(s)-1) | |
| void log_time_record(Stats_Log *log, char *name, int name_len, Time_Record record){ | |
| log_begin_section(log, name, name_len); | |
| log_data_item(log, litstr("golden-array"), record.buffer); | |
| log_data_item(log, litstr("gap-buffer"), record.gap_buffer); | |
| log_data_item(log, litstr("multi-gap-buffer"), record.multi_gap_buffer); | |
| log_data_item(log, litstr("rope"), record.rope_buffer); | |
| log_end_section(log); | |
| } | |
| Time_Record | |
| operator+(const Time_Record &a, const Time_Record &b){ | |
| Time_Record r; | |
| r.buffer = a.buffer + b.buffer; | |
| r.gap_buffer = a.gap_buffer + b.gap_buffer; | |
| r.multi_gap_buffer = a.multi_gap_buffer + b.multi_gap_buffer; | |
| r.rope_buffer = a.rope_buffer + b.rope_buffer; | |
| return r; | |
| } | |
| Time_Record& | |
| operator/=(Time_Record &r, int x){ | |
| r.buffer /= x; | |
| r.gap_buffer /= x; | |
| r.multi_gap_buffer /= x; | |
| r.rope_buffer /= x; | |
| return(r); | |
| } | |
| #define minify(a,b) if ((a)>(b)) (a) = (b) | |
| #define maxify(a,b) if ((a)<(b)) (a) = (b) | |
| void get_record_statistics(Record_Statistics *stats_out, Time_Record *records, int count){ | |
| Record_Statistics stats; | |
| stats.max = records[0]; | |
| stats.min = records[0]; | |
| stats.expected = records[0]; | |
| stats.count = count; | |
| Time_Record *record = records + 1; | |
| for (int i = 1; i < count; ++i, ++record){ | |
| stats.expected = stats.expected + *record; | |
| minify(stats.min.buffer, record->buffer); | |
| minify(stats.min.gap_buffer, record->gap_buffer); | |
| minify(stats.min.multi_gap_buffer, record->multi_gap_buffer); | |
| minify(stats.min.rope_buffer, record->rope_buffer); | |
| maxify(stats.max.buffer, record->buffer); | |
| maxify(stats.max.gap_buffer, record->gap_buffer); | |
| maxify(stats.max.multi_gap_buffer, record->multi_gap_buffer); | |
| maxify(stats.max.rope_buffer, record->rope_buffer); | |
| } | |
| stats.expected /= count; | |
| *stats_out = stats; | |
| } | |
| int test_is_silenced; | |
| void silence_test(){ | |
| test_is_silenced = 1; | |
| } | |
| void print_record(Time_Record record){ | |
| printf("%-16s - %25lluus\n%-16s - %25lluus\n%-16s - %25lluus\n%-16s - %25lluus\n", | |
| "Golden Array", record.buffer, | |
| "Gap Buffer", record.gap_buffer, | |
| "Multi-Gap Buffer", record.multi_gap_buffer, | |
| "Rope", record.rope_buffer); | |
| } | |
| void print_statistics(Time_Record *records, int count, Record_Statistics *stats_out){ | |
| Record_Statistics stats; | |
| get_record_statistics(&stats, records, count); | |
| if (!test_is_silenced){ | |
| printf("samples: %d\n", count); | |
| printf("---averages---\n"); | |
| print_record(stats.expected); | |
| printf("---max---\n"); | |
| print_record(stats.max); | |
| printf("---min---\n"); | |
| print_record(stats.min); | |
| } | |
| if (stats_out) *stats_out = stats; | |
| } | |
| typedef struct Buffer_Set{ | |
| Buffer buffer; | |
| Gap_Buffer gap_buffer; | |
| Multi_Gap_Buffer multi_gap_buffer; | |
| Rope_Buffer rope_buffer; | |
| } Buffer_Set; | |
| #define Buffer_Type Buffer | |
| #include "4coder_test_abstract.cpp" | |
| #undef Buffer_Type | |
| #define Buffer_Type Gap_Buffer | |
| #include "4coder_test_abstract.cpp" | |
| #undef Buffer_Type | |
| #define Buffer_Type Multi_Gap_Buffer | |
| #include "4coder_test_abstract.cpp" | |
| #undef Buffer_Type | |
| #define Buffer_Type Rope_Buffer | |
| #include "4coder_test_abstract.cpp" | |
| #undef Buffer_Type | |
| void log_sample_set(Stats_Log *log, char *name, int name_len, Record_Statistics *stats, | |
| Time_Record *samples, int sample_count){ | |
| log_begin_section(log, name, name_len); | |
| log_data_item(log, litstr("sample-count"), sample_count); | |
| log_time_record(log, litstr("max"), stats->max); | |
| log_time_record(log, litstr("min"), stats->min); | |
| log_time_record(log, litstr("average"), stats->expected); | |
| for (int i = 0; i < sample_count; ++i){ | |
| log_time_record(log, litstr("item"), samples[i]); | |
| } | |
| log_end_section(log); | |
| } | |
| typedef struct Sample_Machine{ | |
| time_int tstart, tend; | |
| Time_Record *samples; | |
| int count; | |
| } Sample_Machine; | |
| Sample_Machine begin_machine(int count, void **data, int *max){ | |
| Sample_Machine result; | |
| result.count = count; | |
| result.samples = (Time_Record*)*data; | |
| *data = result.samples + count; | |
| assert_4tech(count*sizeof(*result.samples) < *max); | |
| *max -= count*sizeof(*result.samples); | |
| return(result); | |
| } | |
| void end_machine(Sample_Machine *machine, Record_Statistics *stats_out, char *func_name){ | |
| if (!test_is_silenced) printf("%s\n", func_name); | |
| print_statistics(machine->samples, machine->count, stats_out); | |
| if (!test_is_silenced) printf("\n"); | |
| test_is_silenced = 0; | |
| } | |
| void start(Sample_Machine *machine){ | |
| machine->tstart = get_time(); | |
| } | |
| time_int stop(Sample_Machine *machine){ | |
| machine->tend = get_time(); | |
| return machine->tend - machine->tstart; | |
| } | |
| void initialization_test(Stats_Log *log, Buffer_Set *set, File_Data file, int test_repitions, | |
| void *scratch, int scratch_size, Record_Statistics *stats_out){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| for (int i = 0; i < test_repitions; ++i){ | |
| start(&machine); | |
| init_buffer(&set->buffer, file, scratch, scratch_size); | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| init_buffer(&set->gap_buffer, file, scratch, scratch_size); | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| start(&machine); | |
| init_buffer(&set->multi_gap_buffer, file, scratch, scratch_size); | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| start(&machine); | |
| init_buffer(&set->rope_buffer, file, scratch, scratch_size); | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i+1 != test_repitions){ | |
| free(set->buffer.data); | |
| free(set->gap_buffer.data); | |
| for (int j = 0; j < set->multi_gap_buffer.chunk_alloced; ++j){ | |
| free(set->multi_gap_buffer.gaps[j].data); | |
| } | |
| free(set->multi_gap_buffer.gaps); | |
| free(set->rope_buffer.data); | |
| free(set->rope_buffer.nodes); | |
| } | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("initialization"), stats_out, machine.samples, machine.count); | |
| } | |
| void measure_starts_widths_test(Stats_Log *log, Buffer_Set *set, int test_repitions, void *scratch, | |
| int scratch_size, Record_Statistics *stats_out, float *font_widths){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| for (int i = 0; i < test_repitions; ++i){ | |
| start(&machine); | |
| measure_starts_widths(&set->buffer, font_widths); | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| measure_starts_widths(&set->gap_buffer, font_widths); | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| start(&machine); | |
| measure_starts_widths(&set->multi_gap_buffer, font_widths); | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| start(&machine); | |
| measure_starts_widths(&set->rope_buffer, font_widths); | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i+1 != test_repitions){ | |
| free(set->buffer.line_starts); | |
| free(set->gap_buffer.line_starts); | |
| free(set->multi_gap_buffer.line_starts); | |
| free(set->rope_buffer.line_starts); | |
| free(set->buffer.line_widths); | |
| free(set->gap_buffer.line_widths); | |
| free(set->multi_gap_buffer.line_widths); | |
| free(set->rope_buffer.line_widths); | |
| set->buffer.line_max = 0; | |
| set->buffer.line_starts = 0; | |
| set->buffer.widths_max = 0; | |
| set->buffer.line_widths = 0; | |
| set->gap_buffer.line_max = 0; | |
| set->gap_buffer.line_starts = 0; | |
| set->gap_buffer.widths_max = 0; | |
| set->gap_buffer.line_widths = 0; | |
| set->multi_gap_buffer.line_max = 0; | |
| set->multi_gap_buffer.line_starts = 0; | |
| set->multi_gap_buffer.widths_max = 0; | |
| set->multi_gap_buffer.line_widths = 0; | |
| set->rope_buffer.line_max = 0; | |
| set->rope_buffer.line_starts = 0; | |
| set->rope_buffer.widths_max = 0; | |
| set->rope_buffer.line_widths = 0; | |
| } | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("measure-starts-widths"), stats_out, machine.samples, machine.count); | |
| } | |
| int page_compare(void *page_1_, void *page_2_, int page_size){ | |
| char *page_1 = (char*)page_1_; | |
| char *page_2 = (char*)page_2_; | |
| int result = 1; | |
| for (int i = 0; i < page_size; ++i){ | |
| hard_assert_4tech(page_1[i] == page_2[i]); | |
| } | |
| return result; | |
| } | |
| float* measure_wraps_test(Stats_Log *log, Buffer_Set *buffers, int test_repitions, void *scratch, | |
| int scratch_size, Record_Statistics *stats_out, float font_height, float max_width){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| float *wrap_ys, *wrap_ys2; | |
| wrap_ys = (float*)malloc(sizeof(float)*buffers->buffer.line_count); | |
| wrap_ys2 = (float*)malloc(sizeof(float)*buffers->buffer.line_count); | |
| for (int i = 0; i < test_repitions; ++i){ | |
| start(&machine); | |
| buffer_measure_wrap_y(&buffers->buffer, wrap_ys, font_height, max_width); | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| buffer_measure_wrap_y(&buffers->gap_buffer, wrap_ys2, font_height, max_width); | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| if (i == 0) | |
| page_compare((char*)wrap_ys, (char*)wrap_ys2, sizeof(float)*buffers->buffer.line_count); | |
| start(&machine); | |
| buffer_measure_wrap_y(&buffers->multi_gap_buffer, wrap_ys2, font_height, max_width); | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| if (i == 0) | |
| page_compare((char*)wrap_ys, (char*)wrap_ys2, sizeof(float)*buffers->buffer.line_count); | |
| start(&machine); | |
| buffer_measure_wrap_y(&buffers->rope_buffer, wrap_ys2, font_height, max_width); | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i == 0) | |
| page_compare((char*)wrap_ys, (char*)wrap_ys2, sizeof(float)*buffers->buffer.line_count); | |
| } | |
| free(wrap_ys2); | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("measure-wrap-ys"), stats_out, machine.samples, machine.count); | |
| return wrap_ys; | |
| } | |
| int cursor_eq(Full_Cursor c1, Full_Cursor c2){ | |
| int result = 0; | |
| if (c1.pos == c2.pos && c1.line == c2.line && c1.character == c2.character && | |
| c1.wrapped_x == c2.wrapped_x && c1.wrapped_y == c2.wrapped_y && | |
| c1.unwrapped_x == c2.unwrapped_x && c1.unwrapped_y == c2.unwrapped_y){ | |
| result = 1; | |
| } | |
| return(result); | |
| } | |
| void full_cursor_test(Stats_Log *log, Buffer_Set *buffers, int pos, | |
| float *wrap_ys, float *advance_data, float font_height, float max_width, | |
| int test_repitions, void *scratch, int scratch_size, Record_Statistics *stats_out){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| Full_Cursor cursor, cursor2; | |
| for (int i = 0; i < test_repitions; ++i){ | |
| start(&machine); | |
| cursor = buffer_cursor_from_pos(&buffers->buffer, pos, wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| cursor2 = buffer_cursor_from_pos(&buffers->gap_buffer, pos, wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| if (i == 0) assert_4tech(cursor_eq(cursor, cursor2)); | |
| start(&machine); | |
| cursor2 = buffer_cursor_from_pos(&buffers->multi_gap_buffer, pos, wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| if (i == 0) assert_4tech(cursor_eq(cursor, cursor2)); | |
| start(&machine); | |
| cursor2 = buffer_cursor_from_pos(&buffers->rope_buffer, pos, wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i == 0) assert_4tech(cursor_eq(cursor, cursor2)); | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("full-cursor-seek"), stats_out, machine.samples, machine.count); | |
| } | |
| void full_cursor_line_test(Stats_Log *log, Buffer_Set *buffers, int line, int character, | |
| float *wrap_ys, float *advance_data, float font_height, float max_width, | |
| int test_repitions, void *scratch, int scratch_size, Record_Statistics *stats_out){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| Full_Cursor cursor, cursor2; | |
| for (int i = 0; i < test_repitions; ++i){ | |
| start(&machine); | |
| cursor = buffer_cursor_from_line_character(&buffers->buffer, line, character, | |
| wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| cursor2 = buffer_cursor_from_line_character(&buffers->gap_buffer, line, character, | |
| wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| if (i == 0) assert_4tech(cursor_eq(cursor, cursor2)); | |
| start(&machine); | |
| cursor2 = buffer_cursor_from_line_character(&buffers->multi_gap_buffer, line, character, | |
| wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| if (i == 0) assert_4tech(cursor_eq(cursor, cursor2)); | |
| start(&machine); | |
| cursor2 = buffer_cursor_from_line_character(&buffers->rope_buffer, line, character, | |
| wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i == 0) assert_4tech(cursor_eq(cursor, cursor2)); | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("full-cursor-seek"), stats_out, machine.samples, machine.count); | |
| } | |
| void full_cursor_xy_test(Stats_Log *log, Buffer_Set *buffers, float x, float y, int round_down, | |
| float *wrap_ys, float *advance_data, float font_height, float max_width, | |
| int test_repitions, void *scratch, int scratch_size, Record_Statistics *stats_out){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| Full_Cursor cursor, cursor2; | |
| for (int i = 0; i < test_repitions; ++i){ | |
| start(&machine); | |
| cursor = buffer_cursor_from_unwrapped_xy(&buffers->buffer, x, y, round_down, | |
| wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| cursor2 = buffer_cursor_from_unwrapped_xy(&buffers->gap_buffer, x, y, round_down, | |
| wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| if (i == 0) assert_4tech(cursor_eq(cursor, cursor2)); | |
| start(&machine); | |
| cursor2 = buffer_cursor_from_unwrapped_xy(&buffers->multi_gap_buffer, x, y, round_down, | |
| wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| if (i == 0) assert_4tech(cursor_eq(cursor, cursor2)); | |
| start(&machine); | |
| cursor2 = buffer_cursor_from_unwrapped_xy(&buffers->rope_buffer, x, y, round_down, | |
| wrap_ys, max_width, font_height, advance_data); | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i == 0) assert_4tech(cursor_eq(cursor, cursor2)); | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("full-cursor-seek"), stats_out, machine.samples, machine.count); | |
| } | |
| void word_seek_test(Stats_Log *log, Buffer_Set *buffers, int test_repitions, | |
| int incremental_position, char *word, int len, | |
| void *scratch, int scratch_size, Record_Statistics *stats_out){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| assert_4tech(scratch_size >= len); | |
| int pos, pos2, old_pos; | |
| old_pos = 0; | |
| for (int i = 0; i < machine.count; ++i){ | |
| start(&machine); | |
| pos = buffer_find_string(&buffers->buffer, old_pos, word, len, (char*)scratch); | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| pos2 = buffer_find_string(&buffers->gap_buffer, old_pos, word, len, (char*)scratch); | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| assert_4tech(pos2 == pos); | |
| start(&machine); | |
| pos2 = buffer_find_string(&buffers->multi_gap_buffer, old_pos, word, len, (char*)scratch); | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| assert_4tech(pos2 == pos); | |
| start(&machine); | |
| pos2 = buffer_find_string(&buffers->rope_buffer, old_pos, word, len, (char*)scratch); | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| assert_4tech(pos2 == pos); | |
| if (incremental_position) old_pos = pos; | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("word-seek"), stats_out, machine.samples, machine.count); | |
| } | |
| void stream_check_test(Buffer_Set *buffers, void *scratch, int scratch_size){ | |
| int i, page_size, size; | |
| size = buffer_size(&buffers->buffer); | |
| { | |
| int size2; | |
| size2 = buffer_size(&buffers->gap_buffer); | |
| hard_assert_4tech(size == size2); | |
| size2 = buffer_size(&buffers->multi_gap_buffer); | |
| hard_assert_4tech(size == size2); | |
| size2 = buffer_size(&buffers->rope_buffer); | |
| hard_assert_4tech(size == size2); | |
| } | |
| page_size = 1 << 10; | |
| char *page_1 = (char*)scratch; | |
| char *page_2 = page_1 + page_size; | |
| scratch_size -= page_size*2; | |
| hard_assert_4tech(scratch_size > 0); | |
| for (i = 0; i < size; i += page_size){ | |
| int end = i + page_size; | |
| if (end > size) end = size; | |
| buffer_stringify(&buffers->buffer, i, end, page_1); | |
| buffer_stringify(&buffers->gap_buffer, i, end, page_2); | |
| page_compare(page_1, page_2, page_size); | |
| buffer_stringify(&buffers->multi_gap_buffer, i, end, page_2); | |
| page_compare(page_1, page_2, page_size); | |
| buffer_stringify(&buffers->rope_buffer, i, end, page_2); | |
| page_compare(page_1, page_2, page_size); | |
| } | |
| for (i = size-1; i > 0; i -= page_size){ | |
| int end = i - page_size; | |
| if (end < 0) end = 0; | |
| buffer_backify(&buffers->buffer, i, end, page_1); | |
| buffer_backify(&buffers->gap_buffer, i, end, page_2); | |
| page_compare(page_1, page_2, page_size); | |
| buffer_backify(&buffers->multi_gap_buffer, i, end, page_2); | |
| page_compare(page_1, page_2, page_size); | |
| buffer_backify(&buffers->rope_buffer, i, end, page_2); | |
| page_compare(page_1, page_2, page_size); | |
| } | |
| } | |
| void insert_bottom_test(Stats_Log *log, Buffer_Set *buffers, int test_repitions, float *advance_data, | |
| int edit_count, void *scratch, int scratch_size, Record_Statistics *stats_out){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| char word[] = "stuff"; | |
| int word_len = sizeof(word) - 1; | |
| int i, j; | |
| for (i = 0; i < test_repitions; ++i){ | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| insert_bottom(&buffers->buffer, word, word_len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| insert_bottom(&buffers->gap_buffer, word, word_len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| insert_bottom(&buffers->multi_gap_buffer, word, word_len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| insert_bottom(&buffers->rope_buffer, word, word_len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i == 0){ | |
| stream_check_test(buffers, scratch, scratch_size); | |
| } | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("insert-bottom"), stats_out, machine.samples, machine.count); | |
| } | |
| void insert_top_test(Stats_Log *log, Buffer_Set *buffers, int test_repitions, float *advance_data, | |
| int edit_count, void *scratch, int scratch_size, Record_Statistics *stats_out){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| char word[] = "stuff"; | |
| int word_len = sizeof(word) - 1; | |
| int i, j; | |
| for (i = 0; i < test_repitions; ++i){ | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| insert_top(&buffers->buffer, word, word_len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| insert_top(&buffers->gap_buffer, word, word_len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| insert_top(&buffers->multi_gap_buffer, word, word_len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| insert_top(&buffers->rope_buffer, word, word_len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i == 0){ | |
| stream_check_test(buffers, scratch, scratch_size); | |
| } | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("insert-top"), stats_out, machine.samples, machine.count); | |
| } | |
| void delete_bottom_test(Stats_Log *log, Buffer_Set *buffers, int test_repitions, float *advance_data, | |
| int edit_count, void *scratch, int scratch_size, Record_Statistics *stats_out){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| int len = 5; | |
| int i, j; | |
| for (i = 0; i < test_repitions; ++i){ | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| delete_bottom(&buffers->buffer, len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| delete_bottom(&buffers->gap_buffer, len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| delete_bottom(&buffers->multi_gap_buffer, len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| delete_bottom(&buffers->rope_buffer, len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i == 0){ | |
| stream_check_test(buffers, scratch, scratch_size); | |
| } | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("delete-bottom"), stats_out, machine.samples, machine.count); | |
| } | |
| void delete_top_test(Stats_Log *log, Buffer_Set *buffers, int test_repitions, float *advance_data, | |
| int edit_count, void *scratch, int scratch_size, Record_Statistics *stats_out){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| int len = 5; | |
| int i, j; | |
| for (i = 0; i < test_repitions; ++i){ | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| delete_top(&buffers->buffer, len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| delete_top(&buffers->gap_buffer, len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| delete_top(&buffers->multi_gap_buffer, len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| start(&machine); | |
| for (j = 0; j < edit_count; ++j){ | |
| delete_top(&buffers->rope_buffer, len, | |
| advance_data, scratch, scratch_size); | |
| } | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i == 0){ | |
| stream_check_test(buffers, scratch, scratch_size); | |
| } | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("delete-top"), stats_out, machine.samples, machine.count); | |
| } | |
| void natural_edits_test(Stats_Log *log, Buffer_Set *buffers, int test_repitions, float *advance_data, | |
| Replay *replay, void *scratch, int scratch_size, Record_Statistics *stats_out){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| printf("edit count: %d\n", replay->replay.count); | |
| log_data_item(log, litstr("edit-count"), replay->replay.count); | |
| int i, j; | |
| for (i = 0; i < test_repitions; ++i){ | |
| j = i*buffer_size(&buffers->buffer) / (1+test_repitions); | |
| start(&machine); | |
| natural_edits(&buffers->buffer, advance_data, replay, j, scratch, scratch_size); | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| natural_edits(&buffers->gap_buffer, advance_data, replay, j, scratch, scratch_size); | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| start(&machine); | |
| natural_edits(&buffers->multi_gap_buffer, advance_data, replay, j, scratch, scratch_size); | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| start(&machine); | |
| natural_edits(&buffers->rope_buffer, advance_data, replay, j, scratch, scratch_size); | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i == 0){ | |
| stream_check_test(buffers, scratch, scratch_size); | |
| } | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("natural-edits"), stats_out, machine.samples, machine.count); | |
| } | |
| void batch_edit_test(Stats_Log *log, Buffer_Set *buffers, int test_repitions, float *advance_data, | |
| Buffer_Edit *batch, char *str_base, int batch_size, | |
| void *scratch, int scratch_size, Record_Statistics *stats_out){ | |
| Sample_Machine machine; | |
| machine = begin_machine(test_repitions, &scratch, &scratch_size); | |
| printf("batch size: %d\n", replay->replay.count); | |
| log_data_item(log, litstr("batch-size"), replay->replay.count); | |
| int i; | |
| for (i = 0; i < test_repitions; ++i){ | |
| start(&machine); | |
| batch_edit(&buffers->buffer, advance_data, batch, str_base, batch_size, scratch, scratch_size); | |
| machine.samples[i].buffer = stop(&machine); | |
| start(&machine); | |
| batch_edit(&buffers->gap_buffer, advance_data, batch, str_base, batch_size, scratch, scratch_size); | |
| machine.samples[i].gap_buffer = stop(&machine); | |
| start(&machine); | |
| batch_edit(&buffers->multi_gap_buffer, advance_data, batch, str_base, batch_size, scratch, scratch_size); | |
| machine.samples[i].multi_gap_buffer = stop(&machine); | |
| start(&machine); | |
| batch_edit(&buffers->rope_buffer, advance_data, batch, str_base, batch_size, scratch, scratch_size); | |
| machine.samples[i].rope_buffer = stop(&machine); | |
| if (i == 0){ | |
| stream_check_test(buffers, scratch, scratch_size); | |
| } | |
| } | |
| end_machine(&machine, stats_out, __FUNCTION__); | |
| log_sample_set(log, litstr("batch-edit"), stats_out, machine.samples, machine.count); | |
| } | |
| void measure_check_test(Buffer_Set *buffers){ | |
| int count; | |
| count = buffers->buffer.line_count; | |
| assert_4tech(count == buffers->buffer.widths_count); | |
| assert_4tech(count == buffers->gap_buffer.line_count); | |
| assert_4tech(count == buffers->multi_gap_buffer.line_count); | |
| assert_4tech(count == buffers->rope_buffer.line_count); | |
| assert_4tech(count == buffers->gap_buffer.widths_count); | |
| assert_4tech(count == buffers->multi_gap_buffer.widths_count); | |
| assert_4tech(count == buffers->rope_buffer.widths_count); | |
| page_compare(buffers->buffer.line_starts, buffers->gap_buffer.line_starts, sizeof(int)*count); | |
| page_compare(buffers->buffer.line_starts, buffers->multi_gap_buffer.line_starts, sizeof(int)*count); | |
| page_compare(buffers->buffer.line_starts, buffers->rope_buffer.line_starts, sizeof(int)*count); | |
| page_compare(buffers->buffer.line_widths, buffers->gap_buffer.line_widths, sizeof(float)*count); | |
| page_compare(buffers->buffer.line_widths, buffers->multi_gap_buffer.line_widths, sizeof(float)*count); | |
| page_compare(buffers->buffer.line_widths, buffers->rope_buffer.line_widths, sizeof(float)*count); | |
| } | |
| #define reps 50 | |
| int main(int argc, char **argv){ | |
| Buffer_Set buffers; | |
| File_Data file; | |
| float *widths_data; | |
| float *wrap_ys; | |
| float font_height; | |
| float max_width; | |
| void *scratch; | |
| int scratch_size; | |
| Stats_Log log; | |
| int do_replay = 0; | |
| char *replay_filename = 0; | |
| if (argc < 2){ | |
| printf("usage: buffer_test <filename> <message> [-h <.hst file>]\n"); | |
| exit(1); | |
| } | |
| setup(); | |
| for (int i = 3; i < argc; ++i){ | |
| if (do_replay){ | |
| replay_filename = argv[i]; | |
| do_replay = 0; | |
| } | |
| if (strcmp(argv[i], "-h") == 0){ | |
| if (replay_filename != 0){ | |
| printf("found -h twice, ignoring duplicates\n"); | |
| } | |
| else{ | |
| do_replay = 1; | |
| } | |
| } | |
| } | |
| do_replay = (replay_filename != 0); | |
| memzero_4tech(buffers); | |
| log.max = 1 << 20; | |
| log.size = 0; | |
| log.out = (char*)malloc(log.max); | |
| log.sec_max = 32; | |
| log.sec_top = 0; | |
| log.sections = (Log_Section*)malloc(sizeof(Log_Section)*log.sec_max); | |
| log.error = 0; | |
| scratch_size = 1 << 20; | |
| scratch = malloc(scratch_size); | |
| file = get_file(argv[1]); | |
| if (!file.data) exit(1); | |
| widths_data = get_font_data("LiberationSans-Regular.ttf", &font_height); | |
| max_width = 500.f; | |
| log_begin_section(&log, litstr("which-test")); | |
| { | |
| log_write_str(&log, argv[1], (int)strlen(argv[1])); | |
| log_write_int(&log, file.size); | |
| log_write_str(&log, argv[2], (int)strlen(argv[2])); | |
| } | |
| log_end_section(&log); | |
| log_begin_section(&log, litstr("file-open")); | |
| { | |
| Record_Statistics init_rec, starts_widths_rec, wraps_rec; | |
| initialization_test(&log, &buffers, file, reps, scratch, scratch_size, &init_rec); | |
| stream_check_test(&buffers, scratch, scratch_size); | |
| measure_starts_widths_test(&log, &buffers, reps, scratch, scratch_size, | |
| &starts_widths_rec, widths_data); | |
| measure_check_test(&buffers); | |
| wrap_ys = measure_wraps_test(&log, &buffers, reps, scratch, scratch_size, | |
| &wraps_rec, font_height, max_width); | |
| Time_Record expected_file_open; | |
| expected_file_open = init_rec.expected + starts_widths_rec.expected + wraps_rec.expected; | |
| printf("average file open:\n"); | |
| print_record(expected_file_open); | |
| printf("\n"); | |
| log_time_record(&log, litstr("average"), expected_file_open); | |
| } | |
| log_end_section(&log); | |
| log_begin_section(&log, litstr("cursor-seek")); | |
| { | |
| Record_Statistics full_cursor; | |
| Time_Record full_cursor_average; | |
| log_begin_section(&log, litstr("to-pos")); | |
| { | |
| memzero_4tech(full_cursor_average); | |
| for (int i = 0; i < 5; ++i){ | |
| silence_test(); | |
| int pos = (file.size*i) / 5; | |
| full_cursor_test(&log, &buffers, pos, | |
| wrap_ys, widths_data, font_height, max_width, | |
| 5, scratch, scratch_size, &full_cursor); | |
| full_cursor_average = full_cursor_average + full_cursor.expected; | |
| } | |
| full_cursor_average /= 5; | |
| printf("average cursor from position:\n"); | |
| print_record(full_cursor_average); | |
| printf("\n"); | |
| log_time_record(&log, litstr("average"), full_cursor_average); | |
| } | |
| log_end_section(&log); | |
| log_begin_section(&log, litstr("to-line-character")); | |
| { | |
| memzero_4tech(full_cursor_average); | |
| for (int i = 0; i < 5; ++i){ | |
| silence_test(); | |
| int line = (buffers.buffer.line_count*i) / 5; | |
| full_cursor_line_test(&log, &buffers, line, 20, | |
| wrap_ys, widths_data, font_height, max_width, | |
| 5, scratch, scratch_size, &full_cursor); | |
| full_cursor_average = full_cursor_average + full_cursor.expected; | |
| } | |
| full_cursor_average /= 5; | |
| printf("average cursor from line & character:\n"); | |
| print_record(full_cursor_average); | |
| printf("\n"); | |
| log_time_record(&log, litstr("average"), full_cursor_average); | |
| } | |
| log_end_section(&log); | |
| log_begin_section(&log, litstr("to-unwrapped-x-y")); | |
| { | |
| memzero_4tech(full_cursor_average); | |
| for (int i = 0; i < 5; ++i){ | |
| silence_test(); | |
| float y = font_height * (buffers.buffer.line_count*i) / 4.f; | |
| full_cursor_xy_test(&log, &buffers, y, 37.f, 0, | |
| wrap_ys, widths_data, font_height, max_width, | |
| 5, scratch, scratch_size, &full_cursor); | |
| full_cursor_average = full_cursor_average + full_cursor.expected; | |
| } | |
| full_cursor_average /= 5; | |
| printf("average cursor from line & character:\n"); | |
| print_record(full_cursor_average); | |
| printf("\n"); | |
| log_time_record(&log, litstr("average"), full_cursor_average); | |
| } | |
| log_end_section(&log); | |
| } | |
| log_end_section(&log); | |
| log_begin_section(&log, litstr("word-seek")); | |
| { | |
| Record_Statistics word_seek; | |
| { | |
| char word[] = "not-going-to-find-this"; | |
| int word_len = sizeof(word) - 1; | |
| word_seek_test(&log, &buffers, reps, 0, word, word_len, scratch, scratch_size, &word_seek); | |
| } | |
| { | |
| char word[] = "return"; | |
| int word_len = sizeof(word) - 1; | |
| word_seek_test(&log, &buffers, reps, 1, word, word_len, scratch, scratch_size, &word_seek); | |
| printf("average normal word seek:\n"); | |
| print_record(word_seek.expected); | |
| printf("\n"); | |
| } | |
| } | |
| log_end_section(&log); | |
| log_begin_section(&log, litstr("one-hundred-single-edits")); | |
| { | |
| Record_Statistics edits; | |
| insert_bottom_test(&log, &buffers, reps, widths_data, 100, scratch, scratch_size, &edits); | |
| insert_top_test(&log, &buffers, reps, widths_data, 100, scratch, scratch_size, &edits); | |
| delete_bottom_test(&log, &buffers, reps, widths_data, 100, scratch, scratch_size, &edits); | |
| delete_top_test(&log, &buffers, reps, widths_data, 100, scratch, scratch_size, &edits); | |
| } | |
| log_end_section(&log); | |
| File_Data replay_file = {}; | |
| Replay replay; | |
| if (do_replay){ | |
| replay_file = get_file(replay_filename); | |
| prepare_replay(replay_file, &replay); | |
| } | |
| if (replay_file.data){ | |
| log_begin_section(&log, litstr("natural-edits")); | |
| { | |
| Record_Statistics edits; | |
| natural_edits_test(&log, &buffers, reps, widths_data, &replay, | |
| scratch, scratch_size, &edits); | |
| } | |
| log_end_section(&log); | |
| } | |
| else{ | |
| printf("skipped natural-edits test\n\n"); | |
| } | |
| log_begin_section(&log, litstr("batch-edit")); | |
| { | |
| Buffer_Edit *batch; | |
| char *str_base; | |
| int batch_size, str_size; | |
| batch_size = 1000; | |
| str_size = 10000; | |
| batch = (Buffer_Edit*)malloc(sizeof(Buffer_Edit)*batch_size); | |
| str_base = (char*)malloc(str_size); | |
| int character_stride; | |
| character_stride = buffer_size(&buffers.buffer); | |
| if (character_stride < batch_size * 10){ | |
| batch_size = character_stride / 10; | |
| character_stride = 10; | |
| } | |
| else{ | |
| character_stride = (character_stride / batch_size); | |
| } | |
| int p, curs; | |
| curs = 0; | |
| p = 0; | |
| for (int i = 0; i < batch_size; ++i){ | |
| Buffer_Edit edit; | |
| edit.start = p; | |
| edit.end = p+8; | |
| p += character_stride; | |
| edit.str_start = curs; | |
| if (i & 1){ | |
| edit.len = 9; | |
| memcpy_4tech(str_base + curs, "123456789", 9); | |
| curs += 9; | |
| } | |
| else{ | |
| edit.len = 7; | |
| memcpy_4tech(str_base + curs, "abcdefg", 7); | |
| curs += 7; | |
| } | |
| batch[i] = edit; | |
| } | |
| Record_Statistics batch_stats; | |
| batch_edit_test(&log, &buffers, reps, widths_data, batch, str_base, batch_size, | |
| scratch, scratch_size, &batch_stats); | |
| } | |
| log_end_section(&log); | |
| log_finish(&log); | |
| return(0); | |
| } | |
| // BOTTOM | |