Jelajahi Sumber

Fix term_copy, environment setup, and profiling.

Stefano Cossu 3 tahun lalu
induk
melakukan
9567f7a272
6 mengubah file dengan 120 tambahan dan 98 penghapusan
  1. 31 17
      Makefile
  2. 4 4
      profile.c
  3. 73 70
      src/environment.c
  4. 6 5
      src/term.c
  5. 5 2
      test/test_graph.c
  6. 1 0
      test/test_term.c

+ 31 - 17
Makefile

@@ -11,12 +11,13 @@ PARSER = lemon
 ## Paths.
 
 PREFIX ?= /usr/local
-bindir = $(PREFIX)/bin
-libdir = $(PREFIX)/lib
+bindir := $(PREFIX)/bin
+libdir := $(PREFIX)/lib
 includedir = $(PREFIX)/include/lsup
 MDB_DIR = ext/openldap/libraries/liblmdb
 XXHASH_DIR = ext/xxHash
-CALLGRIND_DUMP = /tmp/lsup_callgrind.%p.out
+VALGRIND_DUMP = /tmp/lsup_valgrind.log
+CALLGRIND_DUMP = /tmp/lsup_callgrind.out
 
 INCLUDE_BASE = . -Iinclude -I$(MDB_DIR) -I$(XXHASH_DIR) \
 	-Iext/tpl/src -Iext/uthash/src -Iext/log/src
@@ -46,8 +47,8 @@ LSUP_SRC = $(wildcard src/*.c)
 SRC = $(EXT_SRC) $(LSUP_SRC)
 TEST_SRC = $(wildcard test/*.c) test.c
 
-OBJ = $(LSUP_SRC:.c=.o) $(CODEC_OBJ)
 EXT_OBJ = $(EXT_SRC:.c=.o) 
+OBJ = $(EXT_OBJ) $(CODEC_OBJ) $(LSUP_SRC:.c=.o)
 DBG_OBJ = $(EXT_OBJ) $(CODEC_DBG_OBJ) $(LSUP_SRC:.c=_dbg.o)
 
 DEPLIBS = libxxhash liblmdb
@@ -61,7 +62,8 @@ DOCS = docs
 
 ## Environment.
 
-export LD_LIBRARY_PATH = $(libdir):.
+# Tests need the freshly compiled libs.
+export LD_LIBRARY_PATH = .:$(libdir)
 
 
 ## Rules.
@@ -73,8 +75,8 @@ export LD_LIBRARY_PATH = $(libdir):.
 help:
 	@echo "Command overview:"; echo; \
 		grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
-		| sed -n 's/^\(.*\): \(.*\)##\(.*\)/\1::\3/p' \
-		| column -t  -s '::'
+		| sed -n 's/^\(.*\): \(.*\)##\(.*\)/\1|\3/p' \
+		| column -t  -s '|'
 	
 
 lib: $(DEPLIBS) $(LIBS) ## Compile main library (static and dynamic linking).
@@ -162,11 +164,13 @@ bin/test: debug $(TEST_SRC)
 
 .PHONY: test
 test: bin/test ## Run a test suite.
+	@echo "Using libraries: "; ldd bin/test
 	exec bin/test
 
 
 .PHONY: gdb_test
 gdb_test: bin/test ## Run a test suite within gdb.
+	@echo "Using libraries: "; ldd bin/test
 	exec gdb bin/test
 
 lint:
@@ -182,30 +186,40 @@ lint:
 memcheck:
 	valgrind \
 	--leak-check=full --show-leak-kinds=all --track-origins=yes \
-	--log-file=/tmp/lsup_valgrind.log \
+	--log-file=$(VALGRIND_DUMP) \
 	./bin/test
-	echo "Memcheck complete. Valgrind log is at /tmp/lsup_valgrind.log"
+	echo "Memcheck complete. Valgrind log is at $(VALGRIND_DUMP)"
 
 
 memtest: bin/test memcheck ## Run a test suite using Valgrind. Output to separate file.
 
 
-# Profiling application.
-bin/profile: debug $(TEST_SRC)
-	$(CC) $(CFLAGS) -g -DTESTING $(LDFLAGS) -lliblsuprdf_dbg \
+# Performance test application. Essentially the profiling code without debug.
+bin/profile: debug profile.c
+	$(CC) $(CFLAGS) -g -DTESTING $(LDFLAGS) -llsuprdf_dbg \
 		profile.c -o bin/profile
 
 
+# Performance test application. Essentially the profiling code without debug.
+bin/perftest: lib profile.c
+	$(CC) $(CFLAGS) -g $(LDFLAGS) -llsuprdf profile.c -o bin/perftest
+
+
+.PHONY: perftest
+perftest: bin/perftest ## Run a performance test by creating, inserting and looking up triples.
+	bin/perftest
+
+
 .PHONY: profile
-profile: bin/profile ## Run a profiling session. Output can be inspected with KCachegrind.
-	exec valgrind --tool=callgrind --callgrind-out-file="$(CALLGRIND_DUMP)" \
-		bin/profile 10000 && \
-		echo "Profile dump written at $(CALLGRIND_DUMP)"
+profile: bin/perftest ## Run a profiling session. Output can be inspected with KCachegrind.
+	LSUP_MDB_MAPSIZE=800000 valgrind --tool=callgrind \
+		--callgrind-out-file="$(CALLGRIND_DUMP)" bin/perftest 1000
+	@echo "Profile dump written at $(CALLGRIND_DUMP)"
 
 
 .PHONY: pytest
 pytest: ## Run a test suite for the Python package.
-	pip3 install --user . && \
+	pip3 install --user .
 	python3 test/cpython_test.py
 
 

+ 4 - 4
profile.c

@@ -49,7 +49,7 @@ int main(int argc, char *argv[])
 
     LSUP_Triple *trp = generate_triples(nt);
     tc1 = clock();
-    wallclock = (tc1 - start) / CLOCKS_PER_SEC;
+    wallclock = (double) (tc1 - start) / CLOCKS_PER_SEC;
     log_info ("Time elapsed: %lf s", wallclock);
 
     log_info ("Inserting triples.");
@@ -73,7 +73,7 @@ int main(int argc, char *argv[])
     free (trp);
 
     tc2 = clock();
-    wallclock = (tc2 - tc1) / CLOCKS_PER_SEC;
+    wallclock = (double) (tc2 - tc1) / CLOCKS_PER_SEC;
     log_info ("Time elapsed: %lf s", wallclock);
     log_info ("Graph size: %lu", LSUP_graph_size (gr));
 
@@ -91,10 +91,10 @@ int main(int argc, char *argv[])
     log_info ("Found triples by iteration: %lu", ct);
     LSUP_graph_iter_free (it);
     end = clock();
-    wallclock = (end - tc2) / CLOCKS_PER_SEC;
+    wallclock = (double) (end - tc2) / CLOCKS_PER_SEC;
     log_info ("Time elapsed: %lf s", wallclock);
 
-    wallclock = (end - start) / CLOCKS_PER_SEC;
+    wallclock = (double) (end - start) / CLOCKS_PER_SEC;
     rate = nt / wallclock;
     log_info (
             "%d triples created and inserted in %lf s (%lf triples/s)",

+ 73 - 70
src/environment.c

@@ -49,73 +49,73 @@ LSUP_init (void)
 
     if (LSUP_env_is_init) return rc;
 
-    if (LSUP_default_env == NULL) {
 #ifdef DEBUG
-        // In debug mode, always use max logging.
-        int loglevel = LOG_TRACE;
+    // In debug mode, always use max logging.
+    int loglevel = LOG_TRACE;
 #else
-        char *_loglevel = getenv ("LSUP_LOGLEVEL");
-        int loglevel = (_loglevel == NULL) ? LOG_INFO : atoi (_loglevel);
+    char *_loglevel = getenv ("LSUP_LOGLEVEL");
+    int loglevel = (_loglevel == NULL) ? LOG_INFO : atoi (_loglevel);
 #endif
-        log_set_level (loglevel);
-
-        // URI validation pattern.
-        MALLOC_GUARD (LSUP_uri_ptn, LSUP_MEM_ERR);
-        /* Uncomment in case a change in the URI regex results in an error.
-        int regex_rc = regcomp (LSUP_uri_ptn, LSUP_URI_REGEX_STR, REG_EXTENDED);
-        if (regex_rc != 0) {
-            char err_msg[128];
-            size_t err_msg_sz = regerror (regex_rc, LSUP_uri_ptn, err_msg, 128);
-            log_error (
-                    "Error compiling regular expression pattern: %s.",
-                    err_msg);
-            return LSUP_ERROR;
-        }
-        */
-        if (regcomp (LSUP_uri_ptn, LSUP_URI_REGEX_STR, REG_EXTENDED) != 0) {
-            log_error ("Error compiling regular expression pattern.");
-            return LSUP_ERROR;
-        }
-
-        // Default literal datatype key.
-        LSUP_default_datatype = LSUP_iriref_new (DEFAULT_DTYPE, NULL);
-
-        // Default permanent store path.
-        char *mdb_path = getenv ("LSUP_MDB_STORE_PATH");
-        if (!mdb_path) {
-            mdb_path = DEFAULT_ENV_PATH;
-            log_warn (
-                "`LSUP_MDB_STORE_PATH' environment variable is not "
-                "set. The default location %s will be used as the graph "
-                "store.", mdb_path
-            );
-        }
-
-        // Default permanent store.
-        LSUP_default_env = LSUP_env_new (
-                DEFAULT_CTX_LABEL, mdb_path, NULL);
-
-        // RAM disk store.
-        if (LSUP_mdbstore_setup (LSUP_MDB_RAMDISK_PATH, true) != LSUP_OK)
-            log_error ("Error setting up RAM disk store.");
-
-        LSUP_default_env->mdb_store_ramdisk = LSUP_mdbstore_new (
-                LSUP_MDB_RAMDISK_PATH, LSUP_default_env->default_ctx);
-        if (UNLIKELY (!LSUP_default_env->mdb_store_ramdisk))
-            log_error ("Error setting up RAM disk store.");
-
-        log_info ("Initialized RAM disk back end at %s.", LSUP_MDB_RAMDISK_PATH);
-
-        if (!LSUP_default_env) rc = LSUP_DB_ERR;
-
-        // Set automatic teardown TODO Is this a good idea?
-        atexit (LSUP_done);
-
-        rc = LSUP_OK;
-        LSUP_env_is_init = true;
+    log_set_level (loglevel);
+
+    // URI validation pattern.
+    MALLOC_GUARD (LSUP_uri_ptn, LSUP_MEM_ERR);
+    /* Uncomment in case a change in the URI regex results in an error.
+    int regex_rc = regcomp (LSUP_uri_ptn, LSUP_URI_REGEX_STR, REG_EXTENDED);
+    if (regex_rc != 0) {
+        char err_msg[128];
+        size_t err_msg_sz = regerror (regex_rc, LSUP_uri_ptn, err_msg, 128);
+        log_error (
+                "Error compiling regular expression pattern: %s.",
+                err_msg);
+        return LSUP_ERROR;
     }
+    */
+    if (regcomp (LSUP_uri_ptn, LSUP_URI_REGEX_STR, REG_EXTENDED) != 0) {
+        log_error ("Error compiling regular expression pattern.");
+        return LSUP_ERROR;
+    }
+
+    // Default literal datatype key.
+    LSUP_default_datatype = LSUP_iriref_new (DEFAULT_DTYPE, NULL);
+
+    // Default permanent store path.
+    char *mdb_path = getenv ("LSUP_MDB_STORE_PATH");
+    if (!mdb_path) {
+        mdb_path = DEFAULT_ENV_PATH;
+        log_warn (
+            "`LSUP_MDB_STORE_PATH' environment variable is not "
+            "set. The default location %s will be used as the graph "
+            "store.", mdb_path
+        );
+    }
+
+    // Default permanent store.
+    LSUP_default_env = LSUP_env_new (
+            DEFAULT_CTX_LABEL, mdb_path, NULL);
+    if (UNLIKELY (!LSUP_default_env)) return LSUP_ERROR;
 
-    return rc;
+    // RAM disk store.
+    if (LSUP_mdbstore_setup (LSUP_MDB_RAMDISK_PATH, true) != LSUP_OK) {
+        log_error ("Error setting up RAM disk store files.");
+        return LSUP_DB_ERR;
+    }
+
+    LSUP_default_env->mdb_store_ramdisk = LSUP_mdbstore_new (
+            LSUP_MDB_RAMDISK_PATH, LSUP_default_env->default_ctx);
+    if (UNLIKELY (!LSUP_default_env->mdb_store_ramdisk)) {
+        log_error ("Error setting up RAM disk store.");
+        return LSUP_DB_ERR;
+    }
+
+    log_info ("Initialized RAM disk back end at %s.", LSUP_MDB_RAMDISK_PATH);
+
+    // Set automatic teardown TODO Is this a good idea?
+    atexit (LSUP_done);
+
+    LSUP_env_is_init = true;
+
+    return LSUP_OK;
 }
 
 
@@ -127,14 +127,6 @@ LSUP_env_free (LSUP_Env *env)
     LSUP_buffer_free (env->default_ctx);
     LSUP_nsmap_free (env->nsm);
 
-    // Free ID cache.
-    struct term_cache_t *entry, *tmp;
-    HASH_ITER (hh, LSUP_term_cache, entry, tmp) {
-        HASH_DEL (LSUP_term_cache, entry);
-        LSUP_term_free (entry->term);
-        free (entry);
-    }
-
     free (env);
 }
 
@@ -142,9 +134,20 @@ LSUP_env_free (LSUP_Env *env)
 void
 LSUP_done (void)
 {
+    if (!LSUP_env_is_init) return;
+
     LSUP_env_free (LSUP_default_env);
     regfree (LSUP_uri_ptn);
     free (LSUP_uri_ptn);
 
+    // Free ID cache, including default literal datatype.
+    struct term_cache_t *entry, *tmp;
+    HASH_ITER (hh, LSUP_term_cache, entry, tmp) {
+        HASH_DEL (LSUP_term_cache, entry);
+        LSUP_term_free (entry->term);
+        free (entry);
+    }
+    LSUP_default_datatype = NULL;
+
     LSUP_env_is_init = false;
 }

+ 6 - 5
src/term.c

@@ -84,8 +84,9 @@ LSUP_term_copy (const LSUP_Term *src)
         metadata = (void *) LSUP_iriref_nsm (src);
     else if (src->type == LSUP_TERM_LITERAL)
         metadata = (void *) src->datatype;
-    else if (src->type == LSUP_TERM_LT_LITERAL)
-        memcpy (&metadata, src->lang, sizeof (metadata));
+    else if (src->type == LSUP_TERM_LT_LITERAL) {
+        metadata = (void *) src->lang;
+    }
 
     return LSUP_term_new (src->type, src->data, metadata);
 }
@@ -579,10 +580,10 @@ term_init (
         if (! term->datatype) term->datatype = LSUP_default_datatype;
         log_trace ("Storing data type: %s", term->datatype->data);
 
-        if (! LSUP_IS_IRI (term->datatype )) {
+        if (! LSUP_IS_IRI (term->datatype)) {
             log_error (
-                    "Literal data tpe is not a IRI: %s",
-                    term->datatype ->data);
+                    "Literal data type is not an IRI: %s",
+                    term->datatype->data);
 
             return LSUP_VALUE_ERR;
         }

+ 5 - 2
test/test_graph.c

@@ -193,10 +193,12 @@ test_environment()
     LSUP_done();
     EXPECT_INT_EQ (LSUP_env_is_init, false);
 
-    ASSERT (LSUP_init() > 0, "Environment not initialized!");
+    ASSERT (LSUP_init() >= 0, "Environment not initialized!");
     EXPECT_INT_EQ (LSUP_env_is_init, true);
-    ASSERT (LSUP_init() > 0, "Environment not initialized!");
+    ASSERT (LSUP_init() >= 0, "Environment not initialized!");
     EXPECT_INT_EQ (LSUP_env_is_init, true);
+
+    return 0;
 }
 
 
@@ -277,6 +279,7 @@ static int test_graph_copy()
 
 int graph_tests()
 {
+    RUN (test_environment);
     RUN (test_graph_new);
     RUN (test_graph_add);
     RUN (test_graph_lookup);

+ 1 - 0
test/test_term.c

@@ -296,6 +296,7 @@ int term_tests() {
     RUN (test_iriref);
     RUN (test_iriref_abs_rel);
     RUN (test_literal);
+    RUN (test_term_copy);
     RUN (test_term_serialize_deserialize);
     RUN (test_term_to_key);