Hi at all,
I write this post to talking about the performace of an enviroment and how write a good code for sailpoint.
Generally the performance of a Sailpoint environment depends on 3 factors (except hardware):
- Database
- JVM
- Coding
About Database maintenance and performance, I already talked in a other post: Databese
JVM
About JVM, we can change the parameters of it. On this page JVM, Sailpoint recomends some configuration of parameter for different size of machine, but usually a customer want more performance or we work on different configurations from the recommended servers.
The most common configuration is 2 UI, 2 Task and 1 DB server. The logic requires that UIs need less resource respect of Task servers but it’s not always like that.
Before decide, how build the parameters, you have to do a deep analisys and make some prevision about the load and usage.
The most important parameter for JVM, are:
-Xms
: min memory reserved for JVM-Xmx
: max memory reserved for JVM-XX:MinHeapFreeRatio
: min free memory after garbage collection op.-XX:MaxHeapFreeRatio
: max free memory after garbage collection op.-XX:+UseG1GC
: enable Garbage Collector G1-XX:+UseZGC
: enable Garbage Collector Z (for Java 11 or more)-XX:MaxGCPauseMillis
: min time for GC operation pause
Xms & Xmx are very important, like general rule you can configure the Xms to 10% of total memory(RAM) and Xmx to 80%(but you can improve until 90-95% with high RAM size and if you use windows or linux).
MinHeapFreeRatio & MaxHeapFreeRatio need a deep analisys before change them. Usually the defoult values are 40% and 70% but you can change for memery optimization. Be carefull because the consequences can be disastrous. Those paramaters manage the size of the hipe, so frequent heap changes can degrade performance.
I recommend always activating the Garbage Collector because helps to maintain free and optimize the memory: G1 for Java 8 and Z for Java 11 or more. For one more boost you can use XX:+UseParallelGC
for using parallelism of Garbace Collector, better on huge task servers.
MaxGCPauseMillis is used for manage the pauses for Garbage Collector. SP suggest a value of 200 for large server, but you can set 100 or 150 for a little improve.
Coding
Offen on the project or in this forum too, I can see no-optimized code or very bad code.
Usually when we write code, we test on a little subset data or in a dev enviroment very different of production. So, this entails our code have different performace in different enviroment or situation.
When we write a rule, we must think on global situation.
For example, a medium enviroment can have 50k-100k identies, 200k of entitlements, 50-100 applications ecc…
This means that rule/scripts can be execute thousands of times every day(or hour). So, a rule needs few resources but if this rule needs 1 sec to be performed, a process on 10k identites needs more than 2 hours to be performed.
And usually, we have some rule for aggregation or refresh or provisioning for each identity/account.
There are some suggest to improve the execution time of each rule:
Import & Variable
Import only the library that you need.
For example, I write this simple rule :
import sailpoint.object.Configuration;
import sailpoint.tools.Util;
Runtime runtime = Runtime.getRuntime();
long memoryBefore = runtime.totalMemory() - runtime.freeMemory();
long startTime = System.currentTimeMillis();
List conf = context.getObjects(Configuration.class);
long memoryAfter = runtime.totalMemory() - runtime.freeMemory();
long endTime = System.currentTimeMillis();
System.out.println("Memory usage: " + (memoryAfter - memoryBefore)/1024 + " Kb");
System.out.println("Time: " + (endTime - startTime) + " ms");
this version need this time and memory:
with those import:
import sailpoint.object.*;
import sailpoint.tools.*;
the performace is little different:
this happens because the programma needs load more class and code, and needs more memory and time.
Also, use the minimun number of variable where it is possible; for example:
String appName = "AppName";
Application app = context.getObjectByName(Application.class, appName);
could be converted in:
Application app = context.getObjectByName(Application.class, "AppName");
Little considaration: remove a variable doesn’t change much, but 5-10 variables in 50-100 rules yes.
Search instead of getObjects
If you need to search a list of object, better using Search function instead fo getObjects. Is better because search method returns an iterator, representing a pointer in the database and not a list of object.
This method uses and needs less memory respect of getObjects.
Also, is a good practice use context.decache(object) when in rule you dont need anymore a particular object, this free memory for other use.
Other tips
Use StringBuilder instead a normal string composition (string += "aaaa";
)
Use BufferedReader/BufferedWriter for reading/writing files.
Use foreach instead a normal for (where its possible), this can reduce the operation into the loop.
Use PreparedStatement instead of Statement: PreparedStatement can precompile the SQL statement
Conclusion
Separately, each of this recommendations are not a big impact on the environment but if apply together you can see a significant improvement of performance, of the user experience and prevents future worsening.
I hope I have been useful to you