This blog describes the newly introduced 1802 feature “Run Performance Check” in SAP Cloud Application Studio.
Check for updated features
SAP Cloud for Customer is getting updated every 3 months. The added features are highlighted in the What’s New section in the documentation at help.sap.com/studio_cloud. These features are often capable of replacing expensive workarounds you had to do in the past to archive the same functionality.
This feature is an upgrade on the “Performance Tips” feature available in SAP Cloud Application Studio until the 1708 version(September 2017).
The old feature is detailed here : https://blogs.sap.com/2015/08/27/sap-cloud-application-studio-performance-best-practices/
Starting from the 1711 Studio release, the “Performance Tips” feature is being replaced by a new “Run Performance Check” feature.
This feature will now be available on the following content types :
- Business Object(.bo)
- Extension Business Object(.xbo)
- ABSL scripts(.absl)
- UI Files
- Solution Level(Top level containing the solution name in Solution Explorer)
How if this feature different from the old “Performance Tips” ?
This feature will now display the results of the Performance check directly in the “Error List” window instead of the previous feature where results where shown in a pop-up window. Now,clicking on the suggestion will take you directly to the file and line where the suggestion is applicable. This enhances the usability of this feature as iser can now navigate and correct each suggestion.
The feature has also been extended from only absl scripts to be available on four other places as mentioned above. In the future, it is planned to extend this feature to more content types in Cloud Application Studio.
The option “Run Performance Check” available on the header level in Solution explorer on right-click of the solution name will start a background job and you will now receive the results via an email with attachment from the SAP system.
Understanding the different performance check messages
1.1 BO/XBO Messages:
Currently the only messages from Business Object/Extension Business Object check is “Representation term ‘Text’ of data type ‘LANGUAGEINDEPENDENT_LONG_Text’ does not fit to element name ‘Locality’.”
This is just an Information(info message) for the developer that the element/field name added to the current BO/XBO doesn’t match the name or the pattern of the data type. Many times fields are added to the bo/xbo defintion as temporary fields or to try out a specific functionality. If these fields are not removed from the defintion before the solution is assembled they get shipped to the Production tenant/Customer Landscape and they can never be removed. As a result they end of consuming space and resources in all Transactions between UI and backend but never actually serving purpose.
This Performance message Highlights all fields that have a mismatch between element Name and field Name to give an idea if any unwanted fields exist in the bo/xbo Definition.
1.2 ABSL Messages :
The Performance check Messages from ABSL scripts can be interpreted as follows.
1.2.1 Too many retrieves by navigating through instances :
The message for this check reads as “Additional use of association ‘toBusinessPartner’. Define a local variable once and use it in all resp. places.”
The ABSL language makes it very easy to navigation through objects. Behind the scenes objects are being retrieved and discarded. In a nutshell, every dot retrieves something. Either a node or an associations. Accessing a node is fast, retrieving an object by association much slower and doing it over and over again easily adds up to several seconds.
For performance reasons, retrieves by association should be kept at the possible minimum. Results from retrieve by associations should be buffered in the coding if possible.
In the below code, toParent, toBusinessPartner, EmployeeResponsible and DefaultAddress are representing associations. The code results in 13 retrieves on the server side.
this.toParent.RespEmplAddrStreet = this.toBusinessPartner.EmployeeResponsible.Address.DefaultAddress.Street;
this.toParent.RespEmplAddrPostCode = this.toBusinessPartner.EmployeeResponsible.Address.DefaultAddress.PostCode;
A better code example would save the instances in local variable. The example below works with 7 associations, would speed it up by factor two.
var emplResp = this.toBusinessPartner.EmployeeResponsible;
var emplRespAddress = emplResp.Address.DefaultAddress;
var parent = this.toParent;
parent.RespEmplAddrStreet = emplRespAddress.Street;
parent.RespEmplAddrPostCode = emplRespAddress.PostCode;
Keep in mind that .IsSet() leads to an association. Avoid redundant “retrieve by association” operations by storing the result of an operation in a variable / collection
1.2.2 Trace Statements :
The message reads as “Trace statements slow down performance. Use debugger instead.”
Using association in trace statements causes the Problem. Even if the trace is not active, the content inside the trace statement is evaluated. This also might lead to “retrieve by association” operations that can be easily avoided.
A pretty easy improvement is the removal of trace statements. If you have code like this in your project:
Trace.Info("Instance Count", this.toAnotherBO.Count());
The this.toAnotherBO.Count() is getting retrieved and executed even when the trace is not set to active.
1.2.3 Empty Create() calls :
The message reads as “Pass data during create instead of setting the attributes afterwards.”.
An empty create call looks like this :
var createdinstance = Opportunity.Create();
createdinstance.ID.content = "2";
var item = createdinstance.Item.Create();
createdinstance.Name.content = "New Opp";
Further Code would then update the value of fields in the variable “createdinstance”. This will lead to update calls and buffer flushes which could have been avoided if the the Create() call above would have been done along with the data already filled.
This check finds such places and suggests to Change the Code to something like this for improving Performance :
var data : elementsof Opportunity;
data.ID.content = "2";
data.Name.content = "New Opp";
var createdinstance = Opportunity.Create(data);
var item = createdinstance.Item.Create();
1.2.4 Excessive use of Where() calls :
The message reads as “Where() statements directly convert to for-loops and slow down performance. “
The Where() calls actually convert straight to foreach() loop calls in the backend. This is not very obvious form the Syntax of the calls and hence leaves the calls open to Interpretation and misuse.
var find = res.Where(n=> n.ID.content == this.EmpID);
If the Where() call is executed on a large/unsorted set of data, this one line of code can end up consuming a lot of time and hence this Performance check advises you to use the where() call wisely.
1.2.5 Avoid Dump :
The message reads as “Avoid dump : Use IsSet() to check the value returned by association Address. “.
var str = this.Address.Street;
This message is not so much a performance suggestion but rather a coding suggestion. If a line of code is written to navigate using association then it’s wise to check if the association has some data before navigating to the otherwise there will be a dump.
Hence the code should look like :
var str = this.Address.Street;
1.3 MDRO Messages :
The Performance check built on MDRO(.run file) in SAP cloud application studio analyze the design of the mdro as well as the ABSL script that this run executes. The list of performance check is a combination of these two checks :
1.3.1 Parallel Processing : The message reads as “MDRO Parallel processing is not turned on.”
This property enables the framework executing the mass data run to break down the execution in 6 parallel process with 50 instnaces in each process.
Let’s say the query defined in the .run file returns 600 instances. If parallel processing is not enabled each of the 600 instances will be executed one by one and the absl code will be called for each one of them sequentially. This may lead to a high time and resource consumption based on the logic written in the absl code. The mdro run have a static 10 hour execution window after which the run will be terminated so it’s a possibility that the run fails. By switching ON the parallel processing, the execution can be finsihed in a shorter time frame.
Caution : The parallel processing feature should not be turned ON if the code written for the run has logic that can update the same document/instance for two different mdro records i.e. if the MDRO runs on Opportunity and the code running parallely on two different oportunities updates the same Customer information, then a locking object error will error will occur leading to failure of the mass data run.
1.3.2 Action not mass enabled : The message reads as “MDRO action is not mass enabled and this leads to slow perfomrance. Please enable it for faster execution“.
The ABSL code linked to the mass data run is not mass enbled. If it is enabled then all the 50 instances in one process will be executed at one go and hence will take lesser time because queries and searched which would have otherwise been done 50 times will only be done once.
1.3.3 MDRO Design/Query inside ABSL : The message reads as “Query inside MDRO Action gets executed for every instance and slows down performance.” and “MDRO Design: Use Query of the MDRO framework to leverage packaging and parallel processing”
If there are queries written inside the ABSL code, they will be executed for each MDRO instance, so basically the same search is performed over and over again. Hence the info message to leverage the query of the MDRO design is combined with this.This is a suggestion to get the wanted list of instances from the MDRO query and try to reduce writing queries in code to imrove performance.
1.3 UI Messages :
1.3.1 Lazy load UI components : The message reads as “The Lazy Loading property is not enabled for EC TestEC.EC.uicomponent added to UI via Extensibility Explorer.“
It is possible to influence the UI component loading sequence by enabling Lazy Loading.
- Lazy Loading can be activated when adding Embedded Components to standard screens. It will result in an initialization of the embedded component when it gets displayed instead of an initialization when the host object gets loaded. This is often a good idea, but might lead to unintuitive behavior when the logic in the embedded component writes data back to the host BO for example. Then you would see different data on the host BO before you navigated to the embedded component the first time, and different data afterwards.
- Lazy Loading can be activated on custom thing inspector level by turning the data scope handling attribute. This will lead to lazy loading of all thing inspector facets.
1.3.2 Enable operation clubbing : The message reads as “The property to enable Operations Clubbing is turned off for this UI file.“