Are there ways to keep compiled binaries between executions?

15 views
Skip to first unread message

Philippe Roy

unread,
Dec 26, 2009, 5:15:59 PM12/26/09
to v8-users
I am currently using v8 as my javascript engine in order to calculate
conceptual representations of natural language input. It works
extremely well, but I feel that it could have better performance.

In my snippet of code lower, I first compile the javascript source,
and then execute it. I have tried to keep the script variable into a
cache so that I wouldn't need to compile it on the second pass, but it
appears the script variable only lives within the context under which
it was compiled. This is a sad limitation that I would like to get rid
of. Is there a way to do that?

Handle<Value> ExecuteJavascriptString(Persistent<Context> context,
string dSourceStr, string nameStr, bool skiptrace) throw
(CMathematicalError)
{
// Enter the created context for compiling and
// running the hello world script.
Context::Scope context_scope(context);

Handle<Value> result;
Handle<String> source = String::New(dSourceStr.c_str());
Handle<Script> script;
Handle<Value> name = String::New(nameStr.c_str());
{
TryCatch try_catch;
script = Script::Compile(source, name);
if (script.IsEmpty())
{
String::AsciiValue error(try_catch.Exception());
string tmpString = *error;
throw(new CMathematicalError(tmpString));
}
}
string indent = "";
if ((!skiptrace) && (DigitalConceptBuilder::GetCurCalculationContext
()->GetJavascriptTrace()))
{
for (int i = 0; i < g_alreadyReporting; i++)
{
indent += "\t";
}
Handle<Value> dCurPredicate = ExecuteJavascriptString(context, "var
curPredicate; curPredicate", "trace", true);
string dCurPredicateStr = ProcessValueToDisplay(dCurPredicate,
false);
Handle<Value> dCurNode = ExecuteJavascriptString(context, "var
curNode; curNode", "trace", true);
string dCurNodeStr = ProcessValueToDisplay(dCurNode, false);
printf("%s %s %s %s\n%s[\n", g_nodeContext.empty()?"":(indent +
"NODE:" + g_nodeContext.top()->GetNodeDesc() + ((g_nodeContext.top()-
>GetConstructionLine() != "")?(", " + g_nodeContext.top()-
>GetConstructionLine()):"")).c_str(), g_sourceContext.empty()?"":
(g_nodeContext.empty()?"":"\n" + indent + "REF:\"" +
g_sourceContext.top() + "\"").c_str(), ("\n" + indent + "curPredicate:
" + dCurPredicateStr).c_str(), ("\n" + indent + "curNode: " +
dCurNodeStr).c_str(), indent.c_str());
SearchAndReplace(dSourceStr, "\n", "\1");
SearchAndReplace(dSourceStr, "\1", "\n\t" + indent);
SearchAndReplace(dSourceStr, "\r\n", "\1");
SearchAndReplace(dSourceStr, "\1", "\n");
printf("%s\t%s", indent.c_str(), dSourceStr.c_str());
printf("\n");
}
g_alreadyReporting++;
result = script->Run();
g_alreadyReporting--;
if ((!skiptrace) && (DigitalConceptBuilder::GetCurCalculationContext
()->GetJavascriptTrace()))
{
string dDisplay = ProcessValueToDisplay(result, true);
SearchAndReplace(dDisplay, "\n", "\1");
SearchAndReplace(dDisplay, "\1", "\n" + indent);
Handle<Value> dCurPredicate = ExecuteJavascriptString(context, "var
curPredicate; curPredicate", "trace", true);
string dCurPredicateStr = ProcessValueToDisplay(dCurPredicate,
false);
printf("%s] -> %s, curPredicate -> %s\n\n", indent.c_str(),
dDisplay.c_str(), dCurPredicateStr.c_str());
}
return result;
}

Bryan White

unread,
Dec 27, 2009, 8:27:55 AM12/27/09
to v8-u...@googlegroups.com
On Sat, Dec 26, 2009 at 5:15 PM, Philippe Roy <pr...@conceptualspeech.com> wrote:
> I am currently using v8 as my javascript engine in order to calculate
> conceptual representations of natural language input. It works
> extremely well, but I feel that it could have better performance.
>
> In my snippet of code lower, I first compile the javascript source,
> and then execute it. I have tried to keep the   script variable into a
> cache so that I wouldn't need to compile it on the second pass, but it
> appears the script variable only lives within the context under which
> it was compiled. This is a sad limitation that I would like to get rid
> of. Is there a way to do that?

I keep a cache of contexts around. The downside is data can be left
in the global scope from one execution to the next. I try to prevent
this by:

1) creating before each execution a 'Request' object and placing it
in the Global object.
2) Installing an interceptor in the global object to prevent
assignments during script execution.

The idea is to have the scripts use the Request object as a place to
install globals. There are probably a lot of ways to get information
bleed that the interceptor will not catch. I trust my script
programmers to not be intentionally doing bad things and the
interceptor catches most of the accidents. Third party javascript
libraries may not play be the rules however.

Note, the interceptor is not active when the script is 'Run', only
later when I call a script provided function.

--
Bryan White

Bryan White

unread,
Dec 27, 2009, 8:33:37 AM12/27/09
to v8-u...@googlegroups.com
One more note on this approach. It is actually faster then keeping a
cache of the script objects. This is because I both compile and run
the script at the time that the cache miss occurs. The fast path just
creates a fresh 'Request' object and calls the function.

--
Bryan White

Philippe Roy

unread,
Dec 27, 2009, 10:20:05 AM12/27/09
to v8-u...@googlegroups.com
Would you be able to provide sample code?

> --
> v8-users mailing list
> v8-u...@googlegroups.com
> http://groups.google.com/group/v8-users
>

Søren Gjesse

unread,
Dec 27, 2009, 5:18:13 PM12/27/09
to v8-u...@googlegroups.com
You might be able to use the Script::New instead of Script::Compile, as Script::New creates a context independent Script object. Take a look at the comments in include/v8.h for the difference between these two ways of compiling a script.

Regards,
Søren

Philippe Roy

unread,
Dec 28, 2009, 9:59:21 AM12/28/09
to v8-u...@googlegroups.com
That worked! After spending about 2-3 hours to get v8 to build
(installing scons, python and figuring out the instructions), I
finally got v8.lib.

After much expectations to see my performance unleashed as a result of
the fact that I was not to compile every time anymore, it was with
some deception that I can now observe the performance to have been
untouched. That, and the fact that v8.lib is more than 100 MB in size
(so much for my small code snippet that I wanted to include into
thecodeproject.com).

2009/12/27 Søren Gjesse <sgj...@chromium.org>:

Bryan White

unread,
Dec 31, 2009, 12:05:14 PM12/31/09
to v8-u...@googlegroups.com
On Mon, Dec 28, 2009 at 9:59 AM, Philippe Roy <pr...@conceptualspeech.com> wrote:
> After much expectations to see my performance unleashed as a result of
> the fact that I was not to compile every time anymore, it was with
> some deception that I can now observe the performance to have been
> untouched. That, and the fact that v8.lib is more than 100 MB in size
> (so much for my small code snippet that I wanted to include into
> thecodeproject.com).

My libv8.a (Linux static lib) is 4.7MB. If I strip it, it drops to
2.9MB. My programs that use the v8 are running in the 3 to 3.5MB
range (stripped).

--
Bryan White

Reply all
Reply to author
Forward
0 new messages