Performance awareness is an essential skill of a NetSuite Developer, one that can draw a line between a good and bad script. Achieving a business requirement is only one part of the job but without proper performance consideration, it’s not enough. In this article, I compare two common approaches for finding the sublist line that contains a particular value.
Introduction
As developers, we often need to find a sublist line with a specific value. There are two simple approaches frequently used to do this: Record.findSublistLineWithValue
native SuiteScript method or looping through all the sublist lines and comparing the values. While I was reviewing the code of other developers in the past, I noticed several times that they didn’t know about the existence of the Record.findSublistLineWithValue
method and used the other approach instead. So I was wondering, is the SuiteScript method just a fancy wrapper that does the same, or is there an actual performance difference, and if so, how large is it?
The first thing that would pop into our heads when we’re talking about performance in regards to NetSuite development is the SuiteScript Governance and limits. Luckily, none of these approaches consumes any usage units. So, I decided to conduct an experiment and I am pleased to share my findings with you.
Test Setup
The test record was a Sales Order (SO) with 500 item lines in a test drive (TSTDRV) account. Except for the testing script, there was no other custom script or workflow deployed on the SO record. The goal was to find one item line with a specific value, which was actually only present on the last, i.e., 500th line.
I conducted the experiment for client-side using a client script running the line search in the pageInit
entry point. It was executed in two Chrome incognito tabs with the SO with 500 lines open in edit mode and with no active Chrome extensions. The client script reloaded the page after it found the line, doing this 100 times for each tab.
I subsequently repeated the experiment using a scheduled script to see how the approaches perform server-side and to eliminate browser-specific effects. The script re-scheduled itself after each run.
The simple test script is shown below:
Results
Several questions emerged during the experiment that led me to try a few variations of the code. Here is what I tried to get answers for:
- What is faster? Looping or
Record.findSublistLineWithValue?
- Is there a speed difference between SuiteScript 2.0 and 2.1?
- Is the performance dependent on the field where I’m looking for the value? I tried to look in lineuniquekey, item, and quantity.
- Is there a speed difference between standard (deferred) and dynamic mode (only applicable for server-side in the experiment)?
Below are summarized results I got from 100 attempts for each variation (200 for client-side as I tested on 2 browser tabs). The table header says what field we searched for the value in, what kind of approach (‘loop’ or ‘find’), and variation (SuiteScript version and static/dynamic mode) was used. The reported execution times are in seconds. The best average result is highlighted in green color.
Client Side
lineuniquekey | loop|2.0 | loop|2.1 | find|2.0 | find|2.1 |
---|---|---|---|---|
Avg | 0.009565 | 0.00979 | 0.003015 | 0.003435 |
Avg performance | -3.17x | -3.25x | 1x | -1.14x |
Median | 0.009 | 0.009 | 0.002 | 0.002 |
Min | 0.008 | 0.008 | 0.002 | 0.002 |
Max | 0.016 | 0.027 | 0.01 | 0.008 |
item | loop|2.0 | loop|2.1 | find|2.0 | find|2.1 |
---|---|---|---|---|
Avg | 0.0098 | 0.00957 | 0.004545 | 0.002125 |
Avg performance | -4.61x | -4.5x | -2.14x | 1x |
Median | 0.01 | 0.009 | 0.003 | 0.002 |
Min | 0.009 | 0.009 | 0.002 | 0.002 |
Max | 0.016 | 0.016 | 0.115 | 0.004 |
quantity | loop|2.0 | loop|2.1 | find|2.0 | find|2.1 |
---|---|---|---|---|
Avg | 0.008515 | 0.00869 | 0.00427 | 0.002145 |
Avg performance | -3.97x | -4.05x | -1.99x | 1x |
Median | 0.008 | 0.008 | 0.003 | 0.002 |
Min | 0.007 | 0.007 | 0.002 | 0.002 |
Max | 0.016 | 0.016 | 0.014 | 0.004 |
The answer to the first question, which approach is faster is pretty clear, it’s the SuiteScript Record.findSublistLineWithValue
method. What is faster, SuiteScript 2.0 or 2.1? It seems there is no real difference for looping approach but findSublistLineWithValue
performs better in SuiteScript 2.1 except for the lineuniquekey search where SuiteScript 2.0 marginally outperforms 2.1. Perhaps the takeaway here is to use SuiteScript 2.1 whenever possible as it gives better performance in general.
Is there a difference based on the field? Lineuniquekey seems to be slowest but the difference does not appear to be significant.
On client-side, NetSuite's Record.findSublistLineWithValue could be up to 4.5 times faster than simply looping through all sublist lines in search of the target value. Click To TweetThe client script did the searching on the actual record opened in the browser (scriptContext.currentRecord
). So, I also decided to try searching on loaded record (record.load
) instead, this time, only for lineuniquekey. The results were quite surprising. From the table below we can see that findSublistLineWithValue
performs significantly faster on loaded record!
lineuniquekey | loop|2.0|loaded | loop|2.1|loaded | find|2.0|loaded | find|2.1|loaded |
---|---|---|---|---|
Avg | 0.5603 | 0.512775 | 0.00231 | 0.00149 |
Avg performance | -376.04x | -344.14x | -1.55x | 1x |
Median | 0.4735 | 0.4845 | 0.002 | 0.001 |
Min | 0.418 | 0.376 | 0.001 | 0.001 |
Max | 1.144 | 1.019 | 0.007 | 0.002 |
Server Side
S = record loaded in standard mode, D = record loaded in dynamic mode
line unique key | loop|2.0|S | loop|2.0|D | loop|2.1|S | loop|2.1|D | find|2.0|S | find|2.0|D | find|2.1|S | find|2.1|D |
---|---|---|---|---|---|---|---|---|
Avg | 0.07057 | 0.07777 | 0.07532 | 0.08347 | 0.01916 | 0.01863 | 0.01766 | 0.02054 |
Avg performance | -4.0x | -4.4x | -4.27x | -4.73x | -1.08x | -1.05x | 1x | -1.16x |
Median | 0.066 | 0.072 | 0.073 | 0.08 | 0.017 | 0.017 | 0.017 | 0.018 |
Min | 0.049 | 0.053 | 0.052 | 0.063 | 0.013 | 0.014 | 0.013 | 0.014 |
Max | 0.182 | 0.155 | 0.142 | 0.161 | 0.135 | 0.036 | 0.037 | 0.079 |
item | loop|2.0|S | loop|2.0|D | loop|2.1|S | loop|2.1|D | find|2.0|S | find|2.0|D | find|2.1|S | find|2.1|D |
---|---|---|---|---|---|---|---|---|
Avg | 0.06836 | 0.07859 | 0.08093 | 0.08117 | 0.01766 | 0.01808 | 0.01739 | 0.0221 |
Avg Performance | -3.93x | -4.52x | -4.65x | -4.67x | -1.02x | -1.04x | 1x | -1.27x |
Median | 0.065 | 0.073 | 0.0715 | 0.076 | 0.017 | 0.017 | 0.017 | 0.018 |
Min | 0.048 | 0.056 | 0.05 | 0.056 | 0.012 | 0.013 | 0.013 | 0.013 |
Max | 0.114 | 0.143 | 0.539 | 0.232 | 0.028 | 0.04 | 0.033 | 0.219 |
quantity | loop|2.0|S | loop|2.0|D | loop|2.1|S | loop|2.1|D | find|2.0|S | find|2.0|D | find|2.1|S | find|2.1|D |
---|---|---|---|---|---|---|---|---|
Avg | 0.07765 | 0.09263 | 0.08647 | 0.10014 | 0.01794 | 0.01802 | 0.0179 | 0.01789 |
Avg Performance | -4.34x | -5.18x | -4.83x | -5.60x | -1.0028x | -1.0073x | -1.0006x | 1x |
Median | 0.073 | 0.084 | 0.085 | 0.0945 | 0.017 | 0.017 | 0.017 | 0.017 |
Min | 0.053 | 0.067 | 0.062 | 0.073 | 0.013 | 0.013 | 0.013 | 0.015 |
Max | 0.137 | 0.463 | 0.171 | 0.208 | 0.029 | 0.028 | 0.034 | 0.034 |
The winner is again without any doubts the findSublistLineWithValue method. SuiteScript 2.0 seems to be a bit faster for looping approach but also in this case we cannot answer the question unambiguously. Is there a difference between the fields – no, not really.
On server-side, NetSuite's Record.findSublistLineWithValue also significantly outperforms the looping approach by more than 5 times in some cases. Click To TweetOne extra question that I did not test in client side was whether there is any significant speed difference between standard and dynamic record mode. As can be seen from the above results, dynamic mode appears to be slightly slower in most of the cases, especially for looping approach. This is consistent with expectations as dynamic mode mimics the UI and thus, typically introduces some overhead.
One last quick test I did was to compare the performance of two approaches when searching for multiple values. The test was performed using SuiteScript 2.1 and record loaded in standard mode, searching for lineuniquekey present on 200th, 400th and 500th lines.
lineuniquekey | loop|2.1|loaded|multiple | find|2.1|loaded|multiple |
---|---|---|
Avg | 0.07983 | 0.04351 |
Avg Performance | -1.83 | 1x |
Median | 0.071 | 0.039 |
Min | 0.049 | 0.03 |
Max | 0.17 | 0.26 |
Conclusion
Based on the result of this experiment, I believe it is safe to state that Record.findSublistLineWithValue
is faster than looping and should be used if we need to find a unique (or the first instance of a) value in a sublist. SuiteScript version, record mode, and the actual field being searched for seem to be insignificant factors in determining the performance. There are other questions that one could further explore, for example:
- Do the results change when run using a sublist of a non-transaction record type e.g. a custom record sublist?
- Does it matter whether the field being searched for is a native field or a custom field?
The interested reader is invited to investigate further and share their findings.
NetSuite Insights is on a mission to raise the standards around NetSuite practices, one insight at a time. If that resonates with you, check out how you can become an author/collaborator here.
Also, subscribe to our no-nonsense email list to get these insights delivered to your inbox as soon as they’re published. Sometimes, ignorance is a choice. Choose wisely!
Great article! We would love to see more like these! It’s really helpful to quantify the performance of different aspects in the SuiteScript API.
We agree, Ben, that we need more of these kinds of performance experiments in the NetSuite space. Some of the reluctance might be the result of NetSuite’s ToS which generally frown upon benchmarking.