레이블이 벤치마킹인 게시물을 표시합니다. 모든 게시물 표시
레이블이 벤치마킹인 게시물을 표시합니다. 모든 게시물 표시

2010년 12월 25일 토요일

Oprofile을 이용한 CPU 자원 사용 프로파일링

Oprofile
• 실행중인 프로세스의 CPU Usage를 프로파일링
• 실행중인 프로세스의 어떤 함수가 CPU 자원을 많이 사용하는지를 식별
• Database 개발자에게 자주 사용됨
• 특정 함수가 많은 자원을 사용할 경우, 프로그램은 그 함수 콜을 줄일 수 있는 방법으로 재설계될 수 있음
• CPU 사용률이 낮은 장비(I/O 바운딩 서버나 Mutex 대기와 같은)에서는 별로 쓸모가 없음
• How to use
   – $ opcontrol --start (--no-vmlinux)
   – 여기에서 실제 벤치마킹 수행
   – $ opcontrol --dump
   – $ opcontrol --shutdown
   – $ opreport -l  /usr/local/bin/mysqld



실행 예제
[root@TestServer:/mysql/bin]$ opcontrol --start --no-vmlinux
Using default event: CPU_CLK_UNHALTED:100000:0:1:1
Using 2.6+ OProfile kernel interface.
Using log file /var/lib/oprofile/samples/oprofiled.log
Daemon started.
Profiler running.

## ------------------------------------------------------------
## Doing benchmarking here
## sysbnech ....
## ------------------------------------------------------------

[root@TestServer:/mysql/bin]$ opcontrol --dump

[root@TestServer:/mysql/bin]$ opcontrol --shutdown
Stopping profiling.
Killing daemon.

[root@TestServer:/mysql/bin]$ opreport -l /mysql/bin/mysqld
CPU: Core 2, speed 2394.05 MHz (estimated)
Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000
samples  %        symbol name
196      52.5469  sync_array_print_long_waits
156      41.8231  srv_lock_timeout_thread
19        5.0938  sync_array_get_nth_cell
1         0.2681  my_pthread_fastmutex_lock
1         0.2681  os_event_reset

Sysbench를 이용한 MySQL OLTP 성능 측정

# 벤치마킹용 데이터베이스 및 계정 생성
create database sysbench;

create user sysbench@'%' identified by 'sysbench';
create user sysbench@'localhost' identified by 'sysbench';
create user sysbench@'127.0.0.1' identified by 'sysbench';

grant all on sysbench.* to sysbench@'%';
grant all on sysbench.* to sysbench@'localhost';
grant all on sysbench.* to sysbench@'127.0.0.1';


# Sysbench building
$ wget http://downloads.sourceforge.net/project/sysbench/sysbench/0.4.12/sysbench-0.4.12.tar.gz?use_mirror=cdnetworks-kr-1
$ tar xvfz sysbench-0.4.12.tar.gz
$ cd sysbench-0.4.12
$ ./autogen.sh
$ ./configure --prefix=${SYSBENCH_HOME} --with-mysql-includes=${MYSQL_HOME}/include/mysql --with-mysql-libs=${MYSQL_HOME}/lib/mysql
$ make
$ make install


# 테스트를 위한 준비 (테이블 및 데이터 생성)
#  주어진 데이터베이스에 테스트용 테이블(default 테이블명은 sbtest)을 생성하고, 주어진 건수 만큼 레코드를 Insert
#  테스트용으로 만들어진 데이터를 초기화하는 방법은 sysbench 도구를 이용해도 되지만, 간단히 "drop table sbtest;"명령으로 삭제해도 됨
${SYSBENCH_HOME}/bin/sysbench --test=oltp --oltp-table-size=[테이블-레코드-건수] \
--max-requests=[쿼리-요청-개수] --max-time=[테스트-시간] \
--mysql-host=[호스트명] --mysql-db=[테스트-데이터베이스명] --mysql-user=[DB-USER] --mysql-password=[DB-USER-비밀번호] \
--mysql-table-engine=[테이블-엔진-종류] --myisam-max-rows=[MyISAM인 경우-레코드-최대-건수] --mysql-create-options= \
--mysql-socket=[MySQL-소켓-파일-경로] \
--mysql-port=[MySQL-포트-번호] \
--oltp-test-mode=[simple|complex|nontrx] \
--oltp-read-only=[on|off] \
prepare

예제)
./sysbench --test=oltp --oltp-table-size=10000000 --num-threads=8 \
--mysql-host=localhost --mysql-user=sysbench --mysql-password=sysbench \
--mysql-db=sysbench --mysql-table-engine=innodb --myisam-max-rows=10000000000 --mysql-create-options= \
--mysql-socket=/tmp/mysql.sock \
--oltp-test-mode=complex \
--oltp-read-only=off \
prepare

# 테스트 실행
${SYSBENCH_HOME}/bin/sysbench --test=oltp --oltp-table-size=[테이블-레코드-건수] --num-threads=[동시-스레드-개수] \
--max-requests=[쿼리-요청-개수] --max-time=[테스트-시간] \
--mysql-host=[호스트명] --mysql-user=[DB-USER] --mysql-password=[DB-USER-비밀번호] \
--mysql-db=[테스트-데이터베이스명] --mysql-table-engine=[테이블-엔진-종류] --mysql-create-options= \
--mysql-socket=[MySQL-소켓-파일-경로] \
--mysql-port=[MySQL-포트-번호] \
--oltp-test-mode=[simple|complex|nontrx] \
--oltp-read-only=[on|off] \
run

예제)
# 실행 회수 기반의 테스트 (시간 관계없이 10000번 요청 실행)
./sysbench --test=oltp --oltp-table-size=10000000 --num-threads=8 --max-requests=10000 --max-time=0 \
--mysql-host=localhost --mysql-user=sysbench --mysql-password=sysbench \
--mysql-db=sysbench --mysql-table-engine=innodb --mysql-create-options= \
--mysql-socket=/tmp/mysql.sock \
--mysql-port=20306 \
--oltp-test-mode=complex \
--oltp-read-only=off \
run

# 실행 시간 기반의 테스트 (요청 수에 관계 없이 20초 동안 실행)
./sysbench --test=oltp --oltp-table-size=10000000 --num-threads=8 --max-requests=0 --max-time=20 \
--mysql-host=localhost --mysql-user=sysbench --mysql-password=sysbench \
--mysql-db=sysbench --mysql-table-engine=innodb --mysql-create-options= \
--mysql-socket=/tmp/mysql.sock \
--mysql-port=20306 \
--oltp-test-mode=complex \
--oltp-read-only=off \
run

# 결과 분석
sysbench 0.4.12:  multi-threaded system evaluation benchmark
...
OLTP test statistics:
    queries performed:
        read:                            140014
        write:                           50005
        other:                           20002
        total:                           210021
    transactions:                        10001  (866.61 per sec.)   ==> 초당 트랜잭션 866 건
    deadlocks:                           0      (0.00 per sec.)
    read/write requests:                 190019 (16465.61 per sec.) ==> 초당 쿼리 실행 16465 건
    other operations:                    20002  (1733.22 per sec.)

Test execution summary:
...

# 테스트시 주의 사항
  • Sysbench 용 데이터를 prepare 한 후, 처음 실행하는 benchmark는 Buffer pool이 Warming-up되지 않았을 수 있음
  • 테스트하고자 하는 것이 CPU-Bound인지 I/O-Bound인지 명확히 구분하여,
    Buffer pool 사이즈와 --oltp-table-size를 적절히 조절해야 한다.
    일반적으로 InnoDB 스토리지 엔진 사용시, record건수가 10,000,000건인 경우 2.3G 정도의 ibd 파일이 생성되며,

    100,000,000 건인 경우 23G 정도의 ibd 파일이 생성됨
  • 이 테스트로 인해서 산출된 tpmC 값은 시스템의 특성(MySQL Configuration이나 RAID 및 디스크 설정, CPU, 메모리,...)에 
    따른 상대적인 값이므로, 동일 수준의 장비와 비교를 위한 수치만으로 고려해야 한다.
  • 매번 테스트 시나리오를 변경할 때에는, MySQL 서버를 재 시작시키는 것이 가장 좋으며,
    재시작시에는
        mysql> set global innodb_fast_shutdown=0;
        shell$> mysqladmin -uroot -p shutdown
    와 같이 Clean shutdown을 해주는 것이 테스트 간의 영향도를 최소화시킬 수 있는 방법이다.



## 참고 사항 (oltp-test-mode 의 설정값에 따른 테스트 케이스의 SQL 내용)
simple
  • ==> 단순히 아래 형태의 SELECT 쿼리만 실행
  • [필수] SELECT c FROM sbtest WHERE id=N;

complex (advanced transactional)
  • ==> 아래의 쿼리들중에서 M개를 선별하여 쿼리 실행
  • [필수] BEGIN;
  • [옵션] SELECT c FROM sbtest WHERE id=N;
  • [옵션] SELECT c FROM sbtest WHERE id BETWEEN N AND M;
  • [옵션] SELECT SUM(K) FROM sbtest WHERE id BETWEEN N and M;
  • [옵션] SELECT c FROM sbtest WHERE id between N and M ORDER BY c;
  • [옵션] SELECT DISTINCT c FROM sbtest WHERE id BETWEEN N and M ORDER BY c;
  • [옵션] UPDATE sbtest SET k=k+1 WHERE id=N;
  • [옵션] UPDATE sbtest SET c=N WHERE id=M;
  • [옵션] DELETE FROM sbtest WHERE id=N;
  • [옵션] INSERT INTO sbtest VALUES (...);
  • [필수] COMMIT;