2009-08-08 17 views
22

Tôi có một số đoạn mã bằng cách sử dụng PThreads trên Linux mà, tôi nghi ngờ, đang bị tranh chấp khóa quá mức. Những công cụ nào có sẵn để tôi đo lường điều này?Làm thế nào để đo lường sự tranh chấp mutex?

Solaris có DTrace và plockstat. Có cái gì đó tương tự trên Linux? (Tôi biết về một cổng DTrace gần đây cho Linux nhưng nó dường như chưa sẵn sàng cho thời gian chính).

Trả lời

1

Trong trường hợp không có DTrace, đặt cược tốt nhất của bạn có lẽ là SystemTap. Đây là một bài viết tích cực.

http://davidcarterca.wordpress.com/2009/05/27/systemtap/

+0

Tôi e rằng bài đăng trên blog đề cập rõ ràng rằng nó không hữu ích khi đo lường tranh chấp khóa. –

+2

Trong bình luận, anh nói anh không cố giải quyết các ký hiệu. – Eugene

+0

Điểm tốt, tôi sẽ thử. –

4

Sau khi không có nhiều may mắn với SystemTap, tôi quyết định thử và sử dụng DTrace Linux port với một số thành công, bất chấp việc thiếu một nhà cung cấp plockstat. Tập lệnh DTrace sau đây không hoàn toàn là thay thế plockstat nhưng nó đã quản lý để hiển thị cho tôi một số thông tin tôi đã theo dõi.

#!/usr/sbin/dtrace -s 

/* Usage: ./futex.d '"execname"' */ 

long total; 

END 
{ 
    printf("total time spent on futex(): %ldms\n", total); 
} 

/* arg1 == 0 means FUTEX_WAIT */ 
syscall::futex:entry 
/execname == $1 && arg1 == 0/ 
{ 
    self->start = timestamp; 
} 

syscall::futex:return 
/self->start/ 
{ 
    this->elapsed = (timestamp - self->start)/1000000; 
    @[execname] = quantize(this->elapsed); 
    total += this->elapsed; 
    self->start = 0; 
} 

Dưới đây là một ví dụ sử dụng kịch bản DTrace trên để đo thời gian dành cho FUTEX_WAIT cho một chương trình thử nghiệm đơn giản từ DTrace article này.

$ ./futex.d '"mutex-test"' 
dtrace: script './futex.d' matched 3 probes 
^C 
CPU  ID     FUNCTION:NAME 
    1  2        :END total time spent on futex(): 11200ms 


    mutex-test           
      value ------------- Distribution ------------- count  
      128 |           0   
      256 |@@@@@@@@@@@@@@@@@@@@      1   
      512 |           0   
      1024 |           0   
      2048 |           0   
      4096 |           0   
      8192 |@@@@@@@@@@@@@@@@@@@@      1   
      16384 |           0   

Chắc chắn không tuyệt vời, nhưng ít nhất đó là điểm khởi đầu.

4

valgrind phiên bản mới nhất có ganh khóa và các công cụ xác nhận khóa:

http://valgrind.org/docs/manual/drd-manual.html

Đó là tuyệt vời nếu bạn có thể tạo ra các vấn đề dưới Valgrind (nó ảnh hưởng tốc độ mã thời gian chạy) và có đủ bộ nhớ để chạy Valgrind.

Đối với các ứng dụng khác, lõi cứng hơn Linux Trace Toolkit NG được đề nghị:

http://ltt.polymtl.ca/

Chúc mừng, Gilad

+0

Cảm ơn bạn đã đề xuất nhưng valgrind thực sự không thích ứng dụng tôi đang thử nghiệm và thực sự nhanh chóng. –

4

Phiên bản mới nhất của systemtap đi kèm với rất nhiều example scripts. Một đặc biệt có vẻ như nó sẽ máy chủ như là một điểm khởi đầu tốt cho việc giúp bạn hoàn thành nhiệm vụ của bạn:

#! /usr/bin/env stap 

global thread_thislock 
global thread_blocktime 
global FUTEX_WAIT = 0 

global lock_waits 
global process_names 

probe syscall.futex { 
    if (op != FUTEX_WAIT) next 
    t = tid() 
    process_names[pid()] = execname() 
    thread_thislock[t] = $uaddr 
    thread_blocktime[t] = gettimeofday_us() 
} 

probe syscall.futex.return { 
    t = tid() 
    ts = thread_blocktime[t] 
    if (ts) { 
    elapsed = gettimeofday_us() - ts 
    lock_waits[pid(), thread_thislock[t]] <<< elapsed 
    delete thread_blocktime[t] 
    delete thread_thislock[t] 
    } 
} 

probe end { 
    foreach ([pid+, lock] in lock_waits) 
    printf ("%s[%d] lock %p contended %d times, %d avg us\n", 
      process_names[pid], pid, lock, @count(lock_waits[pid,lock]), 
      @avg(lock_waits[pid,lock])) 
} 

Tôi đã cố gắng để chẩn đoán một cái gì đó tương tự với một quá trình MySQL trước và đầu ra quan sát tương tự như sau bằng cách sử dụng kịch bản ở trên :

mysqld[3991] lock 0x000000000a1589e0 contended 45 times, 3 avg us 
mysqld[3991] lock 0x000000004ad289d0 contended 1 times, 3 avg us 

Trong khi tập lệnh trên thu thập thông tin về tất cả các quá trình đang chạy trên hệ thống, sẽ dễ dàng sửa đổi để chỉ hoạt động trên một quy trình nhất định hoặc có thể thực thi. Ví dụ, chúng ta có thể thay đổi kịch bản để có một cuộc tranh luận quá trình ID và sửa đổi các thăm dò trên vào cuộc gọi futex để trông giống như:

probe begin { 
    process_id = strtol(@1, 10) 
} 

probe syscall.futex { 
    if (pid() == process_id && op == FUTEX_WAIT) { 
    t = tid() 
    process_names[process_id] = execname() 
    thread_thislock[t] = $uaddr 
    thread_blocktime[t] = gettimeofday_us() 
    } 
} 

Rõ ràng, bạn có thể thay đổi rất nhiều kịch bản cách để phù hợp với những gì bạn muốn làm. Tôi khuyến khích bạn xem xét các kịch bản mẫu khác nhau cho SystemTap. Họ có lẽ là điểm khởi đầu tốt nhất.

13

mutrace là công cụ: http://0pointer.de/blog/projects/mutrace.html

dễ dàng để xây dựng, cài đặt và sử dụng của nó.

+0

Mã nguồn dường như không còn ở đó nữa, nhưng ở đây: https://github.com/dbpercona/mutrace –

+0

Mã của Lennart có thể tìm thấy tại: http://git.0pointer.net/mutrace.git/ – stsquad