From 574ccee478b9da9457cdf0e476b8df6eb584b580 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Mon, 16 Jul 2012 06:48:11 +0000 Subject: Minor memory management, performance, and tracing improvements. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1361917 13f79535-47bb-0310-9956-ffa450edef68 --- sca-cpp/trunk/modules/atom/atom-test.cpp | 1 + sca-cpp/trunk/modules/js/eval.hpp | 15 ++++-- sca-cpp/trunk/modules/js/js-test.cpp | 1 + sca-cpp/trunk/modules/json/json-test.cpp | 38 ++++++++++++++ sca-cpp/trunk/modules/python/eval.hpp | 75 +++++++++++++++++++--------- sca-cpp/trunk/modules/python/python-test.cpp | 37 ++++++++++++-- sca-cpp/trunk/modules/rss/rss-test.cpp | 1 + sca-cpp/trunk/modules/scdl/scdl-test.cpp | 1 + sca-cpp/trunk/modules/scheme/scheme-test.cpp | 1 + 9 files changed, 138 insertions(+), 32 deletions(-) (limited to 'sca-cpp/trunk/modules') diff --git a/sca-cpp/trunk/modules/atom/atom-test.cpp b/sca-cpp/trunk/modules/atom/atom-test.cpp index e00c75a62f..479ed64f29 100644 --- a/sca-cpp/trunk/modules/atom/atom-test.cpp +++ b/sca-cpp/trunk/modules/atom/atom-test.cpp @@ -273,6 +273,7 @@ bool testFeed() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::atom::testEntry(); diff --git a/sca-cpp/trunk/modules/js/eval.hpp b/sca-cpp/trunk/modules/js/eval.hpp index 21fa274d2c..f8f4cbe598 100644 --- a/sca-cpp/trunk/modules/js/eval.hpp +++ b/sca-cpp/trunk/modules/js/eval.hpp @@ -65,7 +65,7 @@ public: JSRuntime() { // Create JS runtime debug("js::jsruntime"); - rt = JS_NewRuntime(32L * 1024L * 1024L); + rt = JS_NewRuntime(1L * 512L * 1024L); if(rt == NULL) cleanup(); } @@ -114,14 +114,19 @@ public: debug("js::jscontext"); if (jsContext != NULL) { cx = jsContext; + JS_BeginRequest(cx); return; } + debug("js::jsnewcontext"); cx = JS_NewContext(jsRuntime, 8192); if(cx == NULL) return; + JS_BeginRequest(cx); + JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT); JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, reportError); + //JS_SetGCZeal(cx, 2); // Create global JS object global = JS_NewCompartmentAndGlobalObject(cx, &jsGlobalClass, NULL); @@ -140,8 +145,6 @@ public: ~JSContext() { debug("js::~jscontext"); - if (cx != NULL) - JS_MaybeGC(cx); cleanup(); } @@ -156,8 +159,12 @@ public: private: bool cleanup() { if(cx != NULL) { - if (cx != jsContext) + JS_MaybeGC(cx); + JS_EndRequest(cx); + if (cx != jsContext) { + debug("js::jsdestroycontext"); JS_DestroyContext(cx); + } cx = NULL; } return true; diff --git a/sca-cpp/trunk/modules/js/js-test.cpp b/sca-cpp/trunk/modules/js/js-test.cpp index 9cbf000ac3..a7e5597610 100644 --- a/sca-cpp/trunk/modules/js/js-test.cpp +++ b/sca-cpp/trunk/modules/js/js-test.cpp @@ -42,6 +42,7 @@ bool testJSEval() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::js::testJSEval(); diff --git a/sca-cpp/trunk/modules/json/json-test.cpp b/sca-cpp/trunk/modules/json/json-test.cpp index 61aac4ee02..945b6c072c 100644 --- a/sca-cpp/trunk/modules/json/json-test.cpp +++ b/sca-cpp/trunk/modules/json/json-test.cpp @@ -27,6 +27,7 @@ #include "stream.hpp" #include "string.hpp" #include "json.hpp" +#include "perf.hpp" namespace tuscany { namespace json { @@ -74,6 +75,7 @@ const string jsarray("{\n" "}"); bool testJSON() { + gc_scoped_pool pool; const js::JSContext cx; { @@ -217,6 +219,7 @@ const string jsechores("{\n" "}"); bool testJSONRPC() { + gc_scoped_pool pool; js::JSContext cx; { const string lm("{\"id\": 1, \"method\": \"test\", \"params\": []}"); @@ -283,14 +286,49 @@ bool testJSONRPC() { return true; } +struct testReadWrite { + testReadWrite() { + } + const bool operator()() const { + gc_scoped_pool pool; + js::JSContext cx; + + const list ad = mklist(mklist(attribute, "city", string("san francisco")), mklist(attribute, "state", string("ca"))); + const list ac = mklist(mklist(element, "id", string("1234")), mklist(attribute, "balance", 1000)); + const list cr = mklist(mklist (attribute, "name", string("jdoe")), cons(element, cons("address", ad)), cons(element, cons("account", ac))); + const list c = mklist(cons(element, cons("customer", cr))); + + ostringstream os; + writeJSON(jsonWriter, &os, c, cx); + assert(str(os) == jscustomer); + + istringstream is(jscustomer); + const list il = streamList(is); + const list r = content(readJSON(il, cx)); + assert(r == c); + return true; + } +}; + +bool testJSONPerf() { + gc_scoped_pool pool; + + const lambda rwl = lambda(testReadWrite()); + cout << "JSON read + write test " << time(rwl, 5, 200) << " ms" << endl; + + return true; +} + } } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::json::testJSON(); tuscany::json::testJSONRPC(); + tuscany::json::testJSONPerf(); tuscany::cout << "OK" << tuscany::endl; diff --git a/sca-cpp/trunk/modules/python/eval.hpp b/sca-cpp/trunk/modules/python/eval.hpp index da5d226789..5c0be7d261 100644 --- a/sca-cpp/trunk/modules/python/eval.hpp +++ b/sca-cpp/trunk/modules/python/eval.hpp @@ -26,6 +26,8 @@ * Python script evaluation logic. */ #if PYTHON_VERSION == 27 +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE #include #include #include @@ -71,15 +73,12 @@ public: PythonRuntime() { debug("python::pythonruntime"); + // Save current process id #ifdef WANT_THREADS pthread_mutex_init(&mutex, NULL); - -#ifdef IS_DARWIN - // Save current process id pthread_mutex_init(&pidmutex, NULL); - pid = processId(); -#endif #endif + pid = processId(); // Initialize the Python interpreter #ifdef IS_DARWIN @@ -134,11 +133,9 @@ public: private: #ifdef WANT_THREADS pthread_mutex_t mutex; -#ifdef IS_DARWIN pthread_mutex_t pidmutex; - unsigned long pid; -#endif #endif + unsigned long pid; friend class PythonThreadIn; friend class PythonThreadOut; @@ -177,8 +174,8 @@ const string lastError(PythonRuntime* py) { PyObject* trace = NULL; PyErr_Fetch(&type, &val, &trace); if (type != NULL && val != NULL) { - PyObject* stype = PyObject_Str(type); - PyObject* sval = PyObject_Str(val); + PyObject* stype = PyObject_Repr(type); + PyObject* sval = PyObject_Repr(val); string msg = string() + PyString_AsString(stype) + " : " + PyString_AsString(sval) + lastErrorTrace(trace); pyDecRef(stype, py); pyDecRef(sval, py); @@ -220,11 +217,10 @@ private: class PythonThreadIn { public: PythonThreadIn(PythonRuntime* py) : py(py) { -#ifdef WANT_THREADS -#ifdef IS_DARWIN // Reinitialize Python thread support after a fork const unsigned long pid = processId(); +#ifdef WANT_THREADS if (pid != py->pid) { pthread_mutex_lock(&py->pidmutex); if (pid != py->pid) { @@ -236,16 +232,26 @@ public: } pthread_mutex_unlock(&py->pidmutex); } -#endif // Acquire the Python GIL //debug("python::gil::ensure"); gstate = PyGILState_Ensure(); //debug("python::gil::ensured"); +#else + if (pid != py->pid) { + debug("python::afterfork"); + PyOS_AfterFork(); + debug("python::afterforked"); + py->pid = pid; + } #endif } ~PythonThreadIn() { + // Run Python cyclic reference garbage collector + //const size_t c = PyGC_Collect(); + //debug(c, "python::gc::collect::c"); + #ifdef WANT_THREADS // Release the Python GIL //debug("python::gil::release"); @@ -520,7 +526,6 @@ PyObject* valueToPyObject(const value& v, PythonRuntime* py) { /** * Convert a python tuple to a list of values. */ - const list pyTupleToValuesHelper(PyObject* o, const size_t i, const size_t size, PythonRuntime* py) { if (i == size) return list(); @@ -546,6 +551,15 @@ struct pyCallable { pyCallable(const pyCallable& c) : func(c.func), py(c.py), owner(false) { } + const pyCallable& operator=(const pyCallable& c) { + if(this == &c) + return *this; + func = c.func; + py = c.py; + owner = false; + return *this; + } + ~pyCallable() { if (!owner) return; @@ -554,8 +568,7 @@ struct pyCallable { const value operator()(const list& args) const { PythonThreadIn pyin(py); - { - // Temp + if (debug_islogging()) { PyObject* rfunc = PyObject_Repr(func); char* s = NULL; Py_ssize_t l = 0; @@ -564,8 +577,7 @@ struct pyCallable { pyDecRef(rfunc, py); } PyObject* pyargs = valuesToPyTuple(args, py); - { - // Temp + if (debug_islogging()) { PyObject* rargs = PyObject_Repr(pyargs); char* s = NULL; Py_ssize_t l = 0; @@ -573,9 +585,11 @@ struct pyCallable { debug(string(s, l), "python::operator()::args"); pyDecRef(rargs, py); } + PyObject* result = PyObject_CallObject(func, pyargs); - const value v = pyObjectToValue(result, py); pyDecRef(pyargs, py); + + const value v = pyObjectToValue(result, py); pyDecRef(result, py); return v; } @@ -605,6 +619,8 @@ const value pyObjectToValue(PyObject *o, PythonRuntime* py) { return value((double)PyFloat_AsDouble(o)); if (PyTuple_Check(o)) return pyTupleToValues(o, py); + if (PyObject_TypeCheck(o, &pyLambda_type)) + return *(((pyLambda*)o)->func); if (PyCallable_Check(o)) return lambda&)>(pyCallable(o, py)); return value(); @@ -646,10 +662,14 @@ const failable evalScript(const value& expr, PyObject* script, PythonRunt // Call the function PyObject* result = PyObject_CallObject(func, args); + if (result == NULL) { + const string msg = lastError(&py); + pyDecRef(func, &py); + pyDecRef(args, &py); + return mkfailure(string("Function call failed: ") + car(expr) + " : " + msg); + } pyDecRef(func, &py); pyDecRef(args, &py); - if (result == NULL) - return mkfailure(string("Function call failed: ") + car(expr) + " : " + lastError(&py)); // Convert python result to a value const value v = pyObjectToValue(result, &py); @@ -680,10 +700,19 @@ const failable readScript(const string& name, const string& path, ist return mkfailure(string("Couldn't compile script: ") + path + " : " + lastError(&py)); PyObject* mod = PyImport_ExecCodeModuleEx(const_cast(c_str(name)), code, const_cast(c_str(path))); if (mod == NULL) { + const string msg = lastError(&py); pyDecRef(code, &py); - return mkfailure(string("Couldn't import module: ") + path + " : " + lastError(&py)); + return mkfailure(string("Couldn't import module: ") + path + " : " + msg); } - return mod; + pyDecRef(code, &py); + pyDecRef(mod, &py); + + // Lookup the loaded module + PyObject *lmod = PyDict_GetItemString(mods, const_cast(c_str(name))); + if (lmod != NULL) + return lmod; + + return mkfailure(string("Couldn't lookup module: ") + path); } /** diff --git a/sca-cpp/trunk/modules/python/python-test.cpp b/sca-cpp/trunk/modules/python/python-test.cpp index bc275f27c7..29a66cc2e7 100644 --- a/sca-cpp/trunk/modules/python/python-test.cpp +++ b/sca-cpp/trunk/modules/python/python-test.cpp @@ -42,7 +42,7 @@ bool testEvalExpr() { PythonRuntime py; istringstream is(testPythonAdd); - failable script = readScript("script", "script.py", is, py); + failable script = readScript("script1", "script1.py", is, py); assert(hasContent(script)); const value exp = mklist("add", 2, 3); @@ -54,6 +54,29 @@ bool testEvalExpr() { return true; } +const string testPythonMap = + "def addmap(x, y):\n" + " return tuple(map(lambda i: i + y, x))\n"; + +bool testEvalList() { + gc_scoped_pool pool; + PythonRuntime py; + + istringstream is(testPythonMap); + failable script = readScript("script2", "script2.py", is, py); + assert(hasContent(script)); + + const value exp = mklist("addmap", mklist(1, 2, 3), 1); + const failable r = evalScript(exp, content(script), py); + assert(hasContent(r)); + assert(car(content(r)) == value(2)); + assert(cadr(content(r)) == value(3)); + assert(caddr(content(r)) == value(4)); + + releaseScript(content(script), py); + return true; +} + const value mult(const list& args) { const double x = car(args); const double y = cadr(args); @@ -104,7 +127,7 @@ struct testEvalReadAdd { } const bool operator()() const { istringstream is(testPythonAdd); - failable script = readScript("script", "script.py", is, py); + failable script = readScript("script3", "script3.py", is, py); assert(hasContent(script)); const value exp = mklist("add", 2, 3); @@ -139,7 +162,7 @@ bool testEvalPerf() { cout << "Python read + eval test " << time(erl, 5, 10000) << " ms" << endl; istringstream is(testPythonAdd); - failable script = readScript("script", "script.py", is, py); + failable script = readScript("script4", "script4.py", is, py); assert(hasContent(script)); const lambda el = lambda(testEvalAdd(content(script), py)); @@ -158,7 +181,7 @@ struct testReadEvalAddLoop { const bool operator()() const { for (int i = 0; i < 100; i++) { istringstream is(testPythonAdd); - failable script = readScript("script", "script.py", is, py); + failable script = readScript("script6", "script6.py", is, py); assert(hasContent(script)); const value exp = mklist("add", 2, 3); @@ -247,7 +270,7 @@ bool testThreads() { cout << "Python eval + read thread test " << time(elr, 1, 1) / 10000.0 << " ms" << endl; istringstream is(testPythonAdd); - failable script = readScript("script", "script.py", is, py); + failable script = readScript("script7", "script7.py", is, py); assert(hasContent(script)); const lambda el = lambda(testEvalThreads(w, max, content(script), py)); @@ -263,9 +286,13 @@ bool testThreads() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::python::testEvalExpr(); + tuscany::python::testEvalList(); + tuscany::python::testEvalLambda(); + tuscany::python::testEvalLambda(); tuscany::python::testEvalLambda(); tuscany::python::testEvalPerf(); #ifdef WANT_THREADS diff --git a/sca-cpp/trunk/modules/rss/rss-test.cpp b/sca-cpp/trunk/modules/rss/rss-test.cpp index b30792bfe1..be1dcac574 100644 --- a/sca-cpp/trunk/modules/rss/rss-test.cpp +++ b/sca-cpp/trunk/modules/rss/rss-test.cpp @@ -240,6 +240,7 @@ bool testFeed() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::rss::testEntry(); diff --git a/sca-cpp/trunk/modules/scdl/scdl-test.cpp b/sca-cpp/trunk/modules/scdl/scdl-test.cpp index 94baf930a9..4c10f515df 100644 --- a/sca-cpp/trunk/modules/scdl/scdl-test.cpp +++ b/sca-cpp/trunk/modules/scdl/scdl-test.cpp @@ -110,6 +110,7 @@ bool testProperties() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::scdl::testComposite(); diff --git a/sca-cpp/trunk/modules/scheme/scheme-test.cpp b/sca-cpp/trunk/modules/scheme/scheme-test.cpp index dd97bc358d..5b69b8e588 100644 --- a/sca-cpp/trunk/modules/scheme/scheme-test.cpp +++ b/sca-cpp/trunk/modules/scheme/scheme-test.cpp @@ -225,6 +225,7 @@ bool testEvalGC() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::scheme::testEnv(); -- cgit v1.2.3