From: Marc Alff Date: May 24 2010 5:08pm Subject: bzr commit into mysql-next-mr branch (marc.alff:3146) List-Archive: http://lists.mysql.com/commits/109082 Message-Id: <201005241709.o4OCtvb6012226@rcsinet13.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============6478942045304103938==" --===============6478942045304103938== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/malff/BZR_TREE/mysql-next-mr-bench/ based on revid:alik@stripped 3146 Marc Alff 2010-05-24 benchmarks, base 5.5 added: storage/perfschema/unittest/pfs_benchmark-t.cc modified: storage/perfschema/pfs.cc storage/perfschema/pfs_timer.cc storage/perfschema/pfs_timer.h storage/perfschema/unittest/CMakeLists.txt === modified file 'storage/perfschema/pfs.cc' --- a/storage/perfschema/pfs.cc 2010-04-19 12:26:29 +0000 +++ b/storage/perfschema/pfs.cc 2010-05-24 17:07:58 +0000 @@ -1491,7 +1491,7 @@ static void unlock_mutex_v1(PSI_thread * if (pfs_mutex->m_class->m_timed) { ulonglong locked_time; - locked_time= get_timer_value(wait_timer) - pfs_mutex->m_last_locked; + locked_time= get_timer_pico_value(wait_timer) - pfs_mutex->m_last_locked; aggregate_single_stat_chain(&pfs_mutex->m_lock_stat, locked_time); } #endif @@ -1558,7 +1558,7 @@ static void unlock_rwlock_v1(PSI_thread { if (pfs_rwlock->m_class->m_timed) { - locked_time= get_timer_value(wait_timer) - pfs_rwlock->m_last_written; + locked_time= get_timer_pico_value(wait_timer) - pfs_rwlock->m_last_written; aggregate_single_stat_chain(&pfs_rwlock->m_write_lock_stat, locked_time); } } @@ -1566,7 +1566,7 @@ static void unlock_rwlock_v1(PSI_thread { if (pfs_rwlock->m_class->m_timed) { - locked_time= get_timer_value(wait_timer) - pfs_rwlock->m_last_read; + locked_time= get_timer_pico_value(wait_timer) - pfs_rwlock->m_last_read; aggregate_single_stat_chain(&pfs_rwlock->m_read_lock_stat, locked_time); } } @@ -1598,7 +1598,7 @@ static void start_mutex_wait_v1(PSI_mute PFS_events_waits *wait= &pfs_locker->m_waits_current; if (wait->m_timer_state == TIMER_STATE_STARTING) { - wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_start= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_STARTED; } wait->m_source_file= src_file; @@ -1613,7 +1613,7 @@ static void end_mutex_wait_v1(PSI_mutex_ if (wait->m_timer_state == TIMER_STATE_STARTED) { - wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_end= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_TIMED; } if (flag_events_waits_history) @@ -1647,7 +1647,7 @@ static void start_rwlock_rdwait_v1(PSI_r PFS_events_waits *wait= &pfs_locker->m_waits_current; if (wait->m_timer_state == TIMER_STATE_STARTING) { - wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_start= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_STARTED; } wait->m_source_file= src_file; @@ -1662,7 +1662,7 @@ static void end_rwlock_rdwait_v1(PSI_rwl if (wait->m_timer_state == TIMER_STATE_STARTED) { - wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_end= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_TIMED; } if (flag_events_waits_history) @@ -1704,7 +1704,7 @@ static void start_rwlock_wrwait_v1(PSI_r PFS_events_waits *wait= &pfs_locker->m_waits_current; if (wait->m_timer_state == TIMER_STATE_STARTING) { - wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_start= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_STARTED; } wait->m_source_file= src_file; @@ -1719,7 +1719,7 @@ static void end_rwlock_wrwait_v1(PSI_rwl if (wait->m_timer_state == TIMER_STATE_STARTED) { - wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_end= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_TIMED; } if (flag_events_waits_history) @@ -1756,7 +1756,7 @@ static void start_cond_wait_v1(PSI_cond_ PFS_events_waits *wait= &pfs_locker->m_waits_current; if (wait->m_timer_state == TIMER_STATE_STARTING) { - wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_start= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_STARTED; } wait->m_source_file= src_file; @@ -1771,7 +1771,7 @@ static void end_cond_wait_v1(PSI_cond_lo if (wait->m_timer_state == TIMER_STATE_STARTED) { - wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_end= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_TIMED; } if (flag_events_waits_history) @@ -1817,7 +1817,7 @@ static void start_table_wait_v1(PSI_tabl PFS_events_waits *wait= &pfs_locker->m_waits_current; if (wait->m_timer_state == TIMER_STATE_STARTING) { - wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_start= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_STARTED; } wait->m_source_file= src_file; @@ -1838,7 +1838,7 @@ static void end_table_wait_v1(PSI_table_ if (wait->m_timer_state == TIMER_STATE_STARTED) { - wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_end= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_TIMED; } if (flag_events_waits_history) @@ -1924,7 +1924,7 @@ static void start_file_wait_v1(PSI_file_ PFS_events_waits *wait= &pfs_locker->m_waits_current; if (wait->m_timer_state == TIMER_STATE_STARTING) { - wait->m_timer_start= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_start= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_STARTED; } wait->m_source_file= src_file; @@ -1942,7 +1942,7 @@ static void end_file_wait_v1(PSI_file_lo wait->m_number_of_bytes= count; if (wait->m_timer_state == TIMER_STATE_STARTED) { - wait->m_timer_end= get_timer_value(pfs_locker->m_timer_name); + wait->m_timer_end= get_timer_pico_value(pfs_locker->m_timer_name); wait->m_timer_state= TIMER_STATE_TIMED; } if (flag_events_waits_history) === modified file 'storage/perfschema/pfs_timer.cc' --- a/storage/perfschema/pfs_timer.cc 2010-04-19 12:26:29 +0000 +++ b/storage/perfschema/pfs_timer.cc 2010-05-24 17:07:58 +0000 @@ -90,11 +90,34 @@ void init_timers(void) tick_to_pico= 0; } -ulonglong get_timer_value(enum_timer_name timer_name) +ulonglong get_timer_raw_value(enum_timer_name timer_name) { ulonglong result; - switch (timer_name) { + switch (timer_name) + { + case TIMER_NAME_CYCLE: + return my_timer_cycles(); + case TIMER_NAME_NANOSEC: + return my_timer_nanoseconds(); + case TIMER_NAME_MICROSEC: + return my_timer_microseconds(); + case TIMER_NAME_MILLISEC: + return my_timer_milliseconds(); + case TIMER_NAME_TICK: + return my_timer_ticks(); + default: + DBUG_ASSERT(false); + } + return 0; +} + +ulonglong get_timer_pico_value(enum_timer_name timer_name) +{ + ulonglong result; + + switch (timer_name) + { case TIMER_NAME_CYCLE: result= (my_timer_cycles() - cycle_v0) * cycle_to_pico; break; === modified file 'storage/perfschema/pfs_timer.h' --- a/storage/perfschema/pfs_timer.h 2010-04-19 12:26:29 +0000 +++ b/storage/perfschema/pfs_timer.h 2010-05-24 17:07:58 +0000 @@ -28,7 +28,8 @@ extern MY_TIMER_INFO pfs_timer_info; void init_timers(); -ulonglong get_timer_value(enum_timer_name timer_name); +ulonglong get_timer_pico_value(enum_timer_name timer_name); +ulonglong get_timer_raw_value(enum_timer_name timer_name); #endif === modified file 'storage/perfschema/unittest/CMakeLists.txt' --- a/storage/perfschema/unittest/CMakeLists.txt 2010-01-14 18:42:28 +0000 +++ b/storage/perfschema/unittest/CMakeLists.txt 2010-05-24 17:07:58 +0000 @@ -35,6 +35,7 @@ SET(tests pfs_instr pfs_instr-oom pfs + pfs_benchmark ) FOREACH(testname ${tests}) PFS_ADD_TEST(${testname}) === added file 'storage/perfschema/unittest/pfs_benchmark-t.cc' --- a/storage/perfschema/unittest/pfs_benchmark-t.cc 1970-01-01 00:00:00 +0000 +++ b/storage/perfschema/unittest/pfs_benchmark-t.cc 2010-05-24 17:07:58 +0000 @@ -0,0 +1,340 @@ +/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "my_global.h" +#include "my_pthread.h" +#include "pfs_timer.h" +#include "pfs_server.h" +#include "pfs_events_waits.h" +#include "pfs_instr_class.h" +#include "mysql/psi/psi.h" +#include "mysql/psi/mysql_thread.h" +#include "my_sys.h" +#include "tap.h" + +static PFS_mutex_class *bench_mutex_class= NULL; +static mysql_mutex_t bench_mutex; +static PSI_mutex_key bench_mutex_key; +PSI_mutex_info all_bench_mutexes[]= +{ + { & bench_mutex_key, "benchmark", 0} +}; + +static PFS_rwlock_class *bench_rwlock_class= NULL; +static mysql_rwlock_t bench_rwlock; +static PSI_rwlock_key bench_rwlock_key; +PSI_rwlock_info all_bench_rwlocks[]= +{ + { & bench_rwlock_key, "benchmark", 0} +}; + +static PFS_cond_class *bench_cond_class= NULL; +static mysql_cond_t bench_cond; +static PSI_cond_key bench_cond_key; +PSI_cond_info all_bench_conds[]= +{ + { & bench_cond_key, "benchmark", 0} +}; + +static PSI_thread_key key_thread_main; +static PSI_thread_info all_bench_threads[]= +{ + { & key_thread_main, "main", 0} +}; + +static void setup() +{ + PFS_global_param param; + param.m_enabled= true; + param.m_mutex_class_sizing= 10; + param.m_rwlock_class_sizing= 10; + param.m_cond_class_sizing= 10; + param.m_thread_class_sizing= 10; + param.m_table_share_sizing= 10; + param.m_file_class_sizing= 10; + param.m_mutex_sizing= 10; + param.m_rwlock_sizing= 10; + param.m_cond_sizing= 10; + param.m_thread_sizing= 10; + param.m_table_sizing= 10; + param.m_file_sizing= 10; + param.m_file_handle_sizing= 10; + param.m_events_waits_history_sizing= 10; + param.m_events_waits_history_long_sizing= 1000; + + PSI_bootstrap *boot; + boot= initialize_performance_schema(& param); + ok(boot != NULL, "boot"); + ok(boot->get_interface != NULL, "boot->get_interface"); + + PSI_server= (PSI*) boot->get_interface(PSI_CURRENT_VERSION); + ok(PSI_server != NULL, "current version"); + + PSI_server->register_mutex("unittest", all_bench_mutexes, 1); + PSI_server->register_rwlock("unittest", all_bench_rwlocks, 1); + PSI_server->register_cond("unittest", all_bench_conds, 1); + PSI_server->register_thread("unittest", all_bench_threads, 1); + + PSI_thread *psi= PSI_server->new_thread(key_thread_main, NULL, 0); + ok(psi != NULL, "main thread"); + PSI_server->set_thread(psi); + + mysql_mutex_init(bench_mutex_key, & bench_mutex, MY_MUTEX_INIT_FAST); + bench_mutex_class= find_mutex_class(bench_mutex_key); + ok(bench_mutex_class != NULL, "mutex class"); + + mysql_rwlock_init(bench_rwlock_key, & bench_rwlock); + bench_rwlock_class= find_rwlock_class(bench_rwlock_key); + ok(bench_rwlock_class != NULL, "rwlock class"); + + mysql_cond_init(bench_cond_key, & bench_cond, NULL); + bench_cond_class= find_cond_class(bench_cond_key); + ok(bench_cond_class != NULL, "cond class"); +} + +static void teardown() +{ + mysql_mutex_destroy(& bench_mutex); + mysql_rwlock_destroy(& bench_rwlock); + mysql_cond_destroy(& bench_cond); + shutdown_performance_schema(); +} + +void benchmark_mutex(bool timed, uint count, const char *test) +{ + ulonglong timer_start; + ulonglong timer_end; + ulonglong timer_cycles; + + mysql_mutex_t *that= & bench_mutex; + + timer_start= get_timer_raw_value(TIMER_NAME_CYCLE); + + uint i; + for (i= 0 ; im_psi)) + { + locker= PSI_server->get_thread_mutex_locker(that->m_psi, PSI_MUTEX_LOCK); + if (likely(locker != NULL)) + PSI_server->start_mutex_wait(locker, __FILE__, __LINE__); + } + result= 0; + if (likely(locker != NULL)) + PSI_server->end_mutex_wait(locker, result); + } + + /* MYSQL_MUTEX_UNLOCK */ + { + struct PSI_thread *thread; + if (likely(PSI_server && that->m_psi)) + { + thread= PSI_server->get_thread(); + if (likely(thread != NULL)) + PSI_server->unlock_mutex(thread, that->m_psi); + } + } + } + + timer_end= get_timer_raw_value(TIMER_NAME_CYCLE); + timer_cycles= timer_end-timer_start; + + diag("MUTEX benchmark: %s (%s), %d calls, %13llu cycles, %13llu avg", + test, (timed ? "timed" : "counted"), + count, timer_cycles, timer_cycles/count); +} + +void benchmark_rwlock(bool timed, uint count, const char *test) +{ + ulonglong timer_start; + ulonglong timer_end; + ulonglong timer_cycles; + + mysql_rwlock_t *that= & bench_rwlock; + + timer_start= get_timer_raw_value(TIMER_NAME_CYCLE); + + uint i; + for (i= 0 ; im_psi)) + { + locker= PSI_server->get_thread_rwlock_locker(that->m_psi, + PSI_RWLOCK_READLOCK); + if (likely(locker != NULL)) + PSI_server->start_rwlock_rdwait(locker, __FILE__, __LINE__); + } + if (likely(locker != NULL)) + PSI_server->end_rwlock_rdwait(locker, result); + } + + /* MYSQL_RWLOCK_UNLOCK */ + { + struct PSI_thread *thread; + if (likely(PSI_server && that->m_psi)) + { + thread= PSI_server->get_thread(); + if (likely(thread != NULL)) + PSI_server->unlock_rwlock(thread, that->m_psi); + } + } + } + + timer_end= get_timer_raw_value(TIMER_NAME_CYCLE); + timer_cycles= timer_end-timer_start; + + diag("RWLOCK benchmark: %s (%s), %d calls, %13llu cycles, %13llu avg", + test, (timed ? "timed" : "counted"), + count, timer_cycles, timer_cycles/count); +} + +void benchmark_cond(bool timed, uint count, const char *test) +{ + ulonglong timer_start; + ulonglong timer_end; + ulonglong timer_cycles; + + mysql_cond_t *that= & bench_cond; + mysql_mutex_t *mutex= & bench_mutex; + + timer_start= get_timer_raw_value(TIMER_NAME_CYCLE); + + uint i; + for (i= 0 ; im_psi)) + { + thread= PSI_server->get_thread(); + if (likely(thread != NULL)) + PSI_server->signal_cond(thread, that->m_psi); + } + } + + /* MYSQL_COND_BRAODCAST */ + { + struct PSI_thread *thread; + if (likely(PSI_server && that->m_psi)) + { + thread= PSI_server->get_thread(); + if (likely(thread != NULL)) + PSI_server->broadcast_cond(thread, that->m_psi); + } + } + + /* MYSQL_COND_WAIT */ + { + int result= 0; + struct PSI_cond_locker *locker= NULL; + if (likely(PSI_server && that->m_psi)) + { + locker= PSI_server->get_thread_cond_locker(that->m_psi, mutex->m_psi, + PSI_COND_WAIT); + if (likely(locker != NULL)) + PSI_server->start_cond_wait(locker, __FILE__, __LINE__); + } + if (likely(locker != NULL)) + PSI_server->end_cond_wait(locker, result); + } + } + + timer_end= get_timer_raw_value(TIMER_NAME_CYCLE); + timer_cycles= timer_end-timer_start; + + diag("COND benchmark: %s (%s), %d calls, %13llu cycles, %13llu avg", + test, (timed ? "timed" : "counted"), + count, timer_cycles, timer_cycles/count); +} + +void benchmark_all(bool timed, const char *test) +{ + benchmark_mutex(timed, 1, test); + benchmark_rwlock(timed, 1, test); + benchmark_cond(timed, 1, test); + + benchmark_mutex(timed, 1000, test); + benchmark_rwlock(timed, 1000, test); + benchmark_cond(timed, 1000, test); + + benchmark_mutex(timed, 1000000, test); + benchmark_rwlock(timed, 1000000, test); + benchmark_cond(timed, 1000000, test); + + benchmark_mutex(timed, 10000000, test); + benchmark_rwlock(timed, 10000000, test); + benchmark_cond(timed, 10000000, test); +} + +void test_all(bool timed) +{ + flag_events_waits_current= true; + flag_events_waits_history= true; + flag_events_waits_history_long= true; + flag_events_waits_summary_by_thread_by_event_name= true; + flag_events_waits_summary_by_event_name= true; + flag_events_waits_summary_by_instance= true; + flag_file_summary_by_event_name= true; + flag_file_summary_by_instance= true; + + bench_mutex_class->m_timed= timed; + bench_rwlock_class->m_timed= timed; + bench_cond_class->m_timed= timed; + + benchmark_all(timed, "bigbang"); + + flag_events_waits_history= false; + flag_events_waits_history_long= false; + + benchmark_all(timed, "no history"); + + flag_events_waits_summary_by_thread_by_event_name= false; + flag_events_waits_summary_by_event_name= false; + flag_events_waits_summary_by_instance= false; + flag_file_summary_by_event_name= false; + flag_file_summary_by_instance= false; + + benchmark_all(timed, "current"); + + flag_events_waits_current= false; + + benchmark_all(timed, "nothing"); +} + +void do_all_tests() +{ + test_all(true); + test_all(false); +} + +int main(int, char **) +{ + plan(5); + MY_INIT("pfs_benchmark-t"); + setup(); + do_all_tests(); + teardown(); + return 0; +} + --===============6478942045304103938== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/marc.alff@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: marc.alff@stripped # target_branch: file:///Users/malff/BZR_TREE/mysql-next-mr-bench/ # testament_sha1: 9b85bc4b4e6691da517aebb46ece5164aef33aa2 # timestamp: 2010-05-24 11:08:05 -0600 # base_revision_id: alik@stripped # # Begin bundle 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 bUBxOgA= --===============6478942045304103938==--