JavaScript 引擎性能比较之一SpiderMonkey
来源:互联网 发布:唱歌挣钱的软件 编辑:程序博客网 时间:2024/05/24 02:33
JavaScript 是最常用的前端语言, 在后端也渐渐有所应用, 比如 NodeJS, 在C++应用中嵌入JavaScript 到底性能如何?
就拿最流行的 Mozilla SpiderMonkey 和 Google V8 做一个比较测试, 先以 SpiderMonkey 为例, 来执行一个一万个字串的数据排序和反转
1. 下载
https://people.mozilla.org/~sstangl/mozjs-31.2.0.rc0.tar.bz2bunzip2 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 50using 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;}
测试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 的表现如何
0 0
- JavaScript 引擎性能比较之一SpiderMonkey
- SpiderMonkey:Javascript引擎
- JavaScript 引擎 SpiderMonkey
- JavaScript 引擎 SpiderMonkey
- JavaScript脚本引擎SpiderMonkey
- 功能强大的JavaScript引擎--SpiderMonkey
- SpiderMonkey引擎解析JavaScript脚本
- 功能强大的JavaScript引擎--SpiderMonkey
- 功能强大的JavaScript引擎--SpiderMonkey
- 功能强大的JavaScript引擎--SpiderMonkey
- javascript引擎PK:V8 vs Spidermonkey
- javascript引擎PK:V8 vs Spidermonkey
- javascript引擎PK:V8 vs Spidermonkey
- javascript引擎 PK: V8 vs Spidermonkey
- 功能强大的JavaScript引擎--SpiderMonkey与实现
- 使用 SpiderMonkey 使 C++应用支持 JavaScript 脚本引擎
- 使用 SpiderMonkey 使 C++应用支持 JavaScript 脚本引擎
- 在你的C程序中嵌入SpiderMonkey JavaScript引擎
- 关于socket绑定INADDR_ANY
- sql效率
- linux 设置永久ip
- Linux汇编教程03:大小比较操作
- 在PHP语言中使用JSON
- JavaScript 引擎性能比较之一SpiderMonkey
- ps视频 李涛
- How to Get iWork for Free on Older Macs
- UVA11174vector实现树的搜索和使用逆元求a/b%n
- WIFI DIRECT开发(三)P2P传输技术-WIFI Direct
- hdu 5098 Smart Software Installer 拓扑排序or记忆化搜索
- sql学习笔记4:多表查询
- 线性表-链表(一)
- 《c++编程》第3章第38题