jsPerf.app is an online JavaScript performance benchmark test runner & jsperf.com mirror. It is a complete rewrite in homage to the once excellent jsperf.com now with hopefully a more modern & maintainable codebase.
jsperf.com URLs are mirrored at the same path, e.g:
https://jsperf.com/negative-modulo/2
Can be accessed at:
https://jsperf.app/negative-modulo/2
Compare performances when evaluating expressions using the above functions
<script scr="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/sval@0.6.3/dist/sval.min.js"></script>
const TEMPLATE_OBJECT = {
id: "household_record_page",
name: null,
isGlobal: null,
entityType: "_s_Household",
grants: [],
order: null,
roleIds: null,
buttons: null,
createdTime: 1705496417454,
modifiedTime: 1705496417453,
children: ["root"],
allComponents: {
"0": {
langVsTranslatedFieldValues: null,
id: "0",
templateId: "@sprinklr/widget/Layout",
persistedId: null,
name: null,
order: 0,
children: ["1", "2", "3"],
props: {
pageTemplate: "STICKY_HEADER_TWO_COLS_PINNED_LEFT",
colGap: 20,
leftColSpan: 13,
rightColSpan: 7,
className: "spr-ui-05 pr-4",
},
context: null,
uiEvents: null,
formLayout: null,
tableLayout: null,
buttons: null,
valueSource: null,
evaluatedValue: null,
translations: null,
},
"1": {
langVsTranslatedFieldValues: null,
id: "1",
templateId: "@sprinklr/widget/Layout",
persistedId: null,
name: "ONE",
order: 0,
children: ["1a", "1b"],
props: {
pageTemplate: "ONE_REGION",
},
context: null,
uiEvents: null,
formLayout: null,
tableLayout: null,
buttons: null,
valueSource: null,
evaluatedValue: null,
translations: null,
},
root: {
langVsTranslatedFieldValues: null,
id: "root",
templateId: "@sprinklr/widget/Layout",
persistedId: null,
name: null,
order: 0,
children: ["0"],
props: {
pageTemplate: "ONE_REGION",
stickyHeaderPresent: true,
},
context: null,
uiEvents: null,
formLayout: null,
tableLayout: null,
buttons: null,
valueSource: null,
evaluatedValue: null,
translations: null,
},
"1a": {
langVsTranslatedFieldValues: null,
id: "1a",
templateId: "@sprinklr/widget/Layout",
persistedId: null,
name: null,
order: 0,
children: ["1a1"],
props: {
pageTemplate: "ONE_REGION",
className: "ml-4 pr-4",
},
context: null,
uiEvents: null,
formLayout: null,
tableLayout: null,
buttons: null,
valueSource: null,
evaluatedValue: null,
translations: null,
},
"1a1": {
langVsTranslatedFieldValues: null,
id: "1a1",
templateId: "@sprinklr/widget/EntityControls",
persistedId: null,
name: "ONE",
order: 0,
children: null,
props: {
entityType: "_s_Household",
upfrontActionsCount: 4,
},
context: null,
uiEvents: null,
formLayout: null,
tableLayout: null,
buttons: [
{
langVsTranslatedFieldValues: null,
id: "OPEN_MEETING_RECORD_FORM",
templateId: "@sprinklr/action/OpenRecordForm",
persistedId: null,
label: "Schedule Meeting",
detail: null,
icon: "meeting",
entityType: "_s_Meeting",
action: null,
props: {
type: "ICON_TEXT_BUTTON",
recordFormVariant: "THIRD_PANE",
recordFormLayoutId: "finance_meeting",
title: "Schedule Meeting",
context: {
linkedEntityId: "_s_Household-:-${currentRecord?.entityId}",
attendees: "${currentRecord?.attendees}",
},
},
translations: null,
children: null,
visibility: null,
disabilityFilter: null,
payload: null,
},
{
langVsTranslatedFieldValues: null,
id: "OPEN_INTERACTION_RECORD_FORM",
templateId: "@sprinklr/action/OpenRecordForm",
persistedId: null,
label: "Log Interaction",
detail: null,
icon: "interaction",
entityType: "_s_Interaction",
action: null,
props: {
type: "ICON_TEXT_BUTTON",
recordFormVariant: "THIRD_PANE",
recordFormLayoutId: "finance_interaction",
title: "Log Interaction",
messageOnSuccess: "Successfully created the interaction",
context: {
linkedEntityId: "_s_Household-:-${currentRecord?.entityId}",
attendees: [
{
linkedEntityId:
"_s_Customer-:-${currentRecord?.values?._c_headCustomerId}",
},
],
relatedTo: [
"_s_Customer-:-${currentRecord?.values?._c_headCustomerId}",
],
},
},
translations: null,
children: null,
visibility: null,
disabilityFilter: null,
payload: null,
},
{
langVsTranslatedFieldValues: null,
id: "OPEN_SUPERVISOR_REVIEW_RECORD_FORM",
templateId: "@sprinklr/action/OpenRecordForm",
persistedId: null,
label: "Add Review",
detail: null,
icon: "interaction",
entityType: "_c_reviewforsupervisor",
action: null,
props: {
type: "ICON_TEXT_BUTTON",
recordFormVariant: "THIRD_PANE",
recordFormLayoutId: "household_review_form",
title: "Add Review",
messageOnSuccess: "Successfully created the review",
context: {
_c_wealthgroupidforreview: "${currentRecord?.entityId}",
name: "${currentRecord?.name} Review",
_c_wealthgroupheadforreview:
"${currentRecord?.values?._c_headCustomerId}",
_c_rm_user:
"${currentRecord?.shares?.jointGrants?.find(e => e?.endsWith('/WRM') && e?.startsWith('USER/'))?.split('/')?.[1]}",
},
},
translations: null,
children: null,
visibility: {
filterType: "AND",
filters: [],
filters_dummy: [
{
filterType: "EXPRESSION",
field:
"${currentRecord?.shares?.jointGrants?.find(e => e?.endsWith('/WRM') && e?.startsWith('USER/'))?.split('/')?.[1] !== currentUser.userId}",
},
{
filterType: "EXPRESSION",
field:
"${currentRecord?.shares?.jointGrants?.find(e => e?.endsWith('/IA') && e?.startsWith('USER/'))?.split('/')?.[1] !== currentUser.userId}",
},
{
filterType: "EXPRESSION",
field:
"${currentRecord?.shares?.jointGrants?.find(e => e?.endsWith('/SRM') && e?.startsWith('USER/'))?.split('/')?.[1] !== currentUser.userId}",
},
],
},
disabilityFilter: null,
payload: null,
},
{
langVsTranslatedFieldValues: null,
id: "INITIATE_WORKFLOW",
templateId: "@sprinklr/action/GuidedAction",
persistedId: null,
label: "Initiate Workflow",
detail: null,
icon: "workflow",
entityType: "_s_Household",
action: "254937",
props: {
type: "ICON_TEXT_BUTTON",
},
translations: null,
children: null,
visibility: null,
disabilityFilter: null,
payload: null,
},
],
valueSource: null,
evaluatedValue: null,
translations: null,
},
},
};
const CONTEXT = {
currentRecord: {
attendees: [{ id: "1", name: "Nik" }],
values: {
_c_headCustomerId: "123",
},
entityId: "123",
name: "Nikunj",
shares: { jointGrants: ["USER/123/WRM"] },
},
currentUser: {
userId: 123,
},
};
const REGEX_FOR_SINGLE_OR_MULTIPLE_EXP_IN_STRING = /\${([^}]*)}/g;
const REGEX_FOR_SINGLE_EXP_IN_STRING = /^\${.*}$/;
function evalTemplateObject(templateObject, context){
console.log('evalTemplateObject',templateObject,context);
//don't want to allow these things to be accessible while running eval
const window = undefined;
const fetch = undefined;
const document = undefined;
const setTimeout = undefined;
const setInterval = undefined;
const { currentRecord, currentUser, iteratorObject, router, parentRecord, resources, __customContext__ } = context;
if (_.isEmpty(templateObject)) {
return templateObject;
}
const recursivelyIterate = iterator => {
//base case
if (!_.isObject(iterator)) {
if (typeof iterator === 'string') {
//for exp like ${currentRecord.name}
if (REGEX_FOR_SINGLE_EXP_IN_STRING.test(iterator)) {
const parsedValue = eval(iterator.substring(2, iterator.length - 1));
return parsedValue;
}
//for exp like 'Hi ${currentRecord.name} ${currentRecord.surname}'
return iterator.replace(REGEX_FOR_SINGLE_OR_MULTIPLE_EXP_IN_STRING, (match, group) => {
const parsedValue = eval(`${group}`);
return parsedValue;
});
}
return iterator;
}
//if iterator is array
if (Array.isArray(iterator)) {
return iterator.map(value => recursivelyIterate(value));
}
//if iterator is object
return _.reduce(
iterator,
(acc, value, key) => {
acc[key] = recursivelyIterate(value);
return acc;
},
{}
);
};
try {
return recursivelyIterate(templateObject);
} catch (error) {
return templateObject;
}
};
function lodashParseObject(
templateObject,
context
){
console.log('lodashTemplateObject',templateObject,context,_);
if (_.isEmpty(templateObject)) {
return templateObject;
}
try {
return JSON.parse(_.template(JSON.stringify(templateObject))(context)) ??{};
} catch (e) {
return templateObject;
}
};
const svalInterpreter = new Sval({
ecmaVer: 11,
sourceType: "script",
sandBox: true,
});
function svalParseObject(templateObject, context) {
console.log('svalParseObject',templateObject,context,);
svalInterpreter.import({
currentRecord: context.currentRecord,
currentUser: context.currentUser,
iteratorObject: context.iteratorObject,
router: context.router,
parentRecord: context.parentRecord,
resources: context.resources,
__customContext__: context.__customContext__,
});
if (_.isEmpty(templateObject)) {
return templateObject;
}
const recursivelyIterate = (iterator) => {
//base case
if (!_.isObject(iterator)) {
if (typeof iterator === "string") {
//for exp like ${currentRecord.name}
if (REGEX_FOR_SINGLE_EXP_IN_STRING.test(iterator)) {
svalInterpreter.run(
`exports.__output__ = ${iterator.substring(2, iterator.length - 1)}`
);
return svalInterpreter.exports.__output__;
}
//for exp like 'Hi ${currentRecord.name} ${currentRecord.surname}'
return iterator.replace(
REGEX_FOR_SINGLE_OR_MULTIPLE_EXP_IN_STRING,
(match, group) => {
svalInterpreter.run(`exports.__output__ = ${group}`);
return svalInterpreter.exports.__output__;
}
);
}
return iterator;
}
//if iterator is array
if (Array.isArray(iterator)) {
return iterator.map((value) => recursivelyIterate(value));
}
//if iterator is object
return _.reduce(
iterator,
(acc, value, key) => {
acc[key] = recursivelyIterate(value);
return acc;
},
{}
);
};
try {
return recursivelyIterate(templateObject);
} catch (error) {
return templateObject;
}
}
Ready to run.
Test | Ops/sec | |
---|---|---|
eval |
| ready |
sval |
| ready |
lodash/_template |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.