ServiceNow JavaScript performance check based on different strategies using ES5, ES12, GlideRecord and GlideQuery

ServiceNow JavaScript performance check based on different strategies using ES5, ES12, GlideRecord and GlideQuery

My role as a developer in the projects has been reduced significantly by today, but I was looking forward to the day, when a newer JavaScript version than ES5 (ECMAScript 5) will be available in ServiceNow. So finally in the Tokyo Release it happened. In case of scoped applications, the ES12 (ECMAScript 2021) version of Javascript is available as well. Finally, I had the chance to execute some test cases, which had been on my mind for long time to check the performance of the system, using different combination of GlideRecord, GlideQuery ES5 and ES12.

Test Case

In case of reference qualifier definitions I'm always thinking about how the filter condition can be implemented as simple as possible. One of the advantages of ES12 syntax is, that it is possible to write compact codes. I was curious of the performance impact of data filtering with the new version of JS.

I have selected a somewhat complex case for testing. There is a User reference field which is called Special Contact. The users, which can be selected are based on the following filter criteria:

Need to collect all users who are subscribed for the selected CI and the title of the user matches the following pattern:

Junior or Senior or Expert developer in level 1 or 2 (For example: Junior developer 2)?

I prepared this setup by selecting some users randomly from the sys_user table and modifying their Title property. It can be seen on the image below that there are two users where the condition is met:

No alt text provided for this image

I have connected these users to a CI with a "subscribed by type" relationship:

No alt text provided for this image

I have also added the new field to a form of Task extended table and defined the reference qualifier as a function call from a script include.

No alt text provided for this image
No alt text provided for this image

The Code

I tried to keep the code as simple as possible and used only generic objects. Let’s see how the three scripts look like:

The first function contains the “classic way” of how data can be gathered:

getSubscibedUsersV1: function(ciSysId) {

		var usrList = [];		

		var suGr = new GlideRecordSecure("cmdb_subscriber");
		suGr.addQuery("item", "=", ciSysId);
		suGr.query();
		while (suGr.next()) {

			if (suGr.user.title && suGr.user.title.match(/^(Junior|Senior) Developer [1,2]$/g)) {
				usrList.push(suGr.getValue("user"));
			}
		}

		return usrList.join(",");		
	}        

In the second use case, I used the GlideQuery and some Javascript capabilities like map and filter, in order to gather the corresponding data only:

getSubscibedUsersV2: function(ciSysId) {

		return new global.GlideQuery('cmdb_subscriber')
			.withAcls()
			.where("item", "=", ciSysId)
			.select("user.title", "user.sys_id")
			.filter(function(item) {
			return item.user.title && item.user.title.match(/^(Junior|Senior) Developer [1,2]$/g);
		})
			.toArray(100)
			.map(function(k){ return k.user.sys_id; })
			.join(",");
	}        

The difference between the 2nd and 3rd case is minuscule. I started using some new JS syntax, for example Lambda expressions:

getSubscibedUsersV3: function(ciSysId) {

		return new global.GlideQuery('cmdb_subscriber')
			.withAcls()
			.where("item", "=", ciSysId)
			.select("user.title", "user.sys_id")
			.filter(item => item.user.title && item.user.title.match(/^(Junior|Senior) Developer [1,2]$/g))
			.toArray(100)
			.map(item => item.user.sys_id)
			.join(',');
	}        

In the second and third use case I assumed that the number of records cannot be greater than 100, otherwise the toArray function cannot be used.

Important! If you select the ES5 as Javascript mode in the application, the ES6+ syntax cannot be used.

Recommendation: Use the GlideRecordSecure or GlideQuery(...).withAcls() whenever is possible instead of bypassing the security rules.

Executing the test cases

Everything was ready to start testing. The test case was very simple I just selected a CI and opened the User selector window:

No alt text provided for this image

I have used a demo ServiceNow instance and the measurement was defined in the functions based on a simple execution time calculation. I selected 3 CIs and setup different amount of relations:

  • CI 1: amount of users in the Subscribed by relation: 10
  • CI 2: amount of users in the Subscribed by relation: 100
  • CI 3: amount of users in the Subscribed by relation: 600

I used the following combinations of script execution for testing the performance:

  • getSubscibedUsersV1 and getSubscibedUsersV2 functions with JS ES5 and filtering data from the three different amount of set
  • getSubscibedUsersV3 function with both JS versions and filtering data from the three different amount of set

I have done several tests and repeated the actions multiple times, and used average values based on the results. The measured results can be observed on the image below:

No alt text provided for this image

Conclusion

Honestly, I’m a bit surprised. I knew that the performance of GlideQuery is a bit worse than the GlideRecord, but I thought ES12 increases the effectiveness of JS executions, but in this case it didn't. The picture shows that the run times are very close to each other, which means that there is no significant difference between the cases.

There are a lot of great things / possibilities available in the new version of Javascript, but I think, the added value of this case is that using GlideQuery and some ES12 features provides the possibility to write easier / shorter / more compact code, which can help reduce the lead time of implementation, but it won't be faster.

It is up to you to decide if you want to keep on using the classic way of coding, or start something new (is it really new? ??), like Lambda expressions.

#servicenow #javascript #filtering #performance

Mathias Hendrich

ServiceNow Certified Master Architect

2 年

Attila Varga, great article for #ServiceNow developers that wants quality! Thank you for sharing and your effort to test and document it!

Daniel Gibbard

ServiceNow Certified Master Architect

2 年

Nice to see some data on this. I think the reason you see little difference in performance is that the JS engine is still Rhino (ES5) and any ES6+ code is transpiled to ES5. As you said, usage is purely a developer preference at the moment.

Tamás Csépányi, PMP?, PMI-ACP?

Simplify Agile for Complex Organizations | Lean-Agile & Project management expert | Lecturer | Helping career changers

2 年

Wow, great post Attila ;)

Zsofia Varadi

Senior Business Analyst | Project Manager | Consultant | ServiceNow | 5xCIS certified I ITSM | HRSD | PPM | CSM | FSM | Digital Solutions | ITIL 4 | Agile | PRINCE2

2 年

Great read, thanks Attila Varga!

要查看或添加评论,请登录

Attila Varga的更多文章

社区洞察

其他会员也浏览了