JavaScript 引擎性能比较之一SpiderMonkey[通俗易懂]

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] = { '\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 的表现如何

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/184323.html原文链接:https://javaforall.cn

原文地址:https://cloud.tencent.com/developer/article/2152823

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 连接 连接池产生原因 连接池实现原理 小结 TEMPERANCE:Eat not to dullness;drink not to elevation.节制
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 一个优秀的工程师和一个普通的工程师的区别,不是满天飞的架构图,他的功底体现在所写的每一行代码上。-- 毕玄 1. 命名风格 【书摘】类名用 UpperCamelC
今天犯了个错:“接口变动,伤筋动骨,除非你确定只有你一个人在用”。哪怕只是throw了一个新的Exception。哈哈,这是我犯的错误。一、接口和抽象类类,即一个对象。先抽象类,就是抽象出类的基础部分,即抽象基类(抽象类)。官方定义让人费解,但是记忆方法是也不错的 —包含抽象方法的类叫做抽象类。接口
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket一、引子文件,作为常见的数据源。关于操作文件的字节流就是 —FileInputStream&amp;FileOutputStream。
作者:泥沙砖瓦浆木匠网站:http://blog.csdn.net/jeffli1993个人签名:打算起手不凡写出鸿篇巨作的人,往往坚持不了完成第一章节。交流QQ群:【编程之美 365234583】http://qm.qq.com/cgi-bin/qm/qr?k=FhFAoaWwjP29_Aonqz
本文目录 线程与多线程 线程的运行与创建 线程的状态 1 线程与多线程 线程是什么? 线程(Thread)是一个对象(Object)。用来干什么?Java 线程(也称 JVM 线程)是 Java 进程内允许多个同时进行的任务。该进程内并发的任务成为线程(Thread),一个进程里至少一个线程。 Ja
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket在面向对象编程中,编程人员应该在意“资源”。比如?1String hello = &quot;hello&quot;; 在代码中,我们
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 这是泥瓦匠的第103篇原创 《程序兵法:Java String 源码的排序算法(一)》 文章工程:* JDK 1.8* 工程名:algorithm-core-le
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 一、父子类变量名相同会咋样? 有个小故事,今天群里面有个人问下面如图输出什么? 我回答:60。但这是错的,答案结果是 40 。我知错能改,然后说了下父子类变
作者:泥瓦匠 出处:https://www.bysocket.com/2021-10-26/mac-create-files-from-the-root-directory.html Mac 操作系统挺适合开发者进行写代码,最近碰到了一个问题,问题是如何在 macOS 根目录创建文件夹。不同的 ma
作者:李强强上一篇,泥瓦匠基础地讲了下Java I/O : Bit Operation 位运算。这一讲,泥瓦匠带你走进Java中的进制详解。一、引子在Java世界里,99%的工作都是处理这高层。那么二进制,字节码这些会在哪里用到呢?自问自答:在跨平台的时候,就凸显神功了。比如说文件读写,数据通信,还
1 线程中断 1.1 什么是线程中断? 线程中断是线程的标志位属性。而不是真正终止线程,和线程的状态无关。线程中断过程表示一个运行中的线程,通过其他线程调用了该线程的 方法,使得该线程中断标志位属性改变。 深入思考下,线程中断不是去中断了线程,恰恰是用来通知该线程应该被中断了。具体是一个标志位属性,
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want需求 项目在设计表的时候,要处理并发多的一些数据,类似订单号不能重复,要保持唯一。原本以为来个时间戳,精确到毫秒应该不错了。后来觉得是错了,测试环境下很多一
纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 加微信:bysocket01
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want.文章Points:1、介绍RESTful架构风格2、Spring配置CXF3、三层初设计,实现WebService接口层4、撰写HTTPClient 客户
Writer :BYSocket(泥沙砖瓦浆木匠)什么是回调?今天傻傻地截了张图问了下,然后被陈大牛回答道“就一个回调…”。此时千万个草泥马飞奔而过(逃哈哈,看着源码,享受着这种回调在代码上的作用,真是美哉。不妨总结总结。一、什么是回调回调,回调。要先有调用,才有调用者和被调用者之间的回调。所以在百
Writer :BYSocket(泥沙砖瓦浆木匠)一、什么大小端?大小端在计算机业界,Endian表示数据在存储器中的存放顺序。百度百科如下叙述之:大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加
What is a programming language? Before introducing compilation and decompilation, let&#39;s briefly introduce the Programming Language. Programming la
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket泥瓦匠喜欢Java,文章总是扯扯Java。 I/O 基础,就是二进制,也就是Bit。一、Bit与二进制什么是Bit(位)呢?位是CPU
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocket一、前言 泥瓦匠最近被项目搞的天昏地暗。发现有些要给自己一些目标,关于技术的目标:专注很重要。专注Java 基础 + H5(学习) 其他操作系统,算法,数据结构当成课外书博览。有时候,就是那样你越是专注方面越