cancel
Showing results for 
Search instead for 
Did you mean: 

Nested Objects and High Memory Consumption

Good day, everyone.

When a Business Object calls other Business Objects, Blue Prism appears to create additional object instances rather than reusing those already loaded by the Process.

From a performance and memory consumption perspective, is there any official guidance on how much object nesting is considered reasonable?

For example, a "REST API" object might internally call:

  • HTTP Utility
  • JSON Utility
  • Authentication Utility

Is this still considered the recommended architecture, or are there scenarios where implementing reusable functionality as a Process (called through a Process Stage) would be preferable?

I reviewed the discussions below but could not find a definitive recommendation from Blue Prism:

  • Unexpected high memory usage for shared objects

Any guidance or official references would be appreciated.

eduardocarvalho_0-1787934719508.pngeduardocarvalho_0-1787934719508.png

 

RE: AI and ML Capabilities - SS&C Blue Prism Community

RE: Unexpected high memory usage for shared object... - SS&C Blue Prism Community

 

 

1 REPLY 1

I have just so much to say on this topic. I'll try to keep it focused as much as I'm capable of doing lol.

First, Blue Prism's official guidance on calling Processes from another Process is that you should never do it in a loop because the process is reloaded into memory each time it is called, whereas Objects use the existing instance so it's better on memory usage. I have no idea where that is because BP got rid of their documents that they used to provide so it's probably in a University course and I don't enjoy clicking through those unless I'm learning something new. I personally almost never call other Processes from a Process (and definitely not from an Object), but there are legitimate reasons to do it. It's so edge case that I see no reason to describe it though since you can pretty much always just change your design to not do it.

 

Second, object nesting is not a bad thing in most scenarios. The main reason to do it, from my experience, is when you're calling reusable utilities, such as you mentioned in your example. Depending on the complexity of those utilities, they are often tiny in comparison to that of full objects that automate UIs and stuff. Granted, a complex utility object can be the same size or larger than UI objects. Also, related to this, it is and has always been a standard that you should split up objects to keep them as small as possible both to allow multiple developers to work simultaneously as well as to keep memory overhead low. If your process only needs one action, then it's a bit unnecessary to have all the others loaded into memory -- that kind of thing. Straight from the horse's mouth (I mean Blue Prism here): "You can never have too many objects, only too few". Overall, in my experience, this will not cause any issues unless you choose to call a massive object nested and also if you go super deep into the nesting. If you stick to one or two levels and you're not heavily doing this, I doubt you will ever notice a difference except that it does take a moment for those object instances to load. All this said, I do often copy code over into an object to avoid the nesting, not because of total memory usage but to avoid that object instance load time because it is loaded at the moment the action is called and not when the process is initially started. This means that nested objects are not loaded as an instance until and unless they are actually called. Anyway, I don't think it's a problem to nest whenever it benefits you to do so. If you're unsure, just copy solid code into multiple objects. The idea of DRY (Don't Repeat Yourself) does not need to be followed rigidly. It is just a guideline to keep in mind to improve maintainability of code.

 

Third, I want to explain a few things about object instances. You may already know this, but it is important to notice how it works because it can impact how you decide to nest and whether or not you do.

While it's true that Blue Prism creates a new instance of an object from each process/object that calls it, it does reuse the instance from each level/location where it is called from.

I'll do an example of Process A, Object B (OB), and Object C (OC). I'll use "->" to indicate left side is calling right side.

Process A -> Object B (new first instance of OB)

Process A -> Object B (reuses first instance of OB) -- this is as if Process A calls Object B a second time somewhere else in the flow

Process A -> Object C (new first instance of OC)

Process A -> Object B some action -> Object C (new second instance of OC)

Process A -> Object B diff action -> Object C (reuses second instance of OC)

Process A -> Object C (reuses first instance of OC)

In all that, there is only ever two instances of Object B and Object C. The main thing to recognize here is that Blue Prism does reuse instances from each level/layer/process/object. So, any given instance of a process or object will only ever create one instance of any other given process or object.

 

Fourth, I wanted to mention what the real problem is with memory consumption, as I do not think the issue is nested objects. The real issue is collections (and huge text data items - same thing applies but I'll just mention collections throughout this paragraph). Collections appear to have separate copies for each place where they are defined. If a collection is defined in one page of a process and also in another page in a process and also in an object, the data is actually copied to each and is retained in all of these places if you pass the collection data through it. The only way to get rid of this extra memory usage is to delete all rows/empty the collection or for the process to stop altogether. If a collection's rows are deleted or if a text data item is cleared, I believe it stays in memory, but the .NET garbage collector will delete it when it needs more memory. You can also purposefully/directly call the garbage collector using a tiny bit of VB.NET/C# code if you want but you have to clear the collection first. So, if you passed a big collection or even a huge text data item (like you might do in an API call using those objects you mentioned in the nesting example), that gets copied in each location (process/page/object/action). If you have a collection (or text data) that is 5 MB, Blue Prism can handle that just fine, but if you copy it and pass it through a number of pages or through a number of objects or actions, you could quickly turn that into using 100+ MB of memory. Even that will not necessarily crash Blue Prism (especially on recent true 64bit versions), but it is an inefficient use of memory. The way that I have combatted this is to refactor various objects (especially the collections utility vbo) so that there is a global collection (or two or three) on the Initialise page that gets reused by all actions. This way it gets overwritten each time. And then I also clear collections wherever and whenever possible. I also sometimes create a dedicated action in an object that a process can call in order to clear all the collections in the object. This does take some effort to do and think through, so I only recommend worrying about it when/if you actually run into a problem. In many cases, you don't have to edit the central objects at all and the problem can be addressed at the process level by handling collections differently.

 


Dave Morris, 3Ci at Southern Company