Skip to content

Commit 4c9d1c7

Browse files
AliSQLAliSQL
authored andcommitted
[Perf] Issue#23 MERGE INNODB AIO REQUEST
Description: ------------ The InnoDB engine support native AIO and simulated AIO on linux platform. Native AIO use io_submit that glibc supplied to request IO. But InnoDB engine requested AIO one by one through io_submit when trigger read-ahead, so it is a little inefficiency. Solution: --------- We buffered the AIO requests, then io_submit all. For example: when linear-ahead. we buffered next 64 pages io requests, at last, io_submit all io requests.
1 parent 70bb617 commit 4c9d1c7

11 files changed

Lines changed: 253 additions & 34 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
DROP TABLE if exists t1;
2+
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256)) ENGINE=INNODB;
3+
INSERT INTO t1 VALUES (0, REPEAT('a',256));
4+
INSERT INTO t1 SELECT 0, b FROM t1;
5+
INSERT INTO t1 SELECT 0, b FROM t1;
6+
INSERT INTO t1 SELECT 0, b FROM t1;
7+
INSERT INTO t1 SELECT 0, b FROM t1;
8+
INSERT INTO t1 SELECT 0, b FROM t1;
9+
INSERT INTO t1 SELECT 0, b FROM t1;
10+
INSERT INTO t1 SELECT 0, b FROM t1;
11+
INSERT INTO t1 SELECT 0, b FROM t1;
12+
INSERT INTO t1 SELECT 0, b FROM t1;
13+
INSERT INTO t1 SELECT 0, b FROM t1;
14+
INSERT INTO t1 SELECT 0, b FROM t1;
15+
INSERT INTO t1 SELECT 0, b FROM t1;
16+
INSERT INTO t1 SELECT 0, b FROM t1;
17+
INSERT INTO t1 SELECT 0, b FROM t1;
18+
INSERT INTO t1 SELECT 0, b FROM t1;
19+
INSERT INTO t1 SELECT 0, b FROM t1;
20+
show global status like "innodb_buffered_aio_submitted";
21+
Variable_name Value
22+
Innodb_buffered_aio_submitted 0
23+
select * from t1;
24+
select count(*) from t1;
25+
count(*)
26+
65536
27+
show global status like "innodb_buffered_aio_submitted";
28+
Variable_name Value
29+
Innodb_buffered_aio_submitted #
30+
DROP TABLE t1;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--source include/have_innodb.inc
2+
3+
--disable_warnings
4+
DROP TABLE if exists t1;
5+
--enable_warnings
6+
7+
# Create table.
8+
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256)) ENGINE=INNODB;
9+
10+
# Populate table.
11+
INSERT INTO t1 VALUES (0, REPEAT('a',256));
12+
INSERT INTO t1 SELECT 0, b FROM t1;
13+
INSERT INTO t1 SELECT 0, b FROM t1;
14+
INSERT INTO t1 SELECT 0, b FROM t1;
15+
INSERT INTO t1 SELECT 0, b FROM t1;
16+
INSERT INTO t1 SELECT 0, b FROM t1;
17+
INSERT INTO t1 SELECT 0, b FROM t1;
18+
INSERT INTO t1 SELECT 0, b FROM t1;
19+
INSERT INTO t1 SELECT 0, b FROM t1;
20+
INSERT INTO t1 SELECT 0, b FROM t1;
21+
INSERT INTO t1 SELECT 0, b FROM t1;
22+
INSERT INTO t1 SELECT 0, b FROM t1;
23+
INSERT INTO t1 SELECT 0, b FROM t1;
24+
INSERT INTO t1 SELECT 0, b FROM t1;
25+
INSERT INTO t1 SELECT 0, b FROM t1;
26+
INSERT INTO t1 SELECT 0, b FROM t1;
27+
INSERT INTO t1 SELECT 0, b FROM t1;
28+
29+
--source include/restart_mysqld.inc
30+
31+
show global status like "innodb_buffered_aio_submitted";
32+
33+
--disable_result_log
34+
select * from t1;
35+
--enable_result_log
36+
37+
select count(*) from t1;
38+
39+
--replace_column 2 #
40+
show global status like "innodb_buffered_aio_submitted";
41+
42+
DROP TABLE t1;

storage/innobase/buf/buf0rea.cc

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,12 @@ buf_read_page_low(
119119
treat the tablespace as dropped; this is a timestamp we
120120
use to stop dangling page reads from a tablespace
121121
which we have DISCARDed + IMPORTed back */
122-
ulint offset) /*!< in: page number */
122+
ulint offset, /*!< in: page number */
123+
ibool should_buffer) /*!< in: whether to buffer an aio request.
124+
AIO read-ahead uses this. if you plan to use this parameter,
125+
make sure you remember to call os_aio_linux_dispatch_read_array_submit
126+
when you are ready to commit all you requests. */
127+
123128
{
124129
buf_page_t* bpage;
125130
ulint wake_later;
@@ -181,17 +186,17 @@ buf_read_page_low(
181186
}
182187

183188
if (zip_size) {
184-
*err = fil_io(OS_FILE_READ | wake_later
189+
*err = _fil_io(OS_FILE_READ | wake_later
185190
| ignore_nonexistent_pages,
186191
sync, space, zip_size, offset, 0, zip_size,
187-
bpage->zip.data, bpage);
192+
bpage->zip.data, bpage, should_buffer);
188193
} else {
189194
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
190195

191-
*err = fil_io(OS_FILE_READ | wake_later
196+
*err = _fil_io(OS_FILE_READ | wake_later
192197
| ignore_nonexistent_pages,
193198
sync, space, 0, offset, 0, UNIV_PAGE_SIZE,
194-
((buf_block_t*) bpage)->frame, bpage);
199+
((buf_block_t*) bpage)->frame, bpage, should_buffer);
195200
}
196201

197202
if (sync) {
@@ -345,7 +350,7 @@ buf_read_ahead_random(
345350
&err, false,
346351
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
347352
space, zip_size, FALSE,
348-
tablespace_version, i);
353+
tablespace_version, i, false);
349354
if (err == DB_TABLESPACE_DELETED) {
350355
ut_print_timestamp(stderr);
351356
fprintf(stderr,
@@ -408,7 +413,7 @@ buf_read_page(
408413

409414
count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space,
410415
zip_size, FALSE,
411-
tablespace_version, offset);
416+
tablespace_version, offset, false);
412417
srv_stats.buf_pool_reads.add(count);
413418
if (err == DB_TABLESPACE_DELETED) {
414419
ut_print_timestamp(stderr);
@@ -456,7 +461,7 @@ buf_read_page_async(
456461
| OS_AIO_SIMULATED_WAKE_LATER
457462
| BUF_READ_IGNORE_NONEXISTENT_PAGES,
458463
space, zip_size, FALSE,
459-
tablespace_version, offset);
464+
tablespace_version, offset, false);
460465
srv_stats.buf_pool_reads.add(count);
461466

462467
/* We do not increment number of I/O operations used for LRU policy
@@ -715,7 +720,7 @@ buf_read_ahead_linear(
715720
count += buf_read_page_low(
716721
&err, false,
717722
ibuf_mode,
718-
space, zip_size, FALSE, tablespace_version, i);
723+
space, zip_size, FALSE, tablespace_version, i, true);
719724
if (err == DB_TABLESPACE_DELETED) {
720725
ut_print_timestamp(stderr);
721726
fprintf(stderr,
@@ -728,6 +733,9 @@ buf_read_ahead_linear(
728733
}
729734
}
730735
}
736+
#if defined(LINUX_NATIVE_AIO)
737+
os_aio_linux_dispatch_read_array_submit();
738+
#endif
731739

732740
/* In simulated aio we wake the aio handler threads only after
733741
queuing all aio requests, in native aio the following call does
@@ -805,7 +813,7 @@ buf_read_ibuf_merge_pages(
805813
buf_read_page_low(&err, sync && (i + 1 == n_stored),
806814
BUF_READ_ANY_PAGE, space_ids[i],
807815
zip_size, TRUE, space_versions[i],
808-
page_nos[i]);
816+
page_nos[i], false);
809817

810818
if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) {
811819
tablespace_deleted:
@@ -900,12 +908,12 @@ buf_read_recv_pages(
900908
if ((i + 1 == n_stored) && sync) {
901909
buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space,
902910
zip_size, TRUE, tablespace_version,
903-
page_nos[i]);
911+
page_nos[i], false);
904912
} else {
905913
buf_read_page_low(&err, false, BUF_READ_ANY_PAGE
906914
| OS_AIO_SIMULATED_WAKE_LATER,
907915
space, zip_size, TRUE,
908-
tablespace_version, page_nos[i]);
916+
tablespace_version, page_nos[i], false);
909917
}
910918
}
911919

storage/innobase/fil/fil0fil.cc

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5186,7 +5186,7 @@ fil_extend_space_to_desired_size(
51865186
success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC,
51875187
node->name, node->handle, buf,
51885188
offset, page_size * n_pages,
5189-
NULL, NULL);
5189+
NULL, NULL, false);
51905190
#endif /* UNIV_HOTBACKUP */
51915191
if (success) {
51925192
os_has_said_disk_full = FALSE;
@@ -5532,8 +5532,8 @@ Reads or writes data. This operation is asynchronous (aio).
55325532
i/o on a tablespace which does not exist */
55335533
UNIV_INTERN
55345534
dberr_t
5535-
fil_io(
5536-
/*===*/
5535+
_fil_io(
5536+
/*====*/
55375537
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE,
55385538
ORed to OS_FILE_LOG, if a log i/o
55395539
and ORed to OS_AIO_SIMULATED_WAKE_LATER
@@ -5557,8 +5557,13 @@ fil_io(
55575557
void* buf, /*!< in/out: buffer where to store read data
55585558
or from where to write; in aio this must be
55595559
appropriately aligned */
5560-
void* message) /*!< in: message for aio handler if non-sync
5560+
void* message, /*!< in: message for aio handler if non-sync
55615561
aio used, else ignored */
5562+
ibool should_buffer) /*!< in: whether to buffer an aio request.
5563+
AIO read ahead uses this. If you plan to
5564+
use this parameter, make sure you remember
5565+
to call os_aio_linux_dispatch_read_array_submit
5566+
when you are ready to commit all your requests.*/
55625567
{
55635568
ulint mode;
55645569
fil_space_t* space;
@@ -5759,7 +5764,7 @@ fil_io(
57595764
#else
57605765
/* Queue the aio request */
57615766
ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
5762-
offset, len, node, message);
5767+
offset, len, node, message, should_buffer);
57635768
#endif /* UNIV_HOTBACKUP */
57645769
ut_a(ret);
57655770

storage/innobase/handler/ha_innodb.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,8 @@ static SHOW_VAR innodb_status_variables[]= {
758758
(char*) &export_vars.innodb_truncated_status_writes, SHOW_LONG},
759759
{"available_undo_logs",
760760
(char*) &export_vars.innodb_available_undo_logs, SHOW_LONG},
761+
{"buffered_aio_submitted",
762+
(char*) &export_vars.innodb_buffered_aio_submitted, SHOW_LONG},
761763
#ifdef UNIV_DEBUG
762764
{"purge_trx_id_age",
763765
(char*) &export_vars.innodb_purge_trx_id_age, SHOW_LONG},

storage/innobase/include/fil0fil.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,13 +747,18 @@ ulint
747747
fil_space_get_n_reserved_extents(
748748
/*=============================*/
749749
ulint id); /*!< in: space id */
750+
751+
#define fil_io(type, sync, space_id, zip_size, block_offset, \
752+
byte_offset, len, buf, message) \
753+
_fil_io(type, sync, space_id, zip_size, block_offset, \
754+
byte_offset, len, buf, message, false)
750755
/********************************************************************//**
751756
Reads or writes data. This operation is asynchronous (aio).
752757
@return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do
753758
i/o on a tablespace which does not exist */
754759
UNIV_INTERN
755760
dberr_t
756-
fil_io(
761+
_fil_io(
757762
/*===*/
758763
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE,
759764
ORed to OS_FILE_LOG, if a log i/o
@@ -778,8 +783,14 @@ fil_io(
778783
void* buf, /*!< in/out: buffer where to store read data
779784
or from where to write; in aio this must be
780785
appropriately aligned */
781-
void* message) /*!< in: message for aio handler if non-sync
786+
void* message, /*!< in: message for aio handler if non-sync
782787
aio used, else ignored */
788+
ibool should_buffer)
789+
/*!< in: Whether to buffer an aio request.
790+
AIO read ahead uses this. If you plan to
791+
use this parameter, make sure you remember
792+
to call os_aio_linux_dispatch_read_array_submit
793+
when you are ready to commit all your requests.*/
783794
MY_ATTRIBUTE((nonnull(8)));
784795
/**********************************************************************//**
785796
Waits for an aio operation to complete. This function is used to write the

storage/innobase/include/os0file.h

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,9 @@ The wrapper functions have the prefix of "innodb_". */
311311
pfs_os_file_close_func(file, __FILE__, __LINE__)
312312

313313
# define os_aio(type, mode, name, file, buf, offset, \
314-
n, message1, message2) \
314+
n, message1, message2, should_buffer) \
315315
pfs_os_aio_func(type, mode, name, file, buf, offset, \
316-
n, message1, message2, __FILE__, __LINE__)
316+
n, message1, message2, __FILE__, __LINE__, should_buffer)
317317

318318
# define os_file_read(file, buf, offset, n) \
319319
pfs_os_file_read_func(file, buf, offset, n, __FILE__, __LINE__)
@@ -354,9 +354,9 @@ to original un-instrumented file I/O APIs */
354354

355355
# define os_file_close(file) os_file_close_func(file)
356356

357-
# define os_aio(type, mode, name, file, buf, offset, n, message1, message2) \
357+
# define os_aio(type, mode, name, file, buf, offset, n, message1, message2, should_buffer) \
358358
os_aio_func(type, mode, name, file, buf, offset, n, \
359-
message1, message2)
359+
message1, message2, should_buffer)
360360

361361
# define os_file_read(file, buf, offset, n) \
362362
os_file_read_func(file, buf, offset, n)
@@ -759,7 +759,13 @@ pfs_os_aio_func(
759759
aio operation); ignored if mode is
760760
OS_AIO_SYNC */
761761
const char* src_file,/*!< in: file name where func invoked */
762-
ulint src_line);/*!< in: line where the func invoked */
762+
ulint src_line,/*!< in: line where the func invoked */
763+
ibool should_buffer);
764+
/*!< in: Whether to buffer an aio request.
765+
AIO read ahead uses this. If you plan to
766+
use this parameter, make sure you remember
767+
to call os_aio_linux_dispatch_read_array_submit
768+
when you are ready to commit all your requests.*/
763769
/*******************************************************************//**
764770
NOTE! Please use the corresponding macro os_file_write(), not directly
765771
this function!
@@ -1118,10 +1124,16 @@ os_aio_func(
11181124
(can be used to identify a completed
11191125
aio operation); ignored if mode is
11201126
OS_AIO_SYNC */
1121-
void* message2);/*!< in: message for the aio handler
1127+
void* message2,/*!< in: message for the aio handler
11221128
(can be used to identify a completed
11231129
aio operation); ignored if mode is
11241130
OS_AIO_SYNC */
1131+
ibool should_buffer);
1132+
/*!< in: Whether to buffer an aio request.
1133+
AIO read ahead uses this. If you plan to
1134+
use this parameter, make sure you remember
1135+
to call os_aio_linux_dispatch_read_array_submit
1136+
when you are ready to commit all your requests.*/
11251137
/************************************************************************//**
11261138
Wakes up all async i/o threads so that they know to exit themselves in
11271139
shutdown. */
@@ -1285,6 +1297,11 @@ os_aio_linux_handle(
12851297
parameters are valid and can be used to
12861298
restart the operation. */
12871299
ulint* type); /*!< out: OS_FILE_WRITE or ..._READ */
1300+
/*******************************************************************//**
1301+
Submit buffered AIO requests on the given segment to the kernel. */
1302+
UNIV_INTERN
1303+
void
1304+
os_aio_linux_dispatch_read_array_submit();
12881305
#endif /* LINUX_NATIVE_AIO */
12891306

12901307
#ifndef UNIV_NONINL

storage/innobase/include/os0file.ic

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,10 @@ pfs_os_aio_func(
211211
aio operation); ignored if mode is
212212
OS_AIO_SYNC */
213213
const char* src_file,/*!< in: file name where func invoked */
214-
ulint src_line)/*!< in: line where the func invoked */
214+
ulint src_line,/*!< in: line where the func invoked */
215+
ibool should_buffer)
216+
/*!< in: whether to buffer an aio request.
217+
Only used by aio read ahead*/
215218
{
216219
ibool result;
217220
struct PSI_file_locker* locker = NULL;
@@ -225,7 +228,7 @@ pfs_os_aio_func(
225228
src_file, src_line);
226229

227230
result = os_aio_func(type, mode, name, file, buf, offset,
228-
n, message1, message2);
231+
n, message1, message2, should_buffer);
229232

230233
register_pfs_file_io_end(locker, n);
231234

storage/innobase/include/srv0srv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ struct srv_stats_t {
125125

126126
/** Number of rows inserted */
127127
ulint_ctr_64_t n_rows_inserted;
128+
129+
/** Number of buffered aio requests submitted */
130+
ulint_ctr_64_t n_aio_submitted;
128131
};
129132

130133
extern const char* srv_main_thread_op_info;
@@ -845,6 +848,7 @@ struct export_var_t{
845848
ulint innodb_num_open_files; /*!< fil_n_file_opened */
846849
ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */
847850
ulint innodb_available_undo_logs; /*!< srv_available_undo_logs */
851+
ulint innodb_buffered_aio_submitted;
848852
#ifdef UNIV_DEBUG
849853
ulint innodb_purge_trx_id_age; /*!< rw_max_trx_id - purged trx_id */
850854
ulint innodb_purge_view_trx_id_age; /*!< rw_max_trx_id

0 commit comments

Comments
 (0)