From: Samium G. <_de...@fe...> - 2007-11-06 07:06:46
|
Good day folks, Yesterday's morning I saw a mention of oprofile not being of much use in SBCL, due to dynamic code allocation/movement. I wondered, whether this issue was taken a stab at by different VMs. The oprofile list told me about a story[1] which began in September 2004, when IBM Java folks expressed interest in getting oprofile to "work". The problem, of course, being that oprofile has no way to get symbolic information for the heap-managed code objects, and therefore lumps all calls to such objects into one huge basket. Over three years and two different teams, they together managed to produce an API consisting of four functions, which solves the above problem, by allowing the VM to emit information about code object registration/deregistration in a format understandable by oprofile. So, I thought, it might be nice to get some sort of oprofile support in SBCL, and so, about 24 hours later, this is the code which facilitates a proof-of-concept implementation of the SBCL's side of the aforementioned bridge. This has numerous flaws: - Does not handle the effects of GC on code. (It shouldn't be very hard to fix this, to my understanding, just stick the unregister-at-the-old-place/register-at-the-new-place calls inside the GC.) - It is not precise, as it doesn't count the code object entry points (of which, if I'm understanding it correctly, there can be a multitude.) It basically means that it would underestimate the statistics for the often-called quick-running functions. - It does not, to my knowledge, handle any of the code which was loaded from the core, as the only two code object registration paths handled are %COMPILE and LOAD-AS-FASL. (Should also be trivial to fix.) I'm sure there's more to that. However, the patch is below. What is required, is the JIT_SUPPORT branch of oprofile: export CVSROOT=":pserver:ano...@op...:/cvsroot/oprofile" cvs login cvs -z3 co -rJIT_SUPPORT oprofile Then, the scenario goes as follows: betelheise:/home/deepfire# opcontrol --start Profiler running. < Launch SBCL with --oprofile-support and do some nastiness, then quit SBCL[2]. > betelheise:/home/deepfire# opcontrol --stop found jitdump /var/lib/oprofile/jitdump/12499.dump, producing ELF /var/lib/oprofile/samples/current/{root}/usr/bin/sbcl/{dep}/{anon:anon}/12499.jo WARNING: overlaps detected, removing overlapping JIT methods Stopping profiling. betelheise:/home/deepfire# opreport -l /usr/bin/sbcl CPU: AMD64 processors, speed 1000 MHz (estimated) Counted CPU_CLK_UNHALTED events (Cycles outside of halt state) with a unit mask of 0x00 (No unit mask) count 100000 warning: could not check that the binary file /var/lib/oprofile/samples/current/{root}/usr/bin/sbcl/{dep}/{anon:anon}/12499.jo has not been modified since the profile was taken. Results may be inaccurate. samples % image name symbol name 7426 31.5102 sbcl scav_list_pointer 5456 23.1510 sbcl gc_alloc_with_region 5387 22.8582 sbcl scavenge 1360 5.7708 sbcl gc_general_alloc 1147 4.8670 sbcl Lloop 667 2.8302 sbcl collect_garbage 652 2.7666 sbcl gc_init 233 0.9887 sbcl gc_alloc_new_region 198 0.8402 sbcl gc_find_freeish_pages 176 0.7468 sbcl closure_tramp 110 0.4668 sbcl gc_alloc_update_page_tables 107 0.4540 sbcl os_protect 88 0.3734 sbcl scavenge_newspace_generation_one_scan 80 0.3395 sbcl scav_instance_pointer 55 0.2334 sbcl funcallable_instance_tramp 50 0.2122 sbcl scav_instance 41 0.1740 sbcl alloc 39 0.1655 sbcl write_protect_generation_pages 38 0.1612 sbcl copy_object 30 0.1273 sbcl scav_other_pointer 27 0.1146 sbcl scav_immediate 26 0.1103 sbcl scav_boxed 23 0.0976 sbcl alloc_tramp 18 0.0764 sbcl scav_hash_table_entries 17 0.0721 sbcl copy_large_object 14 0.0594 sbcl scav_vector 12 0.0509 sbcl fast_bzero 10 0.0424 sbcl preserve_pointer 7 0.0297 sbcl scav_closure_header 7 0.0297 sbcl scav_fun_pointer 6 0.0255 sbcl copy_large_unboxed_object 6 0.0255 sbcl gc_search_space 5 0.0212 sbcl gc_initialize_pointers 5 0.0212 sbcl scav_code_header 5 0.0212 sbcl scav_vector_unsigned_byte_8 4 0.0170 sbcl .plt 4 0.0170 sbcl gencgc_handle_wp_violation 4 0.0170 sbcl scav_fdefn 4 0.0170 sbcl trans_vector_bit 3 0.0127 sbcl interrupt_handle_pending 2 0.0085 sbcl scav_character_string 2 0.0085 sbcl scav_unboxed 1 0.0042 12499.jo (SB-C::TOP-LEVEL-FORM (SB-KERNEL:MAKE-VALUE-CELL (SB-PCL::ENSURE-CTOR ("#<...>" . "#<...>") "#<...>" . "#<...>")))~2 1 0.0042 12499.jo (SB-C::VARARGS-ENTRY (LAMBDA (&OPTIONAL ("#<...>" . "#<...>") "#<...>" . "#<...>")))~8 1 0.0042 12499.jo (SB-C::XEP (LAMBDA (#:G[SYSTEM-DEFINITION-PATHNAME]279))) 1 0.0042 sbcl load_core_file 1 0.0042 sbcl op_do_write_native_code 1 0.0042 sbcl os_flush_icache 1 0.0042 sbcl os_invalidate 1 0.0042 sbcl scav_weak_pointer 1 0.0042 sbcl sigsegv_handler 1 0.0042 sbcl size_character_string 1 0.0042 sbcl trans_base_string 1 0.0042 sbcl trans_boxed 1 0.0042 sbcl trans_character_string 1 0.0042 sbcl trans_code 1 0.0042 sbcl trans_vector 1 0.0042 sbcl wrapped_readlink This patch is against 1.0.11.3. I can, and probably will, do something GITly about it. ---------------- 8< ------------------ diff --git a/build-order.lisp-expr b/build-order.lisp-expr index 09b1111..49a49c4 100644 --- a/build-order.lisp-expr +++ b/build-order.lisp-expr @@ -649,6 +649,7 @@ ;; compiled as part of the compiler ("src/code/late-extensions") ; needs condition system + #!+sb-oprofile ("src/code/heap-annotation" :not-host) ("src/compiler/generic/target-core" :not-host) ; uses stuff from ; "compiler/generic/core" diff --git a/contrib/asdf-module.mk b/contrib/asdf-module.mk index dc6a07a..2e2af24 100644 diff --git a/src/code/target-load.lisp b/src/code/target-load.lisp index 9ae8a46..1caeb8b 100644 --- a/src/code/target-load.lisp +++ b/src/code/target-load.lisp @@ -232,7 +232,8 @@ (code-instructions code) 0 code-length)) - code))) + #!+sb-oprofile (sb!kernel::oprofile-announce-code-object code code-length) + code))) ;;; Moving native code during a GC or purify is not so trivial on the ;;; x86 port. diff --git a/src/code/unix.lisp b/src/code/unix.lisp index 1fbb1c1..d988bb3 100644 --- a/src/code/unix.lisp +++ b/src/code/unix.lisp @@ -400,6 +400,7 @@ SYSCALL-FORM. Repeat evaluation of SYSCALL-FORM if it is interrupted." ;;; returns NIL and an error number. (defun unix-exit (&optional (code 0)) (declare (type (signed-byte 32) code)) + (sb!kernel::op-close-agent) (void-syscall ("exit" int) code)) ;;; Return the process id of the current process. diff --git a/src/compiler/generic/target-core.lisp b/src/compiler/generic/target-core.lisp index c07f5e5..20321ef 100644 --- a/src/compiler/generic/target-core.lisp +++ b/src/compiler/generic/target-core.lisp @@ -69,6 +69,7 @@ (make-fun-entry entry code-obj object)) (sb!vm:sanctify-for-execution code-obj) + #!+sb-oprofile (sb!kernel::oprofile-announce-code-object code-obj length) (let ((info (debug-info-for-component component))) (push info (core-object-debug-info object)) diff --git a/src/runtime/Config.x86_64-linux b/src/runtime/Config.x86_64-linux index 98d9787..24d22a6 100644 --- a/src/runtime/Config.x86_64-linux +++ b/src/runtime/Config.x86_64-linux @@ -34,6 +34,10 @@ ifdef LISP_FEATURE_SB_THREAD OS_LIBS += -lpthread endif +ifdef LISP_FEATURE_SB_OPROFILE + OS_LIBS += -L/usr/lib/oprofile -lopagent +endif + CFLAGS += -fno-omit-frame-pointer GC_SRC = gencgc.c diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index a4fc68a..03836f0 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -40,6 +40,10 @@ #include <time.h> #endif +#ifdef LISP_FEATURE_SB_OPROFILE +# include <libopagent.h> +#endif + #include "signal.h" #include "runtime.h" @@ -89,10 +93,30 @@ sigint_init(void) SHOW("leaving sigint_init()"); } + +#ifdef LISP_FEATURE_SB_OPROFILE + +boolean oprofile_support_requested = 0; +boolean oprofile_support_granted = 0; + +void op_do_write_native_code(char *name, void *addr, int size) +{ + if (oprofile_support_granted) { + op_write_native_code(name, addr, size); + } +} + +void op_do_unload_native_code(void *addr) +{ + if (oprofile_support_granted) + op_unload_native_code(addr); +} + +#endif + /* * helper functions for dealing with command line args */ - void * successful_malloc(size_t size) { @@ -279,6 +303,10 @@ main(int argc, char *argv[], char *envp[]) dynamic_space_size = strtol(argv[argi++], 0, 0) << 20; if (errno) lose("argument to --dynamic-space-size is not a number"); + } else if (0 == strcmp(arg, "--oprofile-support")) { + oprofile_support_requested = 1; + ++argi; + break; } else if (0 == strcmp(arg, "--debug-environment")) { int n = 0; printf("; Commandline arguments:\n"); @@ -394,6 +422,16 @@ main(int argc, char *argv[], char *envp[]) globals_init(); +#ifdef LISP_FEATURE_SB_OPROFILE + if (oprofile_support_requested) + if (op_open_agent() == 0) { + fprintf(stderr, "Successfully initialized libopagent.\n"); + oprofile_support_granted = 1; + } +#else +# error no worg +#endif + initial_function = load_core_file(core, embedded_core_offset); if (initial_function == NIL) { lose("couldn't find initial function\n"); diff --git a/tools-for-build/ldso-stubs.lisp b/tools-for-build/ldso-stubs.lisp index 5e1abdb..ed8edcf 100644 --- a/tools-for-build/ldso-stubs.lisp +++ b/tools-for-build/ldso-stubs.lisp @@ -309,6 +309,8 @@ ldso_stub__ ## fct: ; \\ "dlsym") #!+os-provides-dladdr '("dladdr") + #!+sb-oprofile + '("op_open_agent" "op_close_agent" "op_write_native_code" "op_unload_native_code") #!-sunos ;; !defined(SVR4) '("sigsetmask"))) regards, Samium "barely-sitting-after-a-24-hour-run" Gromoff [1]: References: Re: oprofile and jitted code -- proposal 1 http://osdir.com/ml/oprofile/2004-09/msg00064.html" http://osdir.com/ml/oprofile/2004-09/msg00078.html" http://osdir.com/ml/oprofile/2005-02/msg00015.html" http://osdir.com/ml/oprofile/2005-03/msg00003.html" http://osdir.com/ml/oprofile/2005-04/msg00112.html" http://osdir.com/ml/oprofile/2005-05/msg00040.html" Re: opreport support for not-C++ symbols http://osdir.com/ml/oprofile/2005-05/msg00006.html" Java patch status http://osdir.com/ml/oprofile/2005-11/msg00006.html" Re: Oprofile and jitted code current status http://osdir.com/ml/oprofile/2006-05/msg00042.html" Oprofile JIT Code Proposal http://marc.info/?t=117457985700003&r=1&w=2" 'Oprofile JIT enhancement questions' thread - MARC http://marc.info/?t=117890572200003&r=1&w=2" '[PATCH 0/6][RFC] Oprofile JIT code support' thread - MARC http://marc.info/?l=oprofile-list&m=118339904112463&w=2" 'Oprofile JIT code support, status' - MARC http://marc.info/?l=oprofile-list&m=118492820428228&w=2" 'Oprofile JIT support walkthrough' - MARC http://marc.info/?t=118469039900001&r=1&w=2" '[patch 0/9][RFC] Oprofile JIT support - Second RFC post against' thread - MARC http://marc.info/?t=118607754400013&r=1&w=2" '[PATCH RFC] OProfile JIT support -- JVMPI agent' thread - MARC< http://marc.info/?t=118737059600001&r=1&w=2" '[patch 0/6] Oprofile JIT support - Update' thread - MARC http://marc.info/?l=oprofile-list&r=1&b=200709&w=2" 'oprofile-list' list - MARC http://marc.info/?l=oprofile-list&m=119153730010597&w=2" [2]: Quitting SBCL is necessary, as the fake ELF file is produced upon libopagent session termination. Perhaps this is too annoying and a more graceful scheme can be devised. |