summaryrefslogtreecommitdiff
path: root/storage/innobase/include
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@skysql.com>2014-08-06 15:28:58 +0300
committerJan Lindström <jan.lindstrom@skysql.com>2014-08-06 15:28:58 +0300
commit6dad23f04aa5c8a022193cc74b62652a3c1e3057 (patch)
tree85141ad578749597ba997677bb56d3deddd17b4d /storage/innobase/include
parente974b564389af8251c2ba51060e6129e45431586 (diff)
downloadmariadb-git-6dad23f04aa5c8a022193cc74b62652a3c1e3057.tar.gz
MDEV-5834: Merge Kakao Defragmentation implementation to MariaDB 10.1
Merge https://github.com/kakao/mariadb-10.0 that contains Facebook's implementation for defragmentation facebook/mysql-5.6@a2d3a74 facebook/mysql-5.6@def96c8 facebook/mysql-5.6@9c67c5d facebook/mysql-5.6@921a81b facebook/mysql-5.6@aa519bd facebook/mysql-5.6@fea7d13 facebook/mysql-5.6@09b29d3 facebook/mysql-5.6@9284abb facebook/mysql-5.6@dbd623d facebook/mysql-5.6@aed55dc facebook/mysql-5.6@aad5c82 This version does not add new SQL-syntax and new handler API function. Instead optimize table is mapped to defragment table if innodb_defragment=ON, by default the feature is off. Contains changes authored by Sunguck Lee (Kakao).
Diffstat (limited to 'storage/innobase/include')
-rw-r--r--storage/innobase/include/btr0btr.h97
-rw-r--r--storage/innobase/include/btr0btr.ic3
-rw-r--r--storage/innobase/include/btr0defragment.h101
-rw-r--r--storage/innobase/include/dict0dict.h14
-rw-r--r--storage/innobase/include/dict0mem.h21
-rw-r--r--storage/innobase/include/dict0priv.h3
-rw-r--r--storage/innobase/include/dict0priv.ic5
-rw-r--r--storage/innobase/include/dict0stats.h33
-rw-r--r--storage/innobase/include/dict0stats_bg.h22
-rw-r--r--storage/innobase/include/lock0lock.h10
-rw-r--r--storage/innobase/include/srv0srv.h16
-rw-r--r--storage/innobase/include/sync0sync.h1
-rw-r--r--storage/innobase/include/ut0timer.h104
-rw-r--r--storage/innobase/include/ut0timer.ic113
14 files changed, 537 insertions, 6 deletions
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index 305acf7e322..b6f8a685ae9 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -2,6 +2,7 @@
Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
+Copyright (c) 2014, SkySQL Ab. 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
@@ -671,6 +672,21 @@ btr_get_size(
is s-latched */
__attribute__((nonnull, warn_unused_result));
/**************************************************************//**
+Gets the number of reserved and used pages in a B-tree.
+@return number of pages reserved, or ULINT_UNDEFINED if the index
+is unavailable */
+UNIV_INTERN
+ulint
+btr_get_size_and_reserved(
+/*======================*/
+ dict_index_t* index, /*!< in: index */
+ ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
+ ulint* used, /*!< out: number of pages used (<= reserved) */
+ mtr_t* mtr) /*!< in/out: mini-transaction where index
+ is s-latched */
+ __attribute__((nonnull));
+
+/**************************************************************//**
Allocates a new file page to be used in an index tree. NOTE: we assume
that the caller has made the reservation for free extents!
@retval NULL if no page could be allocated
@@ -717,6 +733,33 @@ btr_page_free_low(
ulint level, /*!< in: page level */
mtr_t* mtr) /*!< in: mtr */
__attribute__((nonnull));
+/*************************************************************//**
+Reorganizes an index page.
+
+IMPORTANT: On success, the caller will have to update IBUF_BITMAP_FREE
+if this is a compressed leaf page in a secondary index. This has to
+be done either within the same mini-transaction, or by invoking
+ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
+IBUF_BITMAP_FREE is unaffected by reorganization.
+
+@retval true if the operation was successful
+@retval false if it is a compressed page, and recompression failed */
+UNIV_INTERN
+bool
+btr_page_reorganize_block(
+/*======================*/
+ bool recovery,/*!< in: true if called in recovery:
+ locks should not be updated, i.e.,
+ there cannot exist locks on the
+ page, and a hash index should not be
+ dropped: it cannot exist */
+ ulint z_level,/*!< in: compression level to be used
+ if dealing with compressed page */
+ buf_block_t* block, /*!< in/out: B-tree page */
+ dict_index_t* index, /*!< in: the index tree of the page */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
+
#ifdef UNIV_BTR_PRINT
/*************************************************************//**
Prints size info of a B-tree. */
@@ -762,6 +805,60 @@ btr_validate_index(
const trx_t* trx) /*!< in: transaction or 0 */
__attribute__((nonnull(1), warn_unused_result));
+#ifdef UNIV_SYNC_DEBUG
+/*************************************************************//**
+Removes a page from the level list of pages.
+@param space in: space where removed
+@param zip_size in: compressed page size in bytes, or 0 for uncompressed
+@param page in/out: page to remove
+@param index in: index tree
+@param mtr in/out: mini-transaction */
+# define btr_level_list_remove(space,zip_size,page,index,mtr) \
+ btr_level_list_remove_func(space,zip_size,page,index,mtr)
+#else /* UNIV_SYNC_DEBUG */
+/*************************************************************//**
+Removes a page from the level list of pages.
+@param space in: space where removed
+@param zip_size in: compressed page size in bytes, or 0 for uncompressed
+@param page in/out: page to remove
+@param index in: index tree
+@param mtr in/out: mini-transaction */
+# define btr_level_list_remove(space,zip_size,page,index,mtr) \
+ btr_level_list_remove_func(space,zip_size,page,mtr)
+#endif /* UNIV_SYNC_DEBUG */
+
+/*************************************************************//**
+Removes a page from the level list of pages. */
+UNIV_INTERN
+void
+btr_level_list_remove_func(
+/*=======================*/
+ ulint space, /*!< in: space where removed */
+ ulint zip_size,/*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ page_t* page, /*!< in/out: page to remove */
+#ifdef UNIV_SYNC_DEBUG
+ const dict_index_t* index, /*!< in: index tree */
+#endif /* UNIV_SYNC_DEBUG */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
+
+/*************************************************************//**
+If page is the only on its level, this function moves its records to the
+father page, thus reducing the tree height.
+@return father block */
+UNIV_INTERN
+buf_block_t*
+btr_lift_page_up(
+/*=============*/
+ dict_index_t* index, /*!< in: index tree */
+ buf_block_t* block, /*!< in: page which is the only on its level;
+ must not be empty: use
+ btr_discard_only_page_on_level if the last
+ record from the page should be removed */
+ mtr_t* mtr) /*!< in: mtr */
+ __attribute__((nonnull));
+
#define BTR_N_LEAF_PAGES 1
#define BTR_TOTAL_SIZE 2
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic
index 00f50b5dcaf..40b468b200a 100644
--- a/storage/innobase/include/btr0btr.ic
+++ b/storage/innobase/include/btr0btr.ic
@@ -163,9 +163,10 @@ btr_page_get_next(
/*!< in: mini-transaction handle */
{
ut_ad(page && mtr);
+#ifndef UNIV_INNOCHECKSUM
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_S_FIX));
-
+#endif /* UNIV_INNOCHECKSUM */
return(mach_read_from_4(page + FIL_PAGE_NEXT));
}
diff --git a/storage/innobase/include/btr0defragment.h b/storage/innobase/include/btr0defragment.h
new file mode 100644
index 00000000000..8fef3c6519a
--- /dev/null
+++ b/storage/innobase/include/btr0defragment.h
@@ -0,0 +1,101 @@
+/*****************************************************************************
+
+Copyright (C) 2013, 2014 Facebook, Inc. 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.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
+
+*****************************************************************************/
+
+#ifndef btr0defragment_h
+#define btr0defragment_h
+
+#include "univ.i"
+
+#ifndef UNIV_HOTBACKUP
+
+#include "btr0pcur.h"
+
+/* Max number of pages to consider at once during defragmentation. */
+#define BTR_DEFRAGMENT_MAX_N_PAGES 32
+
+/** stats in btr_defragment */
+extern ulint btr_defragment_compression_failures;
+extern ulint btr_defragment_failures;
+extern ulint btr_defragment_count;
+
+/** Item in the work queue for btr_degrament_thread. */
+struct btr_defragment_item_t
+{
+ btr_pcur_t* pcur; /* persistent cursor where
+ btr_defragment_n_pages should start */
+ os_event_t event; /* if not null, signal after work
+ is done */
+ bool removed; /* Mark an item as removed */
+ ulonglong last_processed; /* timestamp of last time this index
+ is processed by defragment thread */
+
+ btr_defragment_item_t(btr_pcur_t* pcur, os_event_t event);
+ ~btr_defragment_item_t();
+};
+
+/******************************************************************//**
+Initialize defragmentation. */
+void
+btr_defragment_init(void);
+/******************************************************************//**
+Shutdown defragmentation. */
+void
+btr_defragment_shutdown();
+/******************************************************************//**
+Check whether the given index is in btr_defragment_wq. */
+bool
+btr_defragment_find_index(
+ dict_index_t* index); /*!< Index to find. */
+/******************************************************************//**
+Add an index to btr_defragment_wq. Return a pointer to os_event if this
+is a synchronized defragmentation. */
+os_event_t
+btr_defragment_add_index(
+ dict_index_t* index, /*!< index to be added */
+ bool async); /*!< whether this is an async defragmentation */
+/******************************************************************//**
+When table is dropped, this function is called to mark a table as removed in
+btr_efragment_wq. The difference between this function and the remove_index
+function is this will not NULL the event. */
+void
+btr_defragment_remove_table(
+ dict_table_t* table); /*!< Index to be removed. */
+/******************************************************************//**
+Mark an index as removed from btr_defragment_wq. */
+void
+btr_defragment_remove_index(
+ dict_index_t* index); /*!< Index to be removed. */
+/*********************************************************************//**
+Check whether we should save defragmentation statistics to persistent storage.*/
+UNIV_INTERN
+void
+btr_defragment_save_defrag_stats_if_needed(
+ dict_index_t* index); /*!< in: index */
+/******************************************************************//**
+Thread that merges consecutive b-tree pages into fewer pages to defragment
+the index. */
+extern "C" UNIV_INTERN
+os_thread_ret_t
+DECLARE_THREAD(btr_defragment_thread)(
+/*==========================================*/
+ void* arg); /*!< in: a dummy parameter required by
+ os_thread_create */
+
+
+#endif /* !UNIV_HOTBACKUP */
+#endif
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 2a96f5299bb..7d14df09cb2 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -120,7 +120,9 @@ enum dict_table_op_t {
DICT_TABLE_OP_DROP_ORPHAN,
/** Silently load the tablespace if it does not exist,
and do not load the definitions of incomplete indexes. */
- DICT_TABLE_OP_LOAD_TABLESPACE
+ DICT_TABLE_OP_LOAD_TABLESPACE,
+ /** Open the table only if it's in table cache. */
+ DICT_TABLE_OP_OPEN_ONLY_IF_CACHED
};
/**********************************************************************//**
@@ -1496,6 +1498,16 @@ dict_table_get_index_on_name(
const char* name) /*!< in: name of the index to find */
__attribute__((nonnull, warn_unused_result));
/**********************************************************************//**
+Looks for an index with the given id given a table instance.
+@return index or NULL */
+UNIV_INTERN
+dict_index_t*
+dict_table_find_index_on_id(
+/*========================*/
+ const dict_table_t* table, /*!< in: table instance */
+ index_id_t id) /*!< in: index id */
+ __attribute__((nonnull, warn_unused_result));
+/**********************************************************************//**
In case there is more than one index with the same name return the index
with the min(id).
@return index, NULL if does not exist */
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index b026210b214..ccca7af1c03 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -588,6 +588,10 @@ struct zip_pad_info_t {
rounds */
};
+/** Number of samples of data size kept when page compression fails for
+a certain index.*/
+#define STAT_DEFRAG_DATA_SIZE_N_SAMPLE 10
+
/** Data structure for an index. Most fields will be
initialized to 0, NULL or FALSE in dict_mem_index_create(). */
struct dict_index_t{
@@ -676,6 +680,23 @@ struct dict_index_t{
/*!< approximate number of leaf pages in the
index tree */
/* @} */
+ /** Statistics for defragmentation, these numbers are estimations and
+ could be very inaccurate at certain times, e.g. right after restart,
+ during defragmentation, etc. */
+ /* @{ */
+ ulint stat_defrag_modified_counter;
+ ulint stat_defrag_n_pages_freed;
+ /* number of pages freed by defragmentation. */
+ ulint stat_defrag_n_page_split;
+ /* number of page splits since last full index
+ defragmentation. */
+ ulint stat_defrag_data_size_sample[STAT_DEFRAG_DATA_SIZE_N_SAMPLE];
+ /* data size when compression failure happened
+ the most recent 10 times. */
+ ulint stat_defrag_sample_next_slot;
+ /* in which slot the next sample should be
+ saved. */
+ /* @} */
rw_lock_t lock; /*!< read-write lock protecting the
upper levels of the index tree */
trx_id_t trx_id; /*!< id of the transaction that created this
diff --git a/storage/innobase/include/dict0priv.h b/storage/innobase/include/dict0priv.h
index 9a3c8e22992..e034662aba0 100644
--- a/storage/innobase/include/dict0priv.h
+++ b/storage/innobase/include/dict0priv.h
@@ -53,8 +53,9 @@ dict_table_t*
dict_table_open_on_id_low(
/*=====================*/
table_id_t table_id, /*!< in: table id */
- dict_err_ignore_t ignore_err); /*!< in: errors to ignore
+ dict_err_ignore_t ignore_err, /*!< in: errors to ignore
when loading the table */
+ ibool open_only_if_in_cache);
#ifndef UNIV_NONINL
#include "dict0priv.ic"
diff --git a/storage/innobase/include/dict0priv.ic b/storage/innobase/include/dict0priv.ic
index 30ba8fb60aa..983218af78a 100644
--- a/storage/innobase/include/dict0priv.ic
+++ b/storage/innobase/include/dict0priv.ic
@@ -74,8 +74,9 @@ dict_table_t*
dict_table_open_on_id_low(
/*======================*/
table_id_t table_id, /*!< in: table id */
- dict_err_ignore_t ignore_err) /*!< in: errors to ignore
+ dict_err_ignore_t ignore_err, /*!< in: errors to ignore
when loading the table */
+ ibool open_only_if_in_cache)
{
dict_table_t* table;
ulint fold;
@@ -88,7 +89,7 @@ dict_table_open_on_id_low(
HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold,
dict_table_t*, table, ut_ad(table->cached),
table->id == table_id);
- if (table == NULL) {
+ if (table == NULL && !open_only_if_in_cache) {
table = dict_load_table_on_id(table_id, ignore_err);
}
diff --git a/storage/innobase/include/dict0stats.h b/storage/innobase/include/dict0stats.h
index 186f90e3694..abf56b2f0c7 100644
--- a/storage/innobase/include/dict0stats.h
+++ b/storage/innobase/include/dict0stats.h
@@ -195,6 +195,39 @@ dict_stats_rename_table(
is returned */
size_t errstr_sz); /*!< in: errstr size */
+/*********************************************************************//**
+Save defragmentation result.
+@return DB_SUCCESS or error code */
+UNIV_INTERN
+dberr_t
+dict_stats_save_defrag_summary(
+ dict_index_t* index); /*!< in: index */
+
+/*********************************************************************//**
+Save defragmentation stats for a given index.
+@return DB_SUCCESS or error code */
+UNIV_INTERN
+dberr_t
+dict_stats_save_defrag_stats(
+ dict_index_t* index); /*!< in: index */
+
+/**********************************************************************//**
+Clear defragmentation summary. */
+UNIV_INTERN
+void
+dict_stats_empty_defrag_summary(
+/*==================*/
+ dict_index_t* index); /*!< in: index to clear defragmentation stats */
+
+/**********************************************************************//**
+Clear defragmentation related index stats. */
+UNIV_INTERN
+void
+dict_stats_empty_defrag_stats(
+/*==================*/
+ dict_index_t* index); /*!< in: index to clear defragmentation stats */
+
+
#ifndef UNIV_NONINL
#include "dict0stats.ic"
#endif
diff --git a/storage/innobase/include/dict0stats_bg.h b/storage/innobase/include/dict0stats_bg.h
index e866ab419fe..32fac3015e8 100644
--- a/storage/innobase/include/dict0stats_bg.h
+++ b/storage/innobase/include/dict0stats_bg.h
@@ -56,6 +56,28 @@ dict_stats_recalc_pool_del(
/*=======================*/
const dict_table_t* table); /*!< in: table to remove */
+/*****************************************************************//**
+Add an index in a table to the defrag pool, which is processed by the
+background stats gathering thread. Only the table id and index id are
+added to the list, so the table can be closed after being enqueued and
+it will be opened when needed. If the table or index does not exist later
+(has been DROPped), then it will be removed from the pool and skipped. */
+UNIV_INTERN
+void
+dict_stats_defrag_pool_add(
+/*=======================*/
+ const dict_index_t* index); /*!< in: table to add */
+
+/*****************************************************************//**
+Delete a given index from the auto defrag pool. */
+UNIV_INTERN
+void
+dict_stats_defrag_pool_del(
+/*=======================*/
+ const dict_table_t* table, /*!<in: if given, remove
+ all entries for the table */
+ const dict_index_t* index); /*!< in: index to remove */
+
/** Yield the data dictionary latch when waiting
for the background thread to stop accessing a table.
@param trx transaction holding the data dictionary locks */
diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h
index 6d5ed35d5d8..3babc4d82fd 100644
--- a/storage/innobase/include/lock0lock.h
+++ b/storage/innobase/include/lock0lock.h
@@ -181,6 +181,16 @@ lock_update_merge_left(
const buf_block_t* right_block); /*!< in: merged index page
which will be discarded */
/*************************************************************//**
+Updates the lock table when a page is splited and merged to
+two pages. */
+UNIV_INTERN
+void
+lock_update_split_and_merge(
+ const buf_block_t* left_block, /*!< in: left page to which merged */
+ const rec_t* orig_pred, /*!< in: original predecessor of
+ supremum on the left page before merge*/
+ const buf_block_t* right_block);/*!< in: right page from which merged */
+/*************************************************************//**
Resets the original locks on heir and replaces them with gap type locks
inherited from rec. */
UNIV_INTERN
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 905d4a0afa7..231537b3cde 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -335,6 +335,15 @@ extern my_bool srv_random_read_ahead;
extern ulong srv_read_ahead_threshold;
extern ulint srv_n_read_io_threads;
extern ulint srv_n_write_io_threads;
+/* Defragmentation, Origianlly facebook default value is 100, but it's too high */
+#define SRV_DEFRAGMENT_FREQUENCY_DEFAULT 40
+extern my_bool srv_defragment;
+extern uint srv_defragment_n_pages;
+extern uint srv_defragment_stats_accuracy;
+extern uint srv_defragment_fill_factor_n_recs;
+extern double srv_defragment_fill_factor;
+extern uint srv_defragment_frequency;
+extern ulonglong srv_defragment_interval;
/* Number of IO operations per second the server can do */
extern ulong srv_io_capacity;
@@ -888,7 +897,12 @@ struct export_var_t{
ulint innodb_rows_deleted; /*!< srv_n_rows_deleted */
ulint innodb_num_open_files; /*!< fil_n_file_opened */
ulint innodb_truncated_status_writes; /*!< srv_truncated_status_writes */
- ulint innodb_available_undo_logs; /*!< srv_available_undo_logs */
+ ulint innodb_available_undo_logs; /*!< srv_available_undo_logs
+ */
+ ulint innodb_defragment_compression_failures;
+ ulint innodb_defragment_failures;
+ ulint innodb_defragment_count;
+
#ifdef UNIV_DEBUG
ulint innodb_purge_trx_id_age; /*!< rw_max_trx_id - purged trx_id */
ulint innodb_purge_view_trx_id_age; /*!< rw_max_trx_id
diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h
index 7b00e16476b..f26e66f1a87 100644
--- a/storage/innobase/include/sync0sync.h
+++ b/storage/innobase/include/sync0sync.h
@@ -687,6 +687,7 @@ or row lock! */
#define SYNC_EXTERN_STORAGE 500
#define SYNC_FSP 400
#define SYNC_FSP_PAGE 395
+#define SYNC_STATS_DEFRAG 390
/*------------------------------------- Change buffer headers */
#define SYNC_IBUF_MUTEX 370 /* ibuf_mutex */
/*------------------------------------- Change buffer tree */
diff --git a/storage/innobase/include/ut0timer.h b/storage/innobase/include/ut0timer.h
new file mode 100644
index 00000000000..f361ae79bf5
--- /dev/null
+++ b/storage/innobase/include/ut0timer.h
@@ -0,0 +1,104 @@
+/*****************************************************************************
+
+Copyright (c) 2013, 2014, Facebook, Inc. All Rights Reserved.
+Copyright (c) 2014, SkySQL Ab. 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.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
+
+*****************************************************************************/
+
+/********************************************************************//**
+@file include/ut0timer.h
+Timer rountines
+
+Created 30/07/2014 Jan Lindström jan.lindstrom@skysql.com
+modified from https://github.com/facebook/mysql-5.6/commit/c75a413edeb96eb99bf11d7269bdfea06f96d6b6
+*************************************************************************/
+#ifndef ut0timer_h
+#define ut0timer_h
+
+#include "univ.i"
+#include "data0type.h"
+#include <my_rdtsc.h>
+
+/* Current timer stats */
+extern struct my_timer_unit_info ut_timer;
+
+/**************************************************************//**
+Function pointer to point selected timer function.
+@return timer current value */
+extern ulonglong (*ut_timer_now)(void);
+
+/**************************************************************//**
+Sets up the data required for use of my_timer_* functions.
+Selects the best timer by high frequency, and tight resolution.
+Points my_timer_now() to the selected timer function.
+Initializes my_timer struct to contain the info for selected timer.*/
+UNIV_INTERN
+void ut_init_timer(void);
+
+/**************************************************************//**
+Return time passed since time then, automatically adjusted
+for the estimated timer overhead.
+@return time passed since "then" */
+UNIV_INLINE
+ulonglong
+ut_timer_since(
+/*===========*/
+ ulonglong then); /*!< in: time where to calculate */
+/**************************************************************//**
+Get time passed since "then", and update then to now
+@return time passed sinche "then" */
+UNIV_INLINE
+ulonglong
+ut_timer_since_and_update(
+/*======================*/
+ ulonglong *then); /*!< in: time where to calculate */
+/**************************************************************//**
+Convert native timer units in a ulonglong into seconds in a double
+@return time in a seconds */
+UNIV_INLINE
+double
+ut_timer_to_seconds(
+/*=================*/
+ ulonglong when); /*!< in: time where to calculate */
+/**************************************************************//**
+Convert native timer units in a ulonglong into milliseconds in a double
+@return time in milliseconds */
+UNIV_INLINE
+double
+ut_timer_to_milliseconds(
+/*=====================*/
+ ulonglong when); /*!< in: time where to calculate */
+/**************************************************************//**
+Convert native timer units in a ulonglong into microseconds in a double
+@return time in microseconds */
+UNIV_INLINE
+double
+ut_timer_to_microseconds(
+/*=====================*/
+ ulonglong when); /*!< in: time where to calculate */
+/**************************************************************//**
+Convert microseconds in a double to native timer units in a ulonglong
+@return time in microseconds */
+UNIV_INLINE
+ulonglong
+ut_microseconds_to_timer(
+/*=====================*/
+ ulonglong when); /*!< in: time where to calculate */
+
+#ifndef UNIV_NONINL
+#include "ut0timer.ic"
+#endif
+
+#endif
diff --git a/storage/innobase/include/ut0timer.ic b/storage/innobase/include/ut0timer.ic
new file mode 100644
index 00000000000..027e89c6279
--- /dev/null
+++ b/storage/innobase/include/ut0timer.ic
@@ -0,0 +1,113 @@
+/*****************************************************************************
+
+Copyright (c) 2013, 2014, Facebook, Inc. All Rights Reserved.
+Copyright (c) 2014, SkySQL Ab. 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.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
+
+*****************************************************************************/
+
+/********************************************************************//**
+@file include/ut0timer.ic
+Timer rountines
+
+Created 30/07/2014 Jan Lindström jan.lindstrom@skysql.com
+modified from https://github.com/facebook/mysql-5.6/commit/c75a413edeb96eb99bf11d7269bdfea06f96d6b6
+*************************************************************************/
+
+/**************************************************************//**
+Return time passed since time then, automatically adjusted
+for the estimated timer overhead.
+@return time passed since "then" */
+UNIV_INLINE
+ulonglong
+ut_timer_since(
+/*===========*/
+ ulonglong then) /*!< in: time where to calculate */
+{
+ return (ut_timer_now() - then) - ut_timer.overhead;
+}
+
+/**************************************************************//**
+Get time passed since "then", and update then to now
+@return time passed sinche "then" */
+UNIV_INLINE
+ulonglong
+ut_timer_since_and_update(
+/*======================*/
+ ulonglong *then) /*!< in: time where to calculate */
+{
+ ulonglong now = ut_timer_now();
+ ulonglong ret = (now - (*then)) - ut_timer.overhead;
+ *then = now;
+ return ret;
+}
+
+/**************************************************************//**
+Convert native timer units in a ulonglong into seconds in a double
+@return time in a seconds */
+UNIV_INLINE
+double
+ut_timer_to_seconds(
+/*=================*/
+ ulonglong when) /*!< in: time where to calculate */
+{
+ double ret = (double)(when);
+ ret /= (double)(ut_timer.frequency);
+ return ret;
+}
+
+/**************************************************************//**
+Convert native timer units in a ulonglong into milliseconds in a double
+@return time in milliseconds */
+UNIV_INLINE
+double
+ut_timer_to_milliseconds(
+/*=====================*/
+ ulonglong when) /*!< in: time where to calculate */
+{
+ double ret = (double)(when);
+ ret *= 1000.0;
+ ret /= (double)(ut_timer.frequency);
+ return ret;
+}
+
+/**************************************************************//**
+Convert native timer units in a ulonglong into microseconds in a double
+@return time in microseconds */
+UNIV_INLINE
+double
+ut_timer_to_microseconds(
+/*=====================*/
+ ulonglong when) /*!< in: time where to calculate */
+{
+ double ret = (double)(when);
+ ret *= 1000000.0;
+ ret /= (double)(ut_timer.frequency);
+ return ret;
+}
+
+/**************************************************************//**
+Convert microseconds in a double to native timer units in a ulonglong
+@return time in microseconds */
+UNIV_INLINE
+ulonglong
+ut_microseconds_to_timer(
+/*=====================*/
+ ulonglong when) /*!< in: time where to calculate */
+{
+ double ret = when;
+ ret *= (double)(ut_timer.frequency);
+ ret /= 1000000.0;
+ return (ulonglong)ret;
+}