List:Commits« Previous MessageNext Message »
From:Magnus Blåudd Date:October 31 2011 9:11am
Subject:bzr push into mysql-5.5-cluster branch (magnus.blaudd:3618 to 3619)
View as plain text  
 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åudd1 Nov