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

JavaScript 引擎性能比较之一SpiderMonkey[通俗易懂]1.下载https://people.mozilla.org/~sstangl/mozjs-31.2.0.rc0.tar.bz2bunzip2mozjs-31.2.0.rc0.tar.bz2tarxvfmozjs-31.2.0.rc0.tar2.构建https://developer.mozilla.org/en-US/docs/Mozilla/Projects/

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新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账号...

(0)


相关推荐

  • 安装了anaconda 还需要单独安装pycharm吗_ugnx10安装教程

    安装了anaconda 还需要单独安装pycharm吗_ugnx10安装教程python环境配置步骤一:Pycharm和Anaconda的安装作者介绍1.复制pycharm和Aanconda的安装包2.安装pycharm3.安装Anaconda作者介绍张伟伟,男,西安工程大学电子信息学院,2019级硕士研究生,张宏伟人工智能课题组。研究方向:机器视觉与人工智能。电子邮件:2430290933@qq.com课题组CSDN官方账号,欢迎一键三连:https://blog.csdn.net/m0_37758063/article/details/113527955?s

  • 开放API接口_软件接口开放

    开放API接口_软件接口开放前言在开发测试阶段,或者是在写Demo的时候,难免会用到一些测试数据,有时苦于没有可用的接口,需要自己动手去写,但是这样大大降低了效率,前期我也找了一些开放的接口,这篇文章整理一下,以下接口完全免费,不用注册,返回格式全是JSON,所有接口均可无限制使用,有需要的小伙伴可以进来看看。(ps:所有数据来源于网络,如有侵权,请作者联系删除)图片类接口美女图片:https://w…

  • Python_Python安装包下载[通俗易懂]

    Python_Python安装包下载[通俗易懂]PythonImagingLibrary(PIL):http://www.pythonware.com/products/pil/pywin32:http://sourceforge.net/projects/pywin32/files/pywin32/Build%20217/

    2022年10月29日
  • Linux安装NVIDIA显卡驱动的正确姿势

    Linux安装NVIDIA显卡驱动的正确姿势什么是nouveau驱动?检测NVIDIA驱动是否成功安装集显与独显的切换使用标准仓库进行自动化安装使用PPA仓库进行自动化安装使用官方的NVIDIA驱动进行手动安装Linux安装NVIDIA显卡驱动的正确姿势可能想玩Linux系统的童鞋,往往死在安装NVIDIA显卡驱动上,所以这篇文章帮助大家以正常的方式安装NVI…

  • idea 2021.5 激活码[在线序列号]

    idea 2021.5 激活码[在线序列号],https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • 大数据与云计算物联网的关系文献_云计算的概念

    大数据与云计算物联网的关系文献_云计算的概念云计算、大数据和物联网代表了IT领域最新的技术发展趋势,三者既有区别又有联系。云计算最初主要包含了两类含义:一类是以谷歌的GFS和MapReduce为代表的大规模分布式并行计算技术;另一类是以亚马逊的虚拟机和对象存储为代表的“按需租用”的商业模式。但是,随着大数据概念的提出,云计算中的分布式计算技术开始更多地被列入大数据技术,而人们提到云计算时,更多指的是底层基础IT资源的整合优化…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号