@@ -6925,13 +6925,7 @@ class SimulatedAIOHandler {
69256925 @param[in,out] array The AIO array
69266926 @param[in] segment Local segment in the array */
69276927 SimulatedAIOHandler (AIO *array, ulint segment)
6928- : m_oldest(),
6929- m_n_elems (),
6930- m_lowest_offset(std::numeric_limits<uint64_t >::max()),
6931- m_array(array),
6932- m_n_slots(),
6933- m_segment(segment),
6934- m_buf() {
6928+ : m_n_elems(), m_array(array), m_n_slots(), m_segment(segment), m_buf() {
69356929 ut_ad (m_segment < 100 );
69366930
69376931 m_slots.resize (OS_AIO_MERGE_N_CONSECUTIVE);
@@ -6943,10 +6937,8 @@ class SimulatedAIOHandler {
69436937 /* * Reset the state of the handler
69446938 @param[in] n_slots Number of pending AIO operations supported */
69456939 void init (ulint n_slots) {
6946- m_oldest = std::chrono::seconds::zero ();
69476940 m_n_elems = 0 ;
69486941 m_n_slots = n_slots;
6949- m_lowest_offset = std::numeric_limits<uint64_t >::max ();
69506942
69516943 ut::aligned_free (m_buf);
69526944 m_buf = nullptr ;
@@ -6984,13 +6976,13 @@ class SimulatedAIOHandler {
69846976 /* * If there are at least 2 seconds old requests, then pick the
69856977 oldest one to prevent starvation. If several requests have the
69866978 same age, then pick the one at the lowest offset.
6979+ @param[in] current_time Time of start of the slot selection.
69876980 @return true if request was selected */
6988- bool select () {
6989- if (! select_oldest ()) {
6990- return ( select_lowest_offset ()) ;
6981+ bool select (std::chrono::steady_clock::time_point current_time ) {
6982+ if (select_oldest (current_time )) {
6983+ return true ;
69916984 }
6992-
6993- return (true );
6985+ return select_lowest_offset ();
69946986 }
69956987
69966988 /* * Check if there are several consecutive blocks
@@ -7152,20 +7144,20 @@ class SimulatedAIOHandler {
71527144
71537145 ulint offset = m_segment * m_n_slots;
71547146
7155- m_lowest_offset = std::numeric_limits<uint64_t >::max ();
7147+ auto lowest_offset = std::numeric_limits<uint64_t >::max ();
71567148
71577149 for (ulint i = 0 ; i < m_n_slots; ++i) {
71587150 Slot *slot;
71597151
71607152 slot = m_array->at (i + offset);
71617153
7162- if (slot->is_reserved && slot->offset < m_lowest_offset ) {
7154+ if (slot->is_reserved && slot->offset < lowest_offset ) {
71637155 /* Found an i/o request */
71647156 m_slots[0 ] = slot;
71657157
71667158 m_n_elems = 1 ;
71677159
7168- m_lowest_offset = slot->offset ;
7160+ lowest_offset = slot->offset ;
71697161 }
71707162 }
71717163
@@ -7175,50 +7167,39 @@ class SimulatedAIOHandler {
71757167 typedef std::vector<Slot *> slots_t ;
71767168
71777169 private:
7178- /* * Select the slot if it is older than the current oldest slot.
7179- @param[in] slot The slot to check */
7180- void select_if_older (Slot *slot) {
7181- const auto time_diff =
7182- std::max (std::chrono::steady_clock::now () - slot->reservation_time ,
7183- std::chrono::steady_clock::duration{0 });
7184-
7185- if (time_diff >= std::chrono::seconds{2 }) {
7186- if ((time_diff > m_oldest) ||
7187- (time_diff == m_oldest && slot->offset < m_lowest_offset)) {
7188- /* Found an i/o request */
7189- m_slots[0 ] = slot;
7190-
7191- m_n_elems = 1 ;
7170+ /* * Select the oldest slot in the array if there are any older than 2s.
7171+ @param[in] current_time Time of start of the slot selection.
7172+ @return true if any slot older than 2s is found */
7173+ bool select_oldest (std::chrono::steady_clock::time_point current_time) {
7174+ ut_ad (m_n_elems == 0 );
71927175
7193- m_oldest = time_diff ;
7176+ ulint offset = m_n_slots * m_segment ;
71947177
7195- m_lowest_offset = slot->offset ;
7178+ auto currrent_slot = m_array->at (offset);
7179+ Slot *oldest_slot = nullptr ;
7180+ for (size_t i = 0 ; i < m_n_slots; ++i, ++currrent_slot) {
7181+ if (currrent_slot->is_reserved &&
7182+ (oldest_slot == nullptr ||
7183+ currrent_slot->reservation_time < oldest_slot->reservation_time ||
7184+ (currrent_slot->reservation_time == oldest_slot->reservation_time &&
7185+ currrent_slot->offset < oldest_slot->offset ))) {
7186+ oldest_slot = currrent_slot;
71967187 }
71977188 }
7198- }
71997189
7200- /* * Select th oldest slot in the array
7201- @return true if oldest slot found */
7202- bool select_oldest ( ) {
7203- ut_ad (m_n_elems == 0 ) ;
7190+ if (oldest_slot != nullptr &&
7191+ current_time - oldest_slot-> reservation_time >=
7192+ std::chrono::seconds{ 2 } ) {
7193+ m_slots[ 0 ] = oldest_slot ;
72047194
7205- Slot *slot;
7206- ulint offset = m_n_slots * m_segment;
7207-
7208- slot = m_array->at (offset);
7209-
7210- for (ulint i = 0 ; i < m_n_slots; ++i, ++slot) {
7211- if (slot->is_reserved ) {
7212- select_if_older (slot);
7213- }
7195+ m_n_elems = 1 ;
7196+ return true ;
72147197 }
72157198
7216- return (m_n_elems > 0 ) ;
7199+ return false ;
72177200 }
72187201
7219- std::chrono::steady_clock::duration m_oldest;
72207202 ulint m_n_elems;
7221- os_offset_t m_lowest_offset;
72227203
72237204 AIO *m_array;
72247205 ulint m_n_slots;
@@ -7294,6 +7275,11 @@ static dberr_t os_aio_simulated_handler(ulint global_segment, fil_node_t **m1,
72947275
72957276 srv_set_io_thread_op_info (global_segment, " looking for i/o requests (b)" );
72967277
7278+ /* Take the current time once as it may cause syscalls and not be too
7279+ performant, it improves throughput greatly to have this executed before
7280+ we grab the AIO mutex. */
7281+ const auto current_time = std::chrono::steady_clock::now ();
7282+
72977283 array->acquire ();
72987284
72997285 ulint n_reserved;
@@ -7317,7 +7303,7 @@ static dberr_t os_aio_simulated_handler(ulint global_segment, fil_node_t **m1,
73177303
73187304 return (DB_SUCCESS);
73197305
7320- } else if (handler.select ()) {
7306+ } else if (handler.select (current_time )) {
73217307 break ;
73227308 }
73237309
0 commit comments