Today’s blog post starts with a question:
“In my continuous integration environment, running tests currently takes 30 minutes. I
believe that a large percentage of time is spent in MySQL, and I want to know if putting MySQL
on tmpfs will cut that time down?”.
I have previously written about how to configure MySQL to be less durable in testing environments, but today I wanted to write about how we can really test the assumption that the question is based around. That is to say:
- We know that total time is 30 minutes.
- We assume MySQL is a large percentage of this.
- We know that this optimization will potentially allow us to avoid IO.
- We then want to know what amount of time MySQL spends waiting on IO during our test suite?
And the answer to this is performance schema.
Performance Schema instruments File IO with statistics such as bytes read/written, and wait time. So if we see that IO wait time was only a small percentage of the 30 minutes of test time, we automatically know if this optimization is worth investigating or not.
Here is a simple query that will work on 5.6 out of the box:
mysql> SELECT
`a`.`EVENT_NAME`,
`a`.`SUM_TIMER_WAIT`/1024/1024/1024 AS `total_latency_ms`,
`b`.`SUM_NUMBER_OF_BYTES_READ` AS `total_bytes_read`,
`b`.`SUM_NUMBER_OF_BYTES_WRITE` AS `total_bytes_written`
FROM
`performance_schema`.`events_waits_summary_global_by_event_name` `a`
INNER JOIN `performance_schema`.`file_summary_by_event_name` `b` USING (event_name)
WHERE
`a`.`EVENT_NAME` like 'wait/io/file/%'
AND `a`.`COUNT_STAR` > 0\G
*************************** 1. row ***************************
EVENT_NAME: wait/io/file/sql/casetest
total_latency_ms: 0.245716745034
total_bytes_read: 0
total_bytes_written: 0
*************************** 2. row ***************************
EVENT_NAME: wait/io/file/sql/ERRMSG
total_latency_ms: 0.911862457171
total_bytes_read: 58982
total_bytes_written: 0
*************************** 3. row ***************************
EVENT_NAME: wait/io/file/sql/FRM
total_latency_ms: 50.292402482592
total_bytes_read: 137771
total_bytes_written: 0
*************************** 4. row ***************************
EVENT_NAME: wait/io/file/sql/global_ddl_log
total_latency_ms: 0.012274521403
total_bytes_read: 0
total_bytes_written: 0
*************************** 5. row ***************************
EVENT_NAME: wait/io/file/sql/pid
total_latency_ms: 0.218277866021
total_bytes_read: 0
total_bytes_written: 5
*************************** 6. row ***************************
EVENT_NAME: wait/io/file/mysys/charset
total_latency_ms: 0.450179565698
total_bytes_read: 18316
total_bytes_written: 0
*************************** 7. row ***************************
EVENT_NAME: wait/io/file/mysys/cnf
total_latency_ms: 0.315982563421
total_bytes_read: 56
total_bytes_written: 0
*************************** 8. row ***************************
EVENT_NAME: wait/io/file/myisam/dfile
total_latency_ms: 0.885083482601
total_bytes_read: 2322
total_bytes_written: 0
*************************** 9. row ***************************
EVENT_NAME: wait/io/file/myisam/kfile
total_latency_ms: 3.881758853793
total_bytes_read: 7058
total_bytes_written: 0
*************************** 10. row ***************************
EVENT_NAME: wait/io/file/innodb/innodb_data_file
total_latency_ms: 114.101030502468
total_bytes_read: 10223616
total_bytes_written: 49152
*************************** 11. row ***************************
EVENT_NAME: wait/io/file/innodb/innodb_log_file
total_latency_ms: 2.865770795383
total_bytes_read: 69632
total_bytes_written: 3072
11 rows in set (0.01 sec)
Taking it one step further and combining with ps_helper
, I think there is a real opportunity to build this metrics collection into the test suite:
/* start by reseting all metrics */
ps_helper.truncate_all();
/* run test suite */
/* Collect test suite metrics from MySQL */
SELECT * FROM ps_helper.wait_classes_global_by_latency;
Here is an example for wait_classes_global_by_latency
from the GitHub project:
mysql> select * from wait_classes_global_by_latency;
+-------------------+--------------+---------------+-------------+-------------+-------------+
| event_class | total_events | total_latency | min_latency | avg_latency | max_latency |
+-------------------+--------------+---------------+-------------+-------------+-------------+
| wait/io/file | 550470 | 46.01 s | 19.44 ns | 83.58 µs | 4.21 s |
| wait/io/socket | 228833 | 2.71 s | 0 ps | 11.86 µs | 29.93 ms |
| wait/io/table | 64063 | 1.89 s | 99.79 ns | 29.43 µs | 68.07 ms |
| wait/lock/table | 76029 | 47.19 ms | 65.45 ns | 620.74 ns | 969.88 µs |
| wait/synch/mutex | 635925 | 34.93 ms | 19.44 ns | 54.93 ns | 107.70 µs |
| wait/synch/rwlock | 61287 | 7.62 ms | 21.38 ns | 124.37 ns | 34.65 µs |
+-------------------+--------------+---------------+-------------+-------------+-------------+
Neat, huh?