3619 Magnus Blåudd 2011-10-31
ndbcluster
- tentative patch to avoid having to new and delete Ndb objects too much by
saving them in a global unused list. Big gain when using non persistent
mysql connections.
added:
sql/ndb_unused_ndb_pool.cc
sql/ndb_unused_ndb_pool.h
modified:
mysql-test/suite/ndb/r/ndb_basic.result
sql/ha_ndbcluster.cc
sql/ndb_thd_ndb.cc
sql/ndb_thd_ndb.h
storage/ndb/CMakeLists.txt
3618 Jonas Oreland 2011-10-24
ndb - install ndb_error_reporter and ndb_size.pl too
modified:
storage/ndb/tools/CMakeLists.txt
=== modified file 'mysql-test/suite/ndb/r/ndb_basic.result'
--- a/mysql-test/suite/ndb/r/ndb_basic.result 2011-10-20 19:52:11 +0000
+++ b/mysql-test/suite/ndb/r/ndb_basic.result 2011-10-31 09:09:47 +0000
@@ -135,6 +135,7 @@ ndb_report_thresh_binlog_epoch_slip #
ndb_report_thresh_binlog_mem_usage #
ndb_table_no_logging #
ndb_table_temporary #
+ndb_unused_ndb_pool #
ndb_use_copying_alter_table #
ndb_use_exact_count #
ndb_use_transactions #
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2011-10-23 07:47:05 +0000
+++ b/sql/ha_ndbcluster.cc 2011-10-31 09:09:47 +0000
@@ -1190,7 +1190,6 @@ Thd_ndb::Thd_ndb(THD* thd) :
{
connection= ndb_get_cluster_connection();
m_connect_count= connection->get_connect_count();
- ndb= new Ndb(connection, "");
lock_count= 0;
start_stmt_count= 0;
save_point_count= 0;
@@ -1238,11 +1237,7 @@ Thd_ndb::~Thd_ndb()
}
}
}
- if (ndb)
- {
- delete ndb;
- ndb= NULL;
- }
+ release_ndb();
changed_tables.empty();
my_hash_free(&open_tables);
free_root(&m_batch_mem_root, MYF(0));
@@ -17893,6 +17888,20 @@ static MYSQL_SYSVAR_UINT(
0 /* block */
);
+uint opt_ndb_unused_ndb_pool;
+static MYSQL_SYSVAR_UINT(
+ unused_ndb_pool, /* name */
+ opt_ndb_unused_ndb_pool, /* var */
+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
+ "Max number of unused Ndb objects",
+ NULL, /* check func. */
+ NULL, /* update func. */
+ 0, /* default */
+ 0, /* min */
+ 65535, /* max */
+ 0 /* block */
+);
+
/* should be in index_stat.h */
extern int
@@ -18205,6 +18214,7 @@ static struct st_mysql_sys_var* system_v
#ifndef DBUG_OFF
MYSQL_SYSVAR(check_shares),
#endif
+ MYSQL_SYSVAR(unused_ndb_pool),
NULL
};
=== modified file 'sql/ndb_thd_ndb.cc'
--- a/sql/ndb_thd_ndb.cc 2011-10-17 18:13:57 +0000
+++ b/sql/ndb_thd_ndb.cc 2011-10-31 09:09:47 +0000
@@ -16,6 +16,9 @@
*/
#include "ndb_thd_ndb.h"
+#include "ndb_unused_ndb_pool.h"
+
+static Ndb_unused_ndb_pool unused_ndb_pool;
/*
Default value for max number of transactions createable against NDB from
@@ -25,6 +28,72 @@
static const int MAX_TRANSACTIONS= 4;
+bool
+Thd_ndb::alloc_ndb(bool use_pool)
+{
+ DBUG_ENTER("Thd_ndb::alloc_ndb");
+ DBUG_PRINT("enter", ("use_pool: %d", use_pool));
+
+ if (use_pool &&
+ unused_ndb_pool.get(&ndb))
+ {
+ if (!valid_ndb() &&
+ !recycle_ndb(m_thd))
+ {
+ // Failed to recycle the invalid Ndb object
+ assert(ndb == NULL);
+ DBUG_RETURN(false);
+ }
+ }
+ else
+ {
+ /*
+ Choose to not use pool or No Ndb object available
+ in pool -> allocate a new one
+ */
+ ndb= new Ndb(connection, "");
+ if (!ndb)
+ {
+ DBUG_PRINT("error", ("Failed to allocate Ndb object"));
+ DBUG_RETURN(false);
+ }
+
+ if (ndb->init(MAX_TRANSACTIONS) != 0)
+ {
+ DBUG_PRINT("error", ("Ndb::init failed, eror: %d message: %s",
+ ndb->getNdbError().code,
+ ndb->getNdbError().message));
+
+ delete ndb;
+ ndb= NULL;
+ DBUG_RETURN(false);
+ }
+ }
+ ndb->setCustomData64(thd_get_thread_id(m_thd));
+ DBUG_RETURN(TRUE);
+}
+
+
+void
+Thd_ndb::release_ndb(bool use_pool)
+{
+ DBUG_ENTER("Thd_ndb::release_ndb");
+ DBUG_PRINT("enter", ("use_pool: %d", use_pool));
+ if (!use_pool ||
+ !unused_ndb_pool.release(ndb))
+ {
+ // - Didn't want to use the pool(for example when returning
+ // a Ndb object which is no longer valid)
+ // - Pool didn't take the Ndb object, it's full or
+ // couldn't alloc memory to extend it's size
+ delete ndb;
+ }
+
+ ndb= NULL;
+ DBUG_VOID_RETURN;
+}
+
+
Thd_ndb*
Thd_ndb::seize(THD* thd)
{
@@ -34,19 +103,12 @@ Thd_ndb::seize(THD* thd)
if (thd_ndb == NULL)
return NULL;
- if (thd_ndb->ndb->init(MAX_TRANSACTIONS) != 0)
+ if (!thd_ndb->alloc_ndb())
{
- DBUG_PRINT("error", ("Ndb::init failed, eror: %d message: %s",
- thd_ndb->ndb->getNdbError().code,
- thd_ndb->ndb->getNdbError().message));
-
delete thd_ndb;
- thd_ndb= NULL;
- }
- else
- {
- thd_ndb->ndb->setCustomData64(thd_get_thread_id(thd));
+ return NULL;
}
+
DBUG_RETURN(thd_ndb);
}
@@ -69,26 +131,15 @@ Thd_ndb::recycle_ndb(THD* thd)
DBUG_ASSERT(global_schema_lock_trans == NULL);
DBUG_ASSERT(trans == NULL);
- delete ndb;
- if ((ndb= new Ndb(connection, "")) == NULL)
- {
- DBUG_PRINT("error",("failed to allocate Ndb object"));
- DBUG_RETURN(false);
- }
+ // Dont use the Ndb object pool when recycling
+ const bool use_pool = false;
+ release_ndb(use_pool);
- if (ndb->init(MAX_TRANSACTIONS) != 0)
- {
- delete ndb;
- ndb= NULL;
- DBUG_PRINT("error", ("Ndb::init failed, %d message: %s",
- ndb->getNdbError().code,
- ndb->getNdbError().message));
+ if (!alloc_ndb(use_pool))
DBUG_RETURN(false);
- }
- else
- {
- ndb->setCustomData64(thd_get_thread_id(thd));
- }
+
+ ndb->setCustomData64(thd_get_thread_id(m_thd));
+
DBUG_RETURN(true);
}
=== modified file 'sql/ndb_thd_ndb.h'
--- a/sql/ndb_thd_ndb.h 2011-06-23 06:59:40 +0000
+++ b/sql/ndb_thd_ndb.h 2011-10-31 09:09:47 +0000
@@ -58,8 +58,12 @@ enum THD_NDB_TRANS_OPTIONS
class Thd_ndb
{
THD* m_thd;
+ unsigned m_connect_count;
Thd_ndb(THD*);
+ Thd_ndb(const Thd_ndb&); // Not implemented
+ Thd_ndb(); // Not impelemented
+
~Thd_ndb();
public:
static Thd_ndb* seize(THD*);
@@ -134,9 +138,11 @@ public:
uint schema_locks_count; // Number of global schema locks taken by thread
bool has_required_global_schema_lock(const char* func);
- unsigned m_connect_count;
bool valid_ndb(void);
bool recycle_ndb(THD* thd);
+private:
+ void release_ndb(bool use_pool = true);
+ bool alloc_ndb(bool use_pool = true);
};
#endif
=== added file 'sql/ndb_unused_ndb_pool.cc'
--- a/sql/ndb_unused_ndb_pool.cc 1970-01-01 00:00:00 +0000
+++ b/sql/ndb_unused_ndb_pool.cc 2011-10-31 09:09:47 +0000
@@ -0,0 +1,78 @@
+/*
+ Copyright (c) 2011, Oracle and/or its affiliates. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "ndb_unused_ndb_pool.h"
+
+#include <ndbapi/Ndb.hpp>
+
+// Configuration parameter used to control the max size of the pool
+extern uint opt_ndb_unused_ndb_pool;
+
+
+void Ndb_unused_ndb_pool::free_unused()
+{
+ // NOTE! Should be called with m_mutex locked or when no one
+ // else is accessing the pool
+ Ndb* ndb;
+ List_iterator_fast<Ndb> it(m_list);
+ while ((ndb= it++))
+ delete ndb;
+ m_list.empty();
+}
+
+
+Ndb_unused_ndb_pool::Ndb_unused_ndb_pool()
+{
+ pthread_mutex_init(&m_mutex, MY_MUTEX_INIT_SLOW);
+ init_alloc_root(&m_memroot, 1024, 0);
+}
+
+
+Ndb_unused_ndb_pool::~Ndb_unused_ndb_pool()
+{
+ // Free any remaining unused Ndb objects
+ pthread_mutex_lock(&m_mutex);
+ free_unused();
+ pthread_mutex_unlock(&m_mutex);
+
+ pthread_mutex_destroy(&m_mutex);
+ free_root(&m_memroot, MYF(0));
+}
+
+
+bool
+Ndb_unused_ndb_pool::get(Ndb** ndb)
+{
+ pthread_mutex_lock(&m_mutex);
+ *ndb = m_list.pop();
+ pthread_mutex_unlock(&m_mutex);
+ return (*ndb != NULL);
+}
+
+
+bool
+Ndb_unused_ndb_pool::release(Ndb* ndb)
+{
+ pthread_mutex_lock(&m_mutex);
+ bool released = false;
+ if (m_list.elements < opt_ndb_unused_ndb_pool)
+ {
+ released = !m_list.push_back(ndb, &m_memroot);
+ }
+ pthread_mutex_unlock(&m_mutex);
+ return released;
+}
=== added file 'sql/ndb_unused_ndb_pool.h'
--- a/sql/ndb_unused_ndb_pool.h 1970-01-01 00:00:00 +0000
+++ b/sql/ndb_unused_ndb_pool.h 2011-10-31 09:09:47 +0000
@@ -0,0 +1,63 @@
+/*
+ Copyright (c) 2011, Oracle and/or its affiliates. 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef NDB_UNUSED_NDB_POOL_H
+#define NDB_UNUSED_NDB_POOL_H
+
+#include <sql_list.h>
+
+class Ndb_unused_ndb_pool
+{
+ // Simple list to hold currently unused Ndb objects
+ List<class Ndb> m_list;
+
+ // Pointers to object in list will be allocated
+ // from this memroot
+ MEM_ROOT m_memroot;
+
+ // Protect the m_list member from concurrent access
+ pthread_mutex_t m_mutex;
+
+ void free_unused();
+public:
+ Ndb_unused_ndb_pool();
+ Ndb_unused_ndb_pool(const Ndb_unused_ndb_pool&); // Not implemented
+ ~Ndb_unused_ndb_pool();
+
+ /**
+ Get a unused Ndb object from the pool, the Ndb object
+ returned is now owned by the caller.
+
+ @param Ndb** output parameter which will be set to
+ found Ndb object if function returns true.
+ */
+ bool get(class Ndb** ndb);
+
+ /**
+ Release a Ndb object and insert it into the pool if there
+ is room.
+
+ @param Ndb* The Ndb object which should be returned to the pool.
+ @return true means the pool has taken over the ndb object, false indicates
+ that the pool was full or could not allocate more memory
+ and the caller still owns the Ndb object
+ */
+ bool release(class Ndb* ndb);
+
+};
+
+#endif
=== modified file 'storage/ndb/CMakeLists.txt'
--- a/storage/ndb/CMakeLists.txt 2011-10-24 12:45:30 +0000
+++ b/storage/ndb/CMakeLists.txt 2011-10-31 09:09:47 +0000
@@ -80,6 +80,7 @@ SET(NDBCLUSTER_SOURCES
../../sql/ndb_global_schema_lock.cc
../../sql/ndb_mi.cc
../../sql/ndb_conflict_trans.cc
+ ../../sql/ndb_unused_ndb_pool.cc
)
# Include directories used when building ha_ndbcluster
No bundle (reason: useless for push emails).| Thread |
|---|
| • bzr push into mysql-5.5-cluster branch (magnus.blaudd:3618 to 3619) | Magnus Blåudd | 1 Nov |