[anjuta] symbol-db: first test on sym_type with table memory mapped on hashtable.
- From: Massimo Cora' <mcora src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [anjuta] symbol-db: first test on sym_type with table memory mapped on hashtable.
- Date: Wed, 2 Jun 2010 23:02:54 +0000 (UTC)
commit 8a2430c8382038efdb3393df855d063b2fb86b2a
Author: Massimo Corà <mcora src gnome org>
Date: Mon May 31 22:03:45 2010 +0200
symbol-db: first test on sym_type with table memory mapped on hashtable.
Population drops from 0.0023 sec/sym to 0.0017 sec/sym on average. Final transaction
flush on db takes about 3 seconds.
plugins/symbol-db/symbol-db-engine-core.c | 213 ++++++++++++++++++++++++++++-
plugins/symbol-db/symbol-db-engine-priv.h | 4 +
2 files changed, 213 insertions(+), 4 deletions(-)
---
diff --git a/plugins/symbol-db/symbol-db-engine-core.c b/plugins/symbol-db/symbol-db-engine-core.c
index a007b74..67bc8d9 100644
--- a/plugins/symbol-db/symbol-db-engine-core.c
+++ b/plugins/symbol-db/symbol-db-engine-core.c
@@ -138,6 +138,14 @@ select symbol_id_base, symbol.name from heritage
}
*/
+#define DEBUG_WRITE_SQL_LOG(format) { \
+ FILE *file; \
+ file = fopen("/tmp/debug_sql.log", "a"); \
+ g_fprintf (file, format); \
+ fclose (file); \
+}
+
+
typedef struct _TableMapTmpHeritage {
gint symbol_referer_id;
gchar *field_inherits;
@@ -236,6 +244,9 @@ static GObjectClass *parent_class = NULL;
static void
sdb_engine_second_pass_do (SymbolDBEngine * dbe);
+static void
+sdb_engine_sym_type_tablemap_db_flush (SymbolDBEngine * dbe);
+
void
sdb_engine_dyn_child_query_node_destroy (gpointer data);
@@ -344,8 +355,18 @@ static void
sdb_engine_init_table_maps (SymbolDBEngine *dbe)
{
SymbolDBEnginePriv *priv = dbe->priv;
-
+
+ /* tmp_heritage_tablemap */
priv->tmp_heritage_tablemap = g_queue_new ();
+
+ /* sym_type_tablemap */
+ priv->sym_type_tablemap_hash = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
+ priv->sym_type_tablemap_queue = g_queue_new ();
+ priv->sym_type_tablemap_id = 1;
+
}
static void
@@ -1757,6 +1778,16 @@ sdb_engine_timeout_trigger_signals (gpointer user_data)
case SCAN_END:
{
+ /* perform flush on db of the tablemaps, if this is the 1st scan */
+ if (priv->is_first_population == TRUE)
+ {
+ sdb_engine_sym_type_tablemap_db_flush (dbe);
+
+
+ /* ok, set the flag to false. We're done with it */
+ priv->is_first_population = FALSE;
+ }
+
/* get the process id from the queue */
gint int_tmp = GPOINTER_TO_INT(g_async_queue_pop (priv->scan_process_id_queue));
g_signal_emit (dbe, signals[SCAN_END], 0, int_tmp);
@@ -2200,6 +2231,7 @@ sdb_engine_init (SymbolDBEngine * object)
sdbe->priv->ctags_launcher = NULL;
sdbe->priv->removed_launchers = NULL;
sdbe->priv->shutting_down = FALSE;
+ sdbe->priv->is_first_population = FALSE;
/* set the ctags executable path to NULL */
sdbe->priv->ctags_path = NULL;
@@ -3016,7 +3048,7 @@ sdb_engine_connect_to_db (SymbolDBEngine * dbe, const gchar *cnc_string)
*/
priv->db_connection
= gda_connection_open_from_string ("SQLite", cnc_string, NULL,
- GDA_CONNECTION_OPTIONS_THREAD_SAFE, NULL);
+ /* FIXME */ GDA_CONNECTION_OPTIONS_THREAD_SAFE, NULL);
if (!GDA_IS_CONNECTION (priv->db_connection))
{
@@ -3052,6 +3084,7 @@ symbol_db_engine_is_connected (SymbolDBEngine * dbe)
/**
* Creates required tables for the database to work.
+ * Sets is_first_population flag to TRUE.
* @param tables_sql_file File containing sql code.
*/
static gboolean
@@ -3085,6 +3118,8 @@ sdb_engine_create_db_tables (SymbolDBEngine * dbe, const gchar * tables_sql_file
*/
query = "INSERT INTO version VALUES ("SYMBOL_DB_VERSION")";
sdb_engine_execute_non_select_sql (dbe, query);
+
+ priv->is_first_population = TRUE;
/* no need to free query of course */
@@ -4070,6 +4105,166 @@ sdb_engine_extract_type_qualifier (const gchar *string, const gchar *expr)
return res;
}
+static void
+sdb_engine_sym_type_tablemap_db_flush (SymbolDBEngine * dbe)
+{
+ GString *transaction_str;
+ SymbolDBEnginePriv *priv;
+ gint i;
+ gint queue_length;
+
+ priv = dbe->priv;
+ DEBUG_PRINT ("Preparing SYM_TYPE flush on db");
+
+ GTimer *sym_timer_DEBUG = g_timer_new ();
+
+ transaction_str = g_string_new ("BEGIN TRANSACTION;");
+
+ queue_length = g_queue_get_length (priv->sym_type_tablemap_queue);
+#if 0
+ for (i = 0; i < queue_length; i++)
+ {
+ gchar * value = g_queue_pop_head (priv->sym_type_tablemap_queue);
+ gchar **tokens = g_strsplit (value, "|", 2);
+
+ g_string_append_printf (transaction_str,
+ "INSERT INTO sym_type (type_type, type_name) VALUES ('%s', '%s');",
+ tokens[0], tokens[1]);
+
+ g_strfreev(tokens);
+ /* no need to free value, it'll be freed when associated value
+ * on hashtable'll be freed
+ */
+ }
+#endif
+
+ const GdaSet *plist;
+ const GdaStatement *stmt;
+ GdaHolder *param;
+ GdaSet *last_inserted;
+ GValue *ret_value;
+ gboolean ret_bool;
+
+ gda_connection_begin_transaction (priv->db_connection, "symtype",
+ GDA_TRANSACTION_ISOLATION_SERIALIZABLE, NULL);
+
+
+ for (i = 0; i < queue_length; i++)
+ {
+ gchar * value = g_queue_pop_head (priv->sym_type_tablemap_queue);
+ gchar **tokens = g_strsplit (value, "|", 2);
+
+ if ((stmt = sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_SYM_TYPE_NEW))
+ == NULL)
+ {
+ g_warning ("query is null");
+ return -1;
+ }
+
+ plist = sdb_engine_get_query_parameters_list (dbe, PREP_QUERY_SYM_TYPE_NEW);
+
+ /* type parameter */
+ if ((param = gda_set_get_holder ((GdaSet*)plist, "type")) == NULL)
+ {
+ g_warning ("param type is NULL from pquery!");
+ return -1;
+ }
+
+ MP_SET_HOLDER_BATCH_STR(priv, param, tokens[0], ret_bool, ret_value);
+
+ /* type_name parameter */
+ if ((param = gda_set_get_holder ((GdaSet*)plist, "typename")) == NULL)
+ {
+ g_warning ("param typename is NULL from pquery!");
+ return -1;
+ }
+
+ MP_SET_HOLDER_BATCH_STR(priv, param, tokens[1], ret_bool, ret_value);
+
+ /* execute the query with parametes just set */
+ gda_connection_statement_execute_non_select (priv->db_connection,
+ (GdaStatement*)stmt,
+ (GdaSet*)plist, NULL,
+ NULL);
+
+ g_strfreev(tokens);
+ /* no need to free value, it'll be freed when associated value
+ * on hashtable'll be freed
+ */
+
+ }
+
+ gda_connection_commit_transaction (priv->db_connection, "symtype", NULL);
+
+ gdouble elapsed_DEBUG = g_timer_elapsed (sym_timer_DEBUG, NULL);
+ DEBUG_PRINT ("===== elapsed using GDA TRANSACTION: %f", elapsed_DEBUG);
+
+
+#if 0
+ transaction_str = g_string_append (transaction_str, "COMMIT;");
+
+ gdouble elapsed_DEBUG = g_timer_elapsed (sym_timer_DEBUG, NULL);
+ DEBUG_PRINT ("elapsed string building: %f", elapsed_DEBUG);
+ g_timer_reset (sym_timer_DEBUG);
+
+
+ DEBUG_WRITE_SQL_LOG (transaction_str->str);
+
+ /* we're ready to execute the transaction */
+ sdb_engine_execute_non_select_sql (dbe, transaction_str->str);
+
+ elapsed_DEBUG = g_timer_elapsed (sym_timer_DEBUG, NULL);
+ DEBUG_PRINT ("elapsed sql executing: %f", elapsed_DEBUG);
+ g_timer_destroy (sym_timer_DEBUG);
+
+ g_string_free (transaction_str, TRUE);
+ DEBUG_PRINT ("DONE");
+#endif
+}
+
+/* ### Thread note: this function inherits the mutex lock ### */
+static GNUC_INLINE gint
+sdb_engine_add_new_sym_type_1st (SymbolDBEngine * dbe, const tagEntry * tag_entry,
+ const gchar* type, const gchar* type_name)
+{
+ SymbolDBEnginePriv *priv;
+ gchar *key_to_find;
+ gpointer *value;
+ gint table_id;
+
+ priv = dbe->priv;
+ key_to_find = g_strconcat (type, "|", type_name, NULL);
+
+ /* use a check-first, insert later pattern. Have a look at the hashtable if
+ * we find the correct key
+ */
+ value = g_hash_table_lookup (priv->sym_type_tablemap_hash, key_to_find);
+
+ if (value == NULL)
+ {
+ gint new_id = priv->sym_type_tablemap_id++;
+
+ /* no value has been found, proceed with insertion */
+ g_hash_table_insert (priv->sym_type_tablemap_hash, key_to_find,
+ GINT_TO_POINTER (new_id));
+
+ /* insert the key_to_find also in the queue.
+ * we won't dup the gchar, so that it'll be freed once the hash table'll be
+ * destroyed
+ */
+ g_queue_push_tail (priv->sym_type_tablemap_queue, key_to_find);
+
+ table_id = new_id;
+ }
+ else
+ {
+ /* fine, return the id found */
+ table_id = GPOINTER_TO_INT (value);
+ }
+
+ return table_id;
+}
+
/* ### Thread note: this function inherits the mutex lock ### */
static GNUC_INLINE gint
sdb_engine_add_new_sym_type (SymbolDBEngine * dbe, const tagEntry * tag_entry)
@@ -4091,12 +4286,13 @@ sdb_engine_add_new_sym_type (SymbolDBEngine * dbe, const tagEntry * tag_entry)
SymbolDBEnginePriv *priv;
GValue *ret_value;
gboolean ret_bool;
- gchar *type_regex = NULL;
+ gchar *type_regex;;
priv = dbe->priv;
/* we assume that tag_entry is != NULL */
type = tag_entry->kind;
+ type_regex = NULL;
if (g_strcmp0 (type, "member") == 0 ||
g_strcmp0 (type, "variable") == 0 ||
@@ -4116,6 +4312,15 @@ sdb_engine_add_new_sym_type (SymbolDBEngine * dbe, const tagEntry * tag_entry)
{
type_name = tag_entry->name;
}
+
+ /* is this the first population? if yes skip to the proper function */
+ if (priv->is_first_population == TRUE)
+ {
+ table_id = sdb_engine_add_new_sym_type_1st (dbe, tag_entry, type, type_name);
+ g_free (type_regex);
+ return table_id;
+ }
+
/* it does not exist. Create a new tuple. */
if ((stmt = sdb_engine_get_statement_by_query_id (dbe, PREP_QUERY_SYM_TYPE_NEW))
@@ -4680,7 +4885,7 @@ sdb_engine_add_new_tmp_heritage_scope (SymbolDBEngine * dbe,
node = g_slice_new0 (TableMapTmpHeritage);
node->symbol_referer_id = symbol_referer_id;
-
+
if ((field_inherits = tagsField (tag_entry, "inherits")) != NULL)
{
node->field_inherits = g_strdup (field_inherits);
diff --git a/plugins/symbol-db/symbol-db-engine-priv.h b/plugins/symbol-db/symbol-db-engine-priv.h
index 1b52cb6..c136c3c 100644
--- a/plugins/symbol-db/symbol-db-engine-priv.h
+++ b/plugins/symbol-db/symbol-db-engine-priv.h
@@ -292,6 +292,7 @@ struct _SymbolDBEnginePriv
AnjutaLauncher *ctags_launcher;
GList *removed_launchers;
gboolean shutting_down;
+ gboolean is_first_population;
GMutex* mutex;
GAsyncQueue* signals_queue;
@@ -313,6 +314,9 @@ struct _SymbolDBEnginePriv
/* Table maps */
GQueue *tmp_heritage_tablemap;
+ GHashTable *sym_type_tablemap_hash;
+ GQueue *sym_type_tablemap_queue;
+ guint sym_type_tablemap_id;
GTree *file_symbols_cache;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]