2010-01-12 32 views
3

我有一個用Ruby和C編寫的程序.C部分是一個共享庫,它是Ruby程序的擴展。我想使用gprof來描述我編寫的C共享庫。我編譯共享庫這樣的:配置一個由Ruby程序調用的C共享庫程序

gcc -I. -I/usr/lib/ruby/1.8/i486-linux -I/usr/lib/ruby/1.8/i486-linux -I. -D_FILE_OFFSET_BITS=64 -fPIC -fno-strict-aliasing -g -march=i686 -O2 -ggdb -pg -fPIC -c extension.c 
gcc -shared -o extension.so extension.o -L. -L/usr/lib -L. -Wl,-Bsymbolic-functions -rdynamic -Wl,-export-dynamic -lruby1.8 -lpthread -lrt -ldl -lcrypt -lm -lc 

然後我執行Ruby程序,它加載該共享庫,我期望在當前目錄下的文件是gmon.out,但由於某些原因,該文件是gmon.out沒有被創建。我該怎麼做呢?

我爲此搜索了一下,但找不到滿意的答案(哪些工作)。

P.S. - 作爲一種解決方法,我可以有一個修改版本的擴展,它是一個純粹的C程序(而不是創建爲共享庫),我可以使用它進行配置文件,但是維護相同C擴展的兩個版本變得繁瑣兩者之間的大量差異)。

我試着寫了一個C程序,它也直接使用共享庫。我立即在共享庫初始化期間調用的一個ruby庫函數中發生頁面錯誤。我認爲它真的希望從一個Ruby程序加載,這可能會在內部做一些魔術。

(gdb) bt 
#0 0x0091556e in st_lookup() from /usr/lib/libruby1.8.so.1.8 
#1 0x008e87c2 in rb_intern() from /usr/lib/libruby1.8.so.1.8 
#2 0x008984a5 in rb_define_module() from /usr/lib/libruby1.8.so.1.8 
#3 0x08048dd0 in Init_SimilarStr() at extension.c:542 
#4 0x0804933e in main (argc=2, argv=0xbffff454) at extension.c:564 

更新:沒關係。我使用#ifdef來編譯擴展的Ruby部分並獲取配置文件。關閉。

+0

萬一有人在尋找答案;我認爲-pg也應該傳遞給鏈接器命令;即'gcc -shared -o extension.so extension.o -L。 -L/usr/lib -L。 -W1,-Bsymbolic-functions -rdynamic -Wl,-export-dynamic -lruby1。8 -lpthread -lrt -ldl -lcrypt -lm -lc -pg' – dashesy 2012-05-15 19:02:56

+0

我希望你不會因爲你找到答案而關閉這個問題。這對其他人也很有用。 – 2013-09-26 14:43:23

回答

1

在這種情況下,我發現oprofile是比gprof更好的選擇。 reports from oprofile更全面。我使用#ifndef PROFILE從C擴展中編譯了引起seg-fault的ruby部分(並非全部都是),並用非ruby代碼替換它們。我在擴展中寫了一個main()例程來調用擴展中的函數。然後,我設置了一個makefile來將擴展程序編譯爲一個定義了PROFILE的C程序。然後我installed oprofile on Ubuntu。寫了這個腳本。

#!/bin/bash 
sudo opcontrol --reset 
sudo opcontrol --start 
./a.out Rome Damascus NewYork Delhi Bangalore 
sudo opcontrol --shutdown 
opreport -lt1 

編譯了一個程序,並執行上面的腳本,這給從「opreport」命令類似這樣的輸出:

... 
... 
Killing daemon. 
warning: /no-vmlinux could not be found. 
warning: [vdso] (tgid:10675 range:0x920000-0x921000) could not be found. 
warning: [vdso] (tgid:1270 range:0xba1000-0xba2000) could not be found. 
warning: [vdso] (tgid:1675 range:0x973000-0x974000) could not be found. 
warning: [vdso] (tgid:1711 range:0x264000-0x265000) could not be found. 
warning: [vdso] (tgid:1737 range:0x990000-0x991000) could not be found. 
warning: [vdso] (tgid:2477 range:0xa53000-0xa54000) could not be found. 
warning: [vdso] (tgid:5658 range:0x7ae000-0x7af000) could not be found. 
CPU: Core Solo/Duo, speed 1000 MHz (estimated) 
Counted CPU_CLK_UNHALTED events (Unhalted clock cycles) with a unit mask of 0x00 (Unhalted core cycles) count 100000 
samples %  app name     symbol name 
12731 32.8949 a.out     levenshtein 
11958 30.8976 a.out     corpora_pass2 
5231  13.5161 no-vmlinux    /no-vmlinux 
4021  10.3896 a.out     corpora_pass1 
1733  4.4778 libc-2.10.1.so   /lib/tls/i686/cmov/libc-2.10.1.so 
542  1.4004 ld-2.10.1.so    /lib/ld-2.10.1.so 
398  1.0284 a.out     method_top_matches 

在那裏,它是:頂級消費是函數萊文斯坦()。我通過另一個命令跟着這個來生成反彙編的輸出,註釋了每行的源代碼和執行次數/時間。這看起來是這樣的(數/時間上的每個執行行左起):

> opannotate --source --assembly ./a.out > report.as.handcoded.1 
> cat report.as.handcoded.1 

... 
... 
... 
      :   __asm__ (
2 0.0069 : 804918a:  mov -0x50(%ebp),%ecx 
4 0.0137 : 804918d:  mov -0x54(%ebp),%ebx 
      : 8049190:  mov -0x4c(%ebp),%eax 
12 0.0412 : 8049193:  cmp %eax,%ecx 
10 0.0344 : 8049195:  cmovbe %ecx,%eax 
8 0.0275 : 8049198:  cmp %eax,%ebx 
11 0.0378 : 804919a:  cmovbe %ebx,%eax 
16 0.0550 : 804919d:  mov %eax,-0x4c(%ebp) 
      :     "cmp  %0, %2\n\t" 
      :     "cmovbe %2, %0\n\t" 
      :     : "+r"(a) : 
      :     "%r"(b), "r"(c) 
      :     ); 
      :   return a; 
... 
... 
... 
0

您可以通過分析器運行ruby解釋器本身。如果這太多了,寫一個加載共享庫並調用其導出函數的小型C程序。然後配置C程序。它可以讓您免於維護庫的兩個版本。

+0

是的,我想我可以描述紅寶石解釋器本身 - 除了也許我會經歷很多我不感興趣的cruft。我認爲可以簡單地配置共享庫本身,因爲我google搜索到了參考這表明這是可能的。除了我沒有得到一個權威的鏈接,告訴我如何做到這一點。 – Sudhanshu 2010-01-12 07:57:20

1

你可以做得比gprof的。考慮stackshots。你可以使用pstack,lsstack(如果你能得到它),或者通過在調試器下手動暫停。 Here's a short intro to the technique.

+0

邁克,是不是每個指令計數+時間,由opannotate程序給出或多或少相同的技術(請參閱我自己的答案在這裏),你在那裏描述? – Sudhanshu 2010-01-12 14:23:08

+0

@Sudhanshu:我只是看着oprofile文檔,我不確定,但看起來它接近我認爲需要的東西。它確實採樣了調用堆棧,但我無法確定它是否在掛鐘時間採樣。 (有些配置文件在系統調用期間不會進行採樣,並且這沒有用處。)然後,如果它在調用站點(或普通指令)上顯示的數字是包含該調用站點的樣本的一小部分,那麼它的做法是正確的。另一個這樣做的分析器是RotateRight/Zoom。 – 2010-01-12 14:43:02

+0

...它需要做的另一件事是讓你控制它什麼時候抽樣,什麼時候不抽樣(比如當它在等待用戶輸入時)。 – 2010-01-12 15:45:48