Subj : Re: Problem with performance of JSCallFunction To : netscape.public.mozilla.jseng From : c_ibrahim Date : Wed Oct 27 2004 04:03 am > Why should this be slower? It has to set up a stack frame, but so does > JS_ExecuteScript (just not a call frame). Something is not right. You > should profile (gprof, quantify, whatever you have) and see where the > cycles are. It's best to use a hierarchical profiler (either of the two > listed), to avoid attributing time to common subroutines exclusively, > instead of spreading it proportionately among ancestor callers. > > Can you show your code, or mail it to me? Then I could profile it too. I used GetTickCount() in the test code to see how many msec required to execute. What is counted is indeed not only the JS_CallFunction alone but the entire steps required to be able to perform JS_CallFunction. The reasoning is because I need the entire steps anyway so I calculate the time needed for the whole. I did the same in the tryout of JS_ExecuteScript. I took a look into the test code, cleaned it up, and found a mistake. It was remedied and indeed you are right, the performance is similar (for the whole steps to perform each call). Rational Quantify shows that JS_CallFunction itself only takes a slightly more time than JS_ExecuteScript. We concentrate now on JS_CallFunction because it seems to be the best for the purpose 'compile once-execute many times-pass parameters' Unfortunately, the performance of JS_CallFunction is still regarded too slow. We'd like to have it at least 10 times faster. I send you the snippet of the test code used to call JS_CallFunction. There are possibly rooms for improvement there. Your advice is very much appreciated. In case you'd like to see the entire test code, I've sent it to your private email adress. I'm not sure whether the others in the milis would like it :) //IN MAIN .... //instantiating the class responsible in calling SpiderMonkey API JSParser* jsParser = new JSParser( .... //timing starts cmd = "return (p1 < p2);"; vector args; args.push_back("p1"); args.push_back("p2"); if(jsParser->CompileFunction("grade", args, cmd)) { //call functions many times, passing parameters vector parameters; parameters.push_back(2); parameters.push_back(3); for (i = 0; i < numTimes; i++) { jsParser->CallFunction("grade", parameters, result); } } //timing ends //performance = timing ends - timing starts .... //IN JSPARSER //in construnctor .... m_context = new JS_NewContext( m_global = new JS_NewObject( .... bool CJSParser::CompileFunction(const std::string& funcName, const std::vector& args, const std::string& funcBody) { bool success = false; int size = args.size(); const char** argnames = new const char*[size]; for (int index=0; index < size; ++index) { argnames[index] = args[index].c_str(); } const char* filename = 0; uintN lineno = 0; JSFunction* func = JS_CompileFunction(m_context, m_global, funcName.c_str(), args.size(), argnames, funcBody.c_str(), funcBody.length(), filename, lineno); delete [] argnames; if (0!=func) { //removed in this class' destructor if (JS_AddNamedRoot(m_context, func, funcName.c_str())) { //std::map m_functions; m_functions.insert(std::make_pair(funcName, func)); success = true; } } return success; } //Rational Quantify shows that in this function // JS_CallFunction took around 60% time // JS_ValueToInt32 took around 10% time bool CJSParser::CallFunction(const string& funcName, const vector& params, int32& result) { bool success = false; JSFunction* func = m_functions[funcName]; int noParams = params.size(); jsval rval; jsval* argv = new jsval[noParams]; for (int index = 0; index < noParams; ++index) { argv[index] = INT_TO_JSVAL(params[index]); } if (JS_TRUE == JS_CallFunction(m_context, m_global, func, noParams, argv, &rval)) { if (JS_TRUE == JS_ValueToInt32(m_context, rval, &result)) { success = true; } } delete [] argv; return success; } thanks a lot, cath .