A Brief History of Performance

A Brief History of Performance

The question I want to look here is how to speed up my automation workflows in the context of SAP. Often there is the situation that there must be processed a lot amount of data, but the time to do that is not enough. So first I focused on the question how fast I am. For this I made a direct comparison between the use of SAP GUI Scripting via Windows Scripting Host and a UiPath workflow.

At first the VBScript code:

StartTime = Timer
For i = 1 To 10
  session.findById("wnd[0]/tbar[0]/okcd").text = "/nSE16"
  session.findById("wnd[0]").sendVKey 0
  session.findById("wnd[0]/usr/ctxtDATABROWSE-TABLENAME").text = "TADIR"
  session.findById("wnd[0]").sendVKey 0
  session.findById("wnd[0]").sendVKey 31
  session.findById("wnd[1]/tbar[0]/btn[0]").press
Next
EndTime = Timer
TimeIt = EndTime – StartTime
MsgBox CStr(TimeIt)

Now the corresponding workflow:

The differences are considerable. The VBScript code needs approx. 17 seconds and the UiPath workflow needs approx. 48 seconds. VBScript code is nearly three times faster. Now I combine these solutions to the following workflow:

Now the UiPath workflow needs approx. 18 seconds. Great.

Then I thought about what this integration scenario actually means.

Advantages and Disadvantages

The advantages of the solution above can be bundled in one word: Speed. The disadvantages contain a few perspectives. The most concise is the loss of control over a part of the process. One step of your automation workflow is now a black box, which contains a lot of steps. These steps escape the visibility of the workflow and therefore the understanding of a person who works with it. It works outside, on a different (language) platform. This also requires more knowledge at other levels, e.g. programming. In the case of an error it must be ensured that there is seamless communication with the calling workflow, to provide it with clear error messages. This integration requirement increases the effort of the workflow building.

Conclusion

Speed does not justify the loss of many advantages that RPA offers us. The scalability of bots offers us the possibility to compensate limited time frames. With complex consolidated solutions this integration scenarios can be considered, or where it is not otherwise possible. In any other case an RPA implementation should be preferred. Speed is not everything. It is our job to build RPA processes so that they are efficient.

5 Likes

Excellent post @StefanSchnell. So many of us are targeting transactional solutions for client systems. It is vital to properly frame the unique value that RPA brings to the table. We do have to answer the speed question but value looms much larger.

1 Like

Thank you @jamiejam :slightly_smiling_face:

SAP Intelligent RPA - A Look Over the Fence

In retrospect I was interested how other RPA platforms behave. To look at this, I implemented the same approach with SAP Intelligent RPA. Here the workflow from Desktop Studio:

Here the JavaScript code:

// ----------------------------------------------------------------
//   Test menu for scenario newWorkflow 
// ----------------------------------------------------------------
GLOBAL.events.START.on(function (ev) {
	if (ctx.options.isDebug) {
		// Add item in systray menu.
		systray.addMenu('', 'newWorkflow', 'Test newWorkflow', '', function (ev) {
			var rootData = ctx.dataManagers.rootData.create();
			
			// Initialize your data here.
			SAPEasyAccess.scenarios.newWorkflow.start(rootData);
		});
	}
});

//---------------------------------------------------
// Scenario newWorkflow Starter ()
//---------------------------------------------------

// ----------------------------------------------------------------
//   Scenario: newWorkflow
// ----------------------------------------------------------------
SAPEasyAccess.scenario({ newWorkflow: function(ev, sc) {
	var rootData = sc.data;

	sc.setMode(e.scenario.mode.clearIfRunning);
	sc.setScenarioTimeout(600000); // Default timeout for global scenario.
	sc.onError(function(sc, st, ex) { sc.endScenario(); }); // Default error handler.
	sc.onTimeout(30000, function(sc, st) { sc.endScenario(); }); // Default timeout handler for each step.
	// Initialize Loop counters
	sc.localData.Startloop = 0;

	rootData.start = new Date().getTime();
	
	
	sc.step(SAPEasyAccess.steps.Start_loop, SAPEasyAccess.steps.pSAPEasyAccess_manage);
	sc.step(SAPEasyAccess.steps.pSAPEasyAccess_manage, SAPEasyAccess.steps.Loops_to_the_start_bl, 'NEXT_LOOP');
	sc.step(SAPEasyAccess.steps.pSAPEasyAccess_manage, SAPEasyAccess.steps.pDataBrowserInitial_m);
	sc.step(SAPEasyAccess.steps.pDataBrowserInitial_m, SAPEasyAccess.steps.Loops_to_the_start_bl, 'NEXT_LOOP');
	sc.step(SAPEasyAccess.steps.pDataBrowserInitial_m, SAPEasyAccess.steps.pDataBrowserTableT_ma);
	sc.step(SAPEasyAccess.steps.pDataBrowserTableT_ma, SAPEasyAccess.steps.Loops_to_the_start_bl, 'NEXT_LOOP');
	sc.step(SAPEasyAccess.steps.pDataBrowserTableT_ma, SAPEasyAccess.steps.pDisplayNumberOfEnt_m);
	sc.step(SAPEasyAccess.steps.pDisplayNumberOfEnt_m, SAPEasyAccess.steps.Loops_to_the_start_bl, 'NEXT_LOOP');
	sc.step(SAPEasyAccess.steps.pDisplayNumberOfEnt_m, SAPEasyAccess.steps.pDataBrowserTableT_ma_1);
	sc.step(SAPEasyAccess.steps.pDataBrowserTableT_ma_1, SAPEasyAccess.steps.Loops_to_the_start_bl, 'NEXT_LOOP');
	sc.step(SAPEasyAccess.steps.pDataBrowserTableT_ma_1, SAPEasyAccess.steps.Exit_loop);
	sc.step(SAPEasyAccess.steps.Exit_loop, SAPEasyAccess.steps.Loops_to_the_start_bl, 'NEXT_LOOP');
	sc.step(SAPEasyAccess.steps.Exit_loop, SAPEasyAccess.steps.Loops_to_the_start_bl);
	sc.step(SAPEasyAccess.steps.Loops_to_the_start_bl, SAPEasyAccess.steps.Start_loop, 'NEXT_LOOP');
	
}}, ctx.dataManagers.rootData).setId('b1d7dbae-8a8d-4f78-854d-e9fad301e91a') ;

// ----------------------------------------------------------------
//   Step: Start_loop
// ----------------------------------------------------------------
SAPEasyAccess.step({ Start_loop: function(ev, sc, st) {
	var rootData = sc.data;
	
	ctx.workflow('newWorkflow', 'b96c70f2-8bf1-43f4-ac5d-a2e78b763a78') ;
	// Starting instruction for a loop.
	if (sc.localData.Startloop < 0) sc.localData.Startloop = 0;
	sc.endStep(); // pSAPEasyAccess_manage
	return;
}});

// ----------------------------------------------------------------
//   Step: pSAPEasyAccess_manage
// ----------------------------------------------------------------
SAPEasyAccess.step({ pSAPEasyAccess_manage: function(ev, sc, st) {
	var rootData = sc.data;
	ctx.workflow('newWorkflow', 'e6f8fac0-109b-41c9-9f95-098ee0311125') ;
	// Wait until the Page loads
	SAPEasyAccess.pSAPEasyAccess.wait(function(ev) {
		SAPEasyAccess.pSAPEasyAccess.oGuiOkCodeField.set("/nSE16");
		// Sends a key sequence to a page.
		SAPEasyAccess.pSAPEasyAccess.keyStroke(e.SAPScripting.key._Enter_);
		sc.endStep(); // pDataBrowserInitial_m
		return;
	});
}});

// ----------------------------------------------------------------
//   Step: pDataBrowserInitial_m
// ----------------------------------------------------------------
SAPEasyAccess.step({ pDataBrowserInitial_m: function(ev, sc, st) {
	var rootData = sc.data;
	ctx.workflow('newWorkflow', '7090b4f7-e9e2-4480-a339-35e23679c167') ;
	// Wait until the Page loads
	SAPEasyAccess.pDataBrowserInitial.wait(function(ev) {
		SAPEasyAccess.pDataBrowserInitial.edTableName.set("TADIR");
		// Sends a key sequence to a page.
		SAPEasyAccess.pDataBrowserInitial.keyStroke(e.SAPScripting.key._Enter_);
		sc.endStep(); // pDataBrowserTableT_ma
		return;
	});
}});

// ----------------------------------------------------------------
//   Step: pDataBrowserTableT_ma
// ----------------------------------------------------------------
SAPEasyAccess.step({ pDataBrowserTableT_ma: function(ev, sc, st) {
	var rootData = sc.data;
	ctx.workflow('newWorkflow', 'dc4471f3-7c97-4354-8eea-4eeec545743e') ;
	// Wait until the Page loads
	SAPEasyAccess.pDataBrowserTableT.wait(function(ev) {
		// Sends a key sequence to a page.
		SAPEasyAccess.pDataBrowserTableT.keyStroke(e.SAPScripting.key._Ctrl__F7_);
		sc.endStep(); // pDisplayNumberOfEnt_m
		return;
	});
}});

// ----------------------------------------------------------------
//   Step: pDisplayNumberOfEnt_m
// ----------------------------------------------------------------
SAPEasyAccess.step({ pDisplayNumberOfEnt_m: function(ev, sc, st) {
	var rootData = sc.data;
	ctx.workflow('newWorkflow', '7061e35c-014c-4d61-8b84-600c2be1c4fc') ;
	// Wait until the Page loads
	SAPEasyAccess.pDisplayNumberOfEnt.wait(function(ev) {
		SAPEasyAccess.pDisplayNumberOfEnt.btClose.click();
		sc.endStep(); // pDataBrowserTableT_ma_1
		return;
	});
}});

// ----------------------------------------------------------------
//   Step: pDataBrowserTableT_ma_1
// ----------------------------------------------------------------
SAPEasyAccess.step({ pDataBrowserTableT_ma_1: function(ev, sc, st) {
	var rootData = sc.data;
	ctx.workflow('newWorkflow', '2c1d8ace-1c6e-4912-bfeb-45c48232bd4f') ;
	// Wait until the Page loads
	SAPEasyAccess.pDataBrowserTableT.wait(function(ev) {
		SAPEasyAccess.pDataBrowserTableT.oGuiOkCodeField.set("/n");
		// Sends a key sequence to a page.
		SAPEasyAccess.pDataBrowserTableT.keyStroke(e.SAPScripting.key._Enter_);
		sc.endStep(); // Exit_loop
		return;
	});
}});

// ----------------------------------------------------------------
//   Step: Exit_loop
// ----------------------------------------------------------------
SAPEasyAccess.step({ Exit_loop: function(ev, sc, st) {
	var rootData = sc.data;
	
	ctx.workflow('newWorkflow', '84a226e6-120e-4fc7-aace-124046a26559') ;
	// Test block to exit from a loop.
	if (sc.localData.Startloop > 9)
	{
		sc.localData.Startloop = -1 ;
		sc.endStep('NEXT_LOOP');
		return ;
	}
	sc.endStep(); // Loops_to_the_start_bl
	return;
}});

// ----------------------------------------------------------------
//   Step: Loops_to_the_start_bl
// ----------------------------------------------------------------
SAPEasyAccess.step({ Loops_to_the_start_bl: function(ev, sc, st) {
	var rootData = sc.data;
	
	ctx.workflow('newWorkflow', 'fc061908-fc2b-4a45-aaeb-9b2347ba9447') ;
	// Loops to the start block.
	if (sc.localData.Startloop != -1)
	{
		sc.localData.Startloop++ ;
		sc.endStep('NEXT_LOOP');
		return ;
	}
	sc.endStep(); // end Scenario
	var end = new Date().getTime();
	var time = end - rootData.start;
	ctx.log(time.toString());
	return;
}});

And here the result from the Desktop Debugger:

image

Approx. 48 seconds. This perspective confirmed the conclusion from above and there is nothing to add.

2 Likes

SAP eCATT - Another Look Over the Fence

In retrospect I was also interested how SAP Extended Computer Aided Test Tool (eCATT) behave. To look at this, I implemented the same approach with SAP eCATT. You can find more information about the eCATT commands here. In the focus of interest is here the command SAPGUI, because it offers all possibilities equivalent to SAP GUI Scripting and the RPA platforms. Here the script from SECATT transaction:

image

It does exactly what the approaches of SAP GUI Scripting with VBScript, UiPath or SAP Intelligent RPA does.

But as you can see in the protocol is the execution time better. 37 seconds instead 48 seconds - approx. 23% percent better than the RPA approaches (I took 10 measurements, that’s an average measurement). That is a word. If you process large amounts of data and you can process 1000 or 1230 records in the same time, that is a difference.

Interesting, double time slower as SAP GUI Scripting in VBScript, but 25% percent faster as the RPA solutions. Is eCATT with it’s possibilities an interesting companion for RPA in the SAP context?

As we can see, each control unit takes time. Some more, some less.

Finally an important note: You can not use eCATT for productive systems, only for test and development systems. So it is not an alternative in a productive environment.

1 Like

@StefanSchnell I have gone through all of your comparison. It was really nice and helpful.:+1:

1 Like

@Arpit_Kesharwani

Thank you very much Arpit. :slightly_smiling_face:

1 Like

Blue Prism - And Another Look Over the Fence

In retrospect I was interested how other RPA platforms behave. To look at this, I tried the same procedure with Blue Prism. Here the object from the studio:

Wow, as you can see it tooks 8 seconds with the fastest debug speed. From Control Room with a process 11 seconds.

BPA Object - SE16 Performance Test.bpobject.xml (17.5 KB)

1 Like