Performance and Coding

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):

  1. Database
  2. JVM
  3. 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:
image
with those import:

import sailpoint.object.*;
import sailpoint.tools.*;

the performace is little different:
image
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

5 Likes

@enistri_devo
Good information. Thanks for sharing.

1 Like

@enistri_devo
This is very useful and thanks a lot for sharing.

1 Like