Tips & Tricks: Nested Loop Performance Demonstration in ServiceNow

Tips & Tricks: Nested Loop Performance Demonstration in ServiceNow

 

Developers often come across scenarios where they need to iterate over collections of data. While loops are fundamental constructs in programming, nested loops can significantly impact performance. In this blog post, we’ll look at the performance difference in time when using nested loops versus separate loops. 

 

This is our second blog post of the Tips & Tricks series, and it was created in collaboration with Appmore’s incredible ServiceNow consultants Niko Sääski and Sakari Kaikkonen. A big thanks to Niko and Sakari for their knowledge on this one!

 

What Are Nested Loops?

 

Nested loops occur when one loop is inside another loop. This results in the inner loop being executed multiple times for every iteration of the outer loop. 

 

 

The Big O Notation and Loops

 

In computer science, the Big O notation is used to describe the performance of algorithms in terms of their growth rate relative to the input size. When nested loops are involved, the time complexity often grows exponentially.

 

To address this issue, developers often choose separate loops. In this approach, data is processed independently, reducing the number of iterations required for comparisons and resulting in a linear time complexity of O(n), where n represents the size of the dataset.

 

For instance, if you have two nested loops, each iterating over n elements, the total number of iterations becomes O(n^2). As n increases, the execution time grows quadratically.

 

 

 

What Does This Have To Do With ServiceNow Development?

 

In ServiceNow developers sometimes encounter situations where data from one table needs to be compared or associated with data from another table. Let’s make up a scenario where we want to identify users who are not callers of incidents in ServiceNow. To tie this to our topic, we’ll use two approaches described below.

 

Nested GR (GlideRecord): This approach involves nested queries, where we first retrieve all users from the “sys_user” table and then, for each user, query the “incident” table to check if they are not the caller in any incident.

 

Separate GR: Here we use separate queries to retrieve users and incidents. We store the results of both queries into separate objects. Then compare the results to identify users who are not callers.

 

There are other ways of solving this, but the aim of this scenario is to be repeatable in Out-of-the-Box (OOB) instances and to underline the performance differences.

 

 

Performance Comparison

 

In our test scenario we have 734 “sys_user” records and 555 “incident” records. Both approaches are scripted and executed 25 times each. Here’s the highlight of the results:

 

Nested GR: Average execution time per iteration: 1663.6 ms (milliseconds).

 

Separate GR: Average execution time per iteration: 155.48 ms.

 

The scripts used and the detailed results are at the end of the blog post.

 

 

Conclusion

 

The results show in actual numbers what the performance difference using nested versus separate loops can be. It’s not always so easy to understand the difference when talking about it in more abstract ways like O(n) versus O(n^2). Considering strategies to minimize unnecessary iterations, such as separate queries and efficient data structures, enhances application responsiveness and scalability.

 

While this article focused on time complexity, it’s also crucial to consider space complexity. Optimizing both complexities becomes increasingly vital for maintaining efficient and scalable ServiceNow applications as data volumes grow.

 

P.S. If we only need to pick “sys_id” values of the records, we can squeeze out even more time saves by using GlideAggregate. More on that in a future post. 

Picture 1. Running the test. The numbers in this are different since it’s taken at a later time and amounts of records was not the same.

picture of running the test

 

Results and Scripts Used

 

[Time measure, number of iterations 25]

 

Nested GR

Array with all iteration times: 1831,1619,1629,1730,1934,1720,1486,1479, 1549,1526,1620,1477,1566,1562,1487,1531,2435,1555,1402,1661,1320,1509,2368,1956,1638
Execution time of all iterations: 41590ms.
Average execution time of one iteration: 1663.6ms.
MAX execution time of iteration: 2435ms.
MIN execution time of iteration: 1320ms.
——————————————————————————–
Separate GR

Array with all iteration times: 150,135,154,159,138,156,166,142,151,153,171,114,135,164,189,166,202,149,132,179,162,168,170,152,130
Execution time of all iterations: 3887ms.
Average execution time of one iteration: 155.48ms.
MAX execution time of iteration: 202ms.
MIN execution time of iteration: 114ms.

Picture 2. Nested GR

Nested gr

Picture 2. Seperate GR

Seperate GR
DE