大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
JavaScript 是最常用的前端语言, 在后端也渐渐有所应用, 比如 NodeJS, 在C++应用中嵌入JavaScript 到底性能如何?
就拿最流行的 Mozilla SpiderMonkey 和 Google V8 做一个比较测试, 先以 SpiderMonkey 为例, 来执行一个一万个字串的数据排序和反转
1. 下载
https://people.mozilla.org/~sstangl/mozjs-31.2.0.rc0.tar.bz2
bunzip2 mozjs-31.2.0.rc0.tar.bz2
tar xvf mozjs-31.2.0.rc0.tar
2. 构建
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Build_Documentation
2.1 下载 autoconf2.13
http://ftp.gnu.org/gnu/autoconf/autoconf-2.13.tar.gz
tar xvfz autoconf-2.13.tar.gz
./configure –prefix=/usr –program-suffix=-2.13
make acdatadir=/usr/share/autoconf-2.13
make acdatadir=/usr/share/autoconf-2.13 install
2.2 编译步骤
cd js/src
autoconf-2.13
# This name should end with “_OPT.OBJ” to make the version control system ignore it.
mkdir build_OPT.OBJ
cd build_OPT.OBJ
../configure
# Use “mozmake” on Windows
make
make install
————
../../dist/bin/nsinstall -t js-config /usr/local/bin
../../dist/bin/nsinstall -t libjs_static.a /usr/local/lib
mv -f /usr/local/lib/libjs_static.a /usr/local/lib/libmozjs-31.a
../../dist/bin/nsinstall -t libmozjs-31.dylib /usr/local/lib
/Applications/Xcode.app/Contents/Developer/usr/bin/make -C shell install
../../../dist/bin/nsinstall -t js /usr/local/bin
————
2.3 编译验证
# ./dist/bin/js
js> print(“hello world”);
hello world
js> quit();
3. 参考资料
*
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_User_Guide
*
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/How_to_embed_the_JavaScript_engine
4. 测试程序
#include "jsapi.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#define TRACE_MINARGS 2
#define TIME_FMT_LEN 50
using namespace JS;
// The class of the global object.
static JSClass globalClass = { "global", JSCLASS_GLOBAL_FLAGS, JS_PropertyStub,
JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nullptr, nullptr,
nullptr, nullptr, JS_GlobalObjectTraceHook };
long long current_timestamp(char arrTimeStr[TIME_FMT_LEN]) {
struct timeval tv;
struct tm* ptm;
char time_string[40];
gettimeofday(&tv, NULL); // get current time
if (arrTimeStr) {
ptm = localtime(&tv.tv_sec);
/* Format the date and time, down to a single second. */
strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ptm);
/* Compute milliseconds from microseconds. */
//snprintf(char * restrict str, size_t size, const char * restrict format,
snprintf(arrTimeStr, TIME_FMT_LEN, "%s.%06d", time_string, tv.tv_usec);
}
long long total_us = tv.tv_sec * 1000000LL + tv.tv_usec ; // caculate milliseconds
// printf("milliseconds: %lld\n", milliseconds);
return total_us;
}
// [SpiderMonkey 24] Use JSBool instead of bool.
static bool debug_trace(JSContext *cx, unsigned argc, jsval *vp) {
JS::CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() > 0) {
char szTimeStr[TIME_FMT_LEN] = { '#include "jsapi.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#define TRACE_MINARGS 2
#define TIME_FMT_LEN 50
using namespace JS;
// The class of the global object.
static JSClass globalClass = { "global", JSCLASS_GLOBAL_FLAGS, JS_PropertyStub,
JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nullptr, nullptr,
nullptr, nullptr, JS_GlobalObjectTraceHook };
long long current_timestamp(char arrTimeStr[TIME_FMT_LEN]) {
struct timeval tv;
struct tm* ptm;
char time_string[40];
gettimeofday(&tv, NULL); // get current time
if (arrTimeStr) {
ptm = localtime(&tv.tv_sec);
/* Format the date and time, down to a single second. */
strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ptm);
/* Compute milliseconds from microseconds. */
//snprintf(char * restrict str, size_t size, const char * restrict format,
snprintf(arrTimeStr, TIME_FMT_LEN, "%s.%06d", time_string, tv.tv_usec);
}
long long total_us = tv.tv_sec * 1000000LL + tv.tv_usec ; // caculate milliseconds
// printf("milliseconds: %lld\n", milliseconds);
return total_us;
}
// [SpiderMonkey 24] Use JSBool instead of bool.
static bool debug_trace(JSContext *cx, unsigned argc, jsval *vp) {
JS::CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() > 0) {
char szTimeStr[TIME_FMT_LEN] = { '\0' };
current_timestamp(szTimeStr);
JSString *str = args[0].toString();
printf("[%s] %s\n", szTimeStr, JS_EncodeString(cx, str));
}
return true;
}
//typedef void (* JSErrorReporter)(JSContext *cx, const char *message, JSErrorReport *report);
// The error reporter callback.
void report_error(JSContext *cx, const char *message, JSErrorReport *report) {
fprintf(stderr, "%s:%u:%s\n",
report->filename ? report->filename : "[no filename]",
(unsigned int) report->lineno, message);
}
int load_file_malloc(const char* szFile, char*& pBuffer,
long* pBufSize = NULL) {
FILE * pFile = NULL;
long lSize = 0;
size_t result = 0;
pFile = fopen(szFile, "r");
if (pFile == NULL) {
fputs("File open error", stderr);
return 1;
}
// obtain file size:
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
rewind(pFile);
// allocate memory to contain the whole file:
pBuffer = (char*) malloc(sizeof(char) * lSize);
if (pBuffer == NULL) {
fputs("Memory allocate error", stderr);
fclose(pFile);
return 2;
}
// copy the file into the buffer:
result = fread(pBuffer, 1, lSize, pFile);
if (result != lSize) {
fputs("Reading file error", stderr);
fclose(pFile);
return 3;
}
if (pBufSize)
*pBufSize = lSize;
fclose(pFile);
return 0;
}
int test(JSContext *cx, RootedObject* pGlobal, const char* pScript) {
//RootedObject global = *pGlobal;
JS::RootedValue rval(cx);
JSAutoCompartment ac(cx, *pGlobal);
JS_InitStandardClasses(cx, *pGlobal);
const char *filename = "noname";
int lineno = 1;
bool ok = JS_DefineFunction(cx, *pGlobal, "debug_trace", debug_trace,
TRACE_MINARGS, 0);
if (!ok)
return 1;
ok = JS_EvaluateScript(cx, *pGlobal, pScript, strlen(pScript), filename,
lineno, &rval);
if (!ok)
return 2;
//JSString *str = rval.toString();
//printf("%s\n", JS_EncodeString(cx, str));
return 0;
}
int run(JSContext *cx, const char* pScript) {
// Enter a request before running anything in the context.
JSAutoRequest ar(cx);
// Create the global object and a new compartment.
RootedObject global(cx);
global = JS_NewGlobalObject(cx, &globalClass, nullptr,
JS::DontFireOnNewGlobalHook);
if (!global)
return 1;
// Enter the new global object's compartment.
JSAutoCompartment ac(cx, global);
// Populate the global object with the standard globals, like Object and
// Array.
if (!JS_InitStandardClasses(cx, global))
return 1;
// Your application code here. This may include JSAPI calls to create your
// own custom JS objects and run scripts.
long long begin_time = current_timestamp(NULL);
test(cx, &global, pScript);
long long end_time = current_timestamp(NULL);
printf("calling costs %lld microseconds\n", end_time - begin_time);
return 0;
}
int main(int argc, const char *argv[]) {
// Initialize the JS engine.
if (!JS_Init())
return 1;
// Create a JS runtime.
JSRuntime *rt = JS_NewRuntime(8L * 1024L * 1024L, JS_USE_HELPER_THREADS);
if (!rt)
return 1;
// Create a context.
JSContext *cx = JS_NewContext(rt, 8192);
if (!cx)
return 1;
//JS_SetErrorReporter(JSContext *cx, JSErrorReporter er);
JS_SetErrorReporter(cx, report_error);
int status = 0;
if (argc > 1) {
char* buffer = NULL;
int ret = load_file_malloc(argv[1], buffer);
if (ret != 0) {
return ret;
}
status = run(cx, buffer);
// free
if (buffer)
free(buffer);
} else {
const char *script = "'hello'+'world, it is '+new Date()";
status = run(cx, script);
}
// Shut everything down.
JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
JS_ShutDown();
return status;
}
' };
current_timestamp(szTimeStr);
JSString *str = args[0].toString();
printf("[%s] %s\n", szTimeStr, JS_EncodeString(cx, str));
}
return true;
}
//typedef void (* JSErrorReporter)(JSContext *cx, const char *message, JSErrorReport *report);
// The error reporter callback.
void report_error(JSContext *cx, const char *message, JSErrorReport *report) {
fprintf(stderr, "%s:%u:%s\n",
report->filename ? report->filename : "[no filename]",
(unsigned int) report->lineno, message);
}
int load_file_malloc(const char* szFile, char*& pBuffer,
long* pBufSize = NULL) {
FILE * pFile = NULL;
long lSize = 0;
size_t result = 0;
pFile = fopen(szFile, "r");
if (pFile == NULL) {
fputs("File open error", stderr);
return 1;
}
// obtain file size:
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
rewind(pFile);
// allocate memory to contain the whole file:
pBuffer = (char*) malloc(sizeof(char) * lSize);
if (pBuffer == NULL) {
fputs("Memory allocate error", stderr);
fclose(pFile);
return 2;
}
// copy the file into the buffer:
result = fread(pBuffer, 1, lSize, pFile);
if (result != lSize) {
fputs("Reading file error", stderr);
fclose(pFile);
return 3;
}
if (pBufSize)
*pBufSize = lSize;
fclose(pFile);
return 0;
}
int test(JSContext *cx, RootedObject* pGlobal, const char* pScript) {
//RootedObject global = *pGlobal;
JS::RootedValue rval(cx);
JSAutoCompartment ac(cx, *pGlobal);
JS_InitStandardClasses(cx, *pGlobal);
const char *filename = "noname";
int lineno = 1;
bool ok = JS_DefineFunction(cx, *pGlobal, "debug_trace", debug_trace,
TRACE_MINARGS, 0);
if (!ok)
return 1;
ok = JS_EvaluateScript(cx, *pGlobal, pScript, strlen(pScript), filename,
lineno, &rval);
if (!ok)
return 2;
//JSString *str = rval.toString();
//printf("%s\n", JS_EncodeString(cx, str));
return 0;
}
int run(JSContext *cx, const char* pScript) {
// Enter a request before running anything in the context.
JSAutoRequest ar(cx);
// Create the global object and a new compartment.
RootedObject global(cx);
global = JS_NewGlobalObject(cx, &globalClass, nullptr,
JS::DontFireOnNewGlobalHook);
if (!global)
return 1;
// Enter the new global object's compartment.
JSAutoCompartment ac(cx, global);
// Populate the global object with the standard globals, like Object and
// Array.
if (!JS_InitStandardClasses(cx, global))
return 1;
// Your application code here. This may include JSAPI calls to create your
// own custom JS objects and run scripts.
long long begin_time = current_timestamp(NULL);
test(cx, &global, pScript);
long long end_time = current_timestamp(NULL);
printf("calling costs %lld microseconds\n", end_time - begin_time);
return 0;
}
int main(int argc, const char *argv[]) {
// Initialize the JS engine.
if (!JS_Init())
return 1;
// Create a JS runtime.
JSRuntime *rt = JS_NewRuntime(8L * 1024L * 1024L, JS_USE_HELPER_THREADS);
if (!rt)
return 1;
// Create a context.
JSContext *cx = JS_NewContext(rt, 8192);
if (!cx)
return 1;
//JS_SetErrorReporter(JSContext *cx, JSErrorReporter er);
JS_SetErrorReporter(cx, report_error);
int status = 0;
if (argc > 1) {
char* buffer = NULL;
int ret = load_file_malloc(argv[1], buffer);
if (ret != 0) {
return ret;
}
status = run(cx, buffer);
// free
if (buffer)
free(buffer);
} else {
const char *script = "'hello'+'world, it is '+new Date()";
status = run(cx, script);
}
// Shut everything down.
JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
JS_ShutDown();
return status;
}
测试JavaScript 脚本
function random_str()
{
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 8; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
var array = new Array();
for ( var i = 0; i < 10000; i++)
{
array[array.length] = random_str();
}
debug_trace("begin sort and reverse array which length=" + array.length );
array.sort();
array.reverse();
debug_trace("done, first element=" + array[0]+ ", " + "last element=" + array[array.length-1] );
测试结果
$ ./test/SpiderMonkeyTest ./test/arraysort.js
[2015-05-07 21:07:29.762895] begin sort and reverse array which length=10000
[2015-05-07 21:07:29.766270] done, first element=zzjG0Pnh, last element=0000LZbe
calling costs 52492 microseconds
性能还可以, 总执行时间花费52 毫秒, JS数组排序反转大约用了4 毫秒多, 下一步看看 Google V8 的表现如何
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/184323.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...