authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-25 12:29:25-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-25 12:29:25-04:00
loge0050af293146a38e2122413196e66f73d90f2e0
tree3da86e1e696d8452e3af47e0cad2e218b5d094c6
parent4cc2ea14214434297d01c1c89e9308c5c332b0fb

add some timing diagnostics

pass --enable-timing-info to print a nice table like this: ``` Name Start End Duration Percent Initialize 0.0000 0.0000 0.0000 0.0001 Semantic Analysis 0.0000 0.0421 0.0420 0.2109 Code Generation 0.0421 0.0620 0.0200 0.1003 LLVM Emit Object 0.0620 0.1852 0.1231 0.6180 Build Dependencies 0.1852 0.1974 0.0122 0.0615 LLVM Link 0.1974 0.1993 0.0018 0.0093 Generate .h 0.1993 0.1993 0.0000 0.0000 Total 0.0000 0.1993 0.1993 1.0000 ```

7 files changed, 89 insertions(+), 0 deletions(-)

src/all_types.hpp+7
...@@ -1285,6 +1285,11 @@ struct ZigLLVMFnKey {...@@ -1285,6 +1285,11 @@ struct ZigLLVMFnKey {
1285uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey);1285uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey);
1286bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b);1286bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b);
12871287
1288struct TimeEvent {
1289 double time;
1290 const char *name;
1291};
1292
1288struct CodeGen {1293struct CodeGen {
1289 LLVMModuleRef module;1294 LLVMModuleRef module;
1290 ZigList<ErrorMsg*> errors;1295 ZigList<ErrorMsg*> errors;
...@@ -1468,6 +1473,8 @@ struct CodeGen {...@@ -1468,6 +1473,8 @@ struct CodeGen {
14681473
1469 Buf *test_filter;1474 Buf *test_filter;
1470 Buf *test_name_prefix;1475 Buf *test_name_prefix;
1476
1477 ZigList<TimeEvent> timing_events;
1471};1478};
14721479
1473enum VarLinkage {1480enum VarLinkage {
src/codegen.cpp+30
...@@ -57,6 +57,9 @@ PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_pa...@@ -57,6 +57,9 @@ PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_pa
5757
58CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {58CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
59 CodeGen *g = allocate<CodeGen>(1);59 CodeGen *g = allocate<CodeGen>(1);
60
61 codegen_add_time_event(g, "Initialize");
62
60 g->import_table.init(32);63 g->import_table.init(32);
61 g->builtin_fn_table.init(32);64 g->builtin_fn_table.init(32);
62 g->primitive_type_table.init(32);65 g->primitive_type_table.init(32);
...@@ -3654,6 +3657,8 @@ static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const c...@@ -3654,6 +3657,8 @@ static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const c
3654static void do_code_gen(CodeGen *g) {3657static void do_code_gen(CodeGen *g) {
3655 assert(!g->errors.length);3658 assert(!g->errors.length);
36563659
3660 codegen_add_time_event(g, "Code Generation");
3661
3657 delete_unused_builtin_fns(g);3662 delete_unused_builtin_fns(g);
3658 generate_error_name_table(g);3663 generate_error_name_table(g);
3659 generate_enum_name_tables(g);3664 generate_enum_name_tables(g);
...@@ -3977,6 +3982,8 @@ static void do_code_gen(CodeGen *g) {...@@ -3977,6 +3982,8 @@ static void do_code_gen(CodeGen *g) {
3977 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);3982 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
3978#endif3983#endif
39793984
3985 codegen_add_time_event(g, "LLVM Emit Object");
3986
3980 char *err_msg = nullptr;3987 char *err_msg = nullptr;
3981 Buf *out_file_o = buf_create_from_buf(g->root_out_name);3988 Buf *out_file_o = buf_create_from_buf(g->root_out_name);
3982 const char *o_ext = target_o_file_ext(&g->zig_target);3989 const char *o_ext = target_o_file_ext(&g->zig_target);
...@@ -4730,6 +4737,8 @@ static PackageTableEntry *create_zigrt_pkg(CodeGen *g) {...@@ -4730,6 +4737,8 @@ static PackageTableEntry *create_zigrt_pkg(CodeGen *g) {
4730}4737}
47314738
4732void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {4739void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {
4740 codegen_add_time_event(g, "Semantic Analysis");
4741
4733 Buf source_path = BUF_INIT;4742 Buf source_path = BUF_INIT;
4734 os_path_join(src_dir, src_basename, &source_path);4743 os_path_join(src_dir, src_basename, &source_path);
47354744
...@@ -5020,3 +5029,24 @@ void codegen_generate_h_file(CodeGen *g) {...@@ -5020,3 +5029,24 @@ void codegen_generate_h_file(CodeGen *g) {
5020 if (fclose(out_h))5029 if (fclose(out_h))
5021 zig_panic("unable to close h file: %s", strerror(errno));5030 zig_panic("unable to close h file: %s", strerror(errno));
5022}5031}
5032
5033void codegen_print_timing_report(CodeGen *g, FILE *f) {
5034 double start_time = g->timing_events.at(0).time;
5035 double end_time = g->timing_events.last().time;
5036 double total = end_time - start_time;
5037 fprintf(f, "%20s%12s%12s%12s%12s\n", "Name", "Start", "End", "Duration", "Percent");
5038 for (size_t i = 0; i < g->timing_events.length - 1; i += 1) {
5039 TimeEvent *te = &g->timing_events.at(i);
5040 TimeEvent *next_te = &g->timing_events.at(i + 1);
5041 fprintf(f, "%20s%12.4f%12.4f%12.4f%12.4f\n", te->name,
5042 te->time - start_time,
5043 next_te->time - start_time,
5044 next_te->time - te->time,
5045 (next_te->time - te->time) / total);
5046 }
5047 fprintf(f, "%20s%12.4f%12.4f%12.4f%12.4f\n", "Total", 0.0, total, total, 1.0);
5048}
5049
5050void codegen_add_time_event(CodeGen *g, const char *name) {
5051 g->timing_events.append({os_get_time(), name});
5052}
src/codegen.hpp+2
...@@ -47,6 +47,8 @@ void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt);...@@ -47,6 +47,8 @@ void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt);
47void codegen_set_test_filter(CodeGen *g, Buf *filter);47void codegen_set_test_filter(CodeGen *g, Buf *filter);
48void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);48void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
49void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);49void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
50void codegen_add_time_event(CodeGen *g, const char *name);
51void codegen_print_timing_report(CodeGen *g, FILE *f);
5052
51PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path);53PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path);
52void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);54void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
src/link.cpp+6
...@@ -732,6 +732,8 @@ static void construct_linker_job(LinkJob *lj) {...@@ -732,6 +732,8 @@ static void construct_linker_job(LinkJob *lj) {
732}732}
733733
734void codegen_link(CodeGen *g, const char *out_file) {734void codegen_link(CodeGen *g, const char *out_file) {
735 codegen_add_time_event(g, "Build Dependencies");
736
735 LinkJob lj = {0};737 LinkJob lj = {0};
736738
737 // even though we're calling LLD as a library it thinks the first739 // even though we're calling LLD as a library it thinks the first
...@@ -808,10 +810,12 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -808,10 +810,12 @@ void codegen_link(CodeGen *g, const char *out_file) {
808810
809 Buf diag = BUF_INIT;811 Buf diag = BUF_INIT;
810812
813 codegen_add_time_event(g, "LLVM Link");
811 if (!ZigLLDLink(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) {814 if (!ZigLLDLink(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) {
812 fprintf(stderr, "%s\n", buf_ptr(&diag));815 fprintf(stderr, "%s\n", buf_ptr(&diag));
813 exit(1);816 exit(1);
814 }817 }
818 codegen_add_time_event(g, "Generate .h");
815819
816 if (g->out_type == OutTypeLib ||820 if (g->out_type == OutTypeLib ||
817 g->out_type == OutTypeObj)821 g->out_type == OutTypeObj)
...@@ -819,6 +823,8 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -819,6 +823,8 @@ void codegen_link(CodeGen *g, const char *out_file) {
819 codegen_generate_h_file(g);823 codegen_generate_h_file(g);
820 }824 }
821825
826 codegen_add_time_event(g, "Done");
827
822 if (g->verbose) {828 if (g->verbose) {
823 fprintf(stderr, "OK\n");829 fprintf(stderr, "OK\n");
824 }830 }
src/main.cpp+14
...@@ -64,6 +64,7 @@ static int usage(const char *arg0) {...@@ -64,6 +64,7 @@ static int usage(const char *arg0) {
64 " -mwindows (windows only) --subsystem windows to the linker\n"64 " -mwindows (windows only) --subsystem windows to the linker\n"
65 " -rdynamic add all symbols to the dynamic symbol table\n"65 " -rdynamic add all symbols to the dynamic symbol table\n"
66 " -rpath [path] add directory to the runtime library search path\n"66 " -rpath [path] add directory to the runtime library search path\n"
67 " --enable-timing-info print timing diagnostics\n"
67 "Test Options:\n"68 "Test Options:\n"
68 " --test-filter [text] skip tests that do not match filter\n"69 " --test-filter [text] skip tests that do not match filter\n"
69 " --test-name-prefix [text] add prefix to all tests\n"70 " --test-name-prefix [text] add prefix to all tests\n"
...@@ -163,6 +164,7 @@ int main(int argc, char **argv) {...@@ -163,6 +164,7 @@ int main(int argc, char **argv) {
163 size_t ver_major = 0;164 size_t ver_major = 0;
164 size_t ver_minor = 0;165 size_t ver_minor = 0;
165 size_t ver_patch = 0;166 size_t ver_patch = 0;
167 bool timing_info = false;
166168
167 if (argc >= 2 && strcmp(argv[1], "build") == 0) {169 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
168 const char *zig_exe_path = arg0;170 const char *zig_exe_path = arg0;
...@@ -292,6 +294,8 @@ int main(int argc, char **argv) {...@@ -292,6 +294,8 @@ int main(int argc, char **argv) {
292 rdynamic = true;294 rdynamic = true;
293 } else if (strcmp(arg, "--each-lib-rpath") == 0) {295 } else if (strcmp(arg, "--each-lib-rpath") == 0) {
294 each_lib_rpath = true;296 each_lib_rpath = true;
297 } else if (strcmp(arg, "--enable-timing-info") == 0) {
298 timing_info = true;
295 } else if (arg[1] == 'L' && arg[2] != 0) {299 } else if (arg[1] == 'L' && arg[2] != 0) {
296 // alias for --library-path300 // alias for --library-path
297 lib_dirs.append(&arg[2]);301 lib_dirs.append(&arg[2]);
...@@ -596,20 +600,28 @@ int main(int argc, char **argv) {...@@ -596,20 +600,28 @@ int main(int argc, char **argv) {
596 if (cmd == CmdBuild) {600 if (cmd == CmdBuild) {
597 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);601 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
598 codegen_link(g, out_file);602 codegen_link(g, out_file);
603 if (timing_info)
604 codegen_print_timing_report(g, stderr);
599 return EXIT_SUCCESS;605 return EXIT_SUCCESS;
600 } else if (cmd == CmdLink) {606 } else if (cmd == CmdLink) {
601 for (size_t i = 0; i < objects.length; i += 1) {607 for (size_t i = 0; i < objects.length; i += 1) {
602 codegen_add_object(g, buf_create_from_str(objects.at(i)));608 codegen_add_object(g, buf_create_from_str(objects.at(i)));
603 }609 }
604 codegen_link(g, out_file);610 codegen_link(g, out_file);
611 if (timing_info)
612 codegen_print_timing_report(g, stderr);
605 return EXIT_SUCCESS;613 return EXIT_SUCCESS;
606 } else if (cmd == CmdAsm) {614 } else if (cmd == CmdAsm) {
607 codegen_add_root_assembly(g, &root_source_dir, &root_source_name, &root_source_code);615 codegen_add_root_assembly(g, &root_source_dir, &root_source_name, &root_source_code);
608 codegen_link(g, out_file);616 codegen_link(g, out_file);
617 if (timing_info)
618 codegen_print_timing_report(g, stderr);
609 return EXIT_SUCCESS;619 return EXIT_SUCCESS;
610 } else if (cmd == CmdParseH) {620 } else if (cmd == CmdParseH) {
611 codegen_parseh(g, &root_source_dir, &root_source_name, &root_source_code);621 codegen_parseh(g, &root_source_dir, &root_source_name, &root_source_code);
612 ast_render_decls(g, stdout, 4, g->root_import);622 ast_render_decls(g, stdout, 4, g->root_import);
623 if (timing_info)
624 codegen_print_timing_report(g, stderr);
613 return EXIT_SUCCESS;625 return EXIT_SUCCESS;
614 } else if (cmd == CmdTest) {626 } else if (cmd == CmdTest) {
615 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);627 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code);
...@@ -620,6 +632,8 @@ int main(int argc, char **argv) {...@@ -620,6 +632,8 @@ int main(int argc, char **argv) {
620 if (term.how != TerminationIdClean || term.code != 0) {632 if (term.how != TerminationIdClean || term.code != 0) {
621 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");633 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");
622 fprintf(stderr, "./test\n");634 fprintf(stderr, "./test\n");
635 } else if (timing_info) {
636 codegen_print_timing_report(g, stderr);
623 }637 }
624 return (term.how == TerminationIdClean) ? term.code : -1;638 return (term.how == TerminationIdClean) ? term.code : -1;
625 } else {639 } else {
src/os.cpp+29
...@@ -38,6 +38,11 @@...@@ -38,6 +38,11 @@
3838
39#endif39#endif
4040
41#if defined(__MACH__)
42#include <mach/clock.h>
43#include <mach/mach.h>
44#endif
45
41#include <stdlib.h>46#include <stdlib.h>
42#include <errno.h>47#include <errno.h>
43#include <time.h>48#include <time.h>
...@@ -690,3 +695,27 @@ int os_rename(Buf *src_path, Buf *dest_path) {...@@ -690,3 +695,27 @@ int os_rename(Buf *src_path, Buf *dest_path) {
690 }695 }
691 return 0;696 return 0;
692}697}
698
699double os_get_time(void) {
700#if defined(ZIG_OS_WINDOWS)
701 unsigned __int64 time;
702 QueryPerformanceCounter((LARGE_INTEGER*) &time);
703 return time * win32_time_resolution;
704#elif defined(__MACH__)
705 mach_timespec_t mts;
706
707 kern_return_t err = clock_get_time(cclock, &mts);
708 assert(!err);
709
710 double seconds = (double)mts.tv_sec;
711 seconds += ((double)mts.tv_nsec) / 1000000000.0;
712
713 return seconds;
714#else
715 struct timespec tms;
716 clock_gettime(CLOCK_MONOTONIC, &tms);
717 double seconds = (double)tms.tv_sec;
718 seconds += ((double)tms.tv_nsec) / 1000000000.0;
719 return seconds;
720#endif
721}
src/os.hpp+1
...@@ -56,6 +56,7 @@ int os_delete_file(Buf *path);...@@ -56,6 +56,7 @@ int os_delete_file(Buf *path);
56int os_file_exists(Buf *full_path, bool *result);56int os_file_exists(Buf *full_path, bool *result);
5757
58int os_rename(Buf *src_path, Buf *dest_path);58int os_rename(Buf *src_path, Buf *dest_path);
59double os_get_time(void);
5960
60#if defined(__APPLE__)61#if defined(__APPLE__)
61#define ZIG_OS_DARWIN62#define ZIG_OS_DARWIN