1. François ROSSIGNOL
  2. PowerBuilder
  3. Friday, 12 March 2021 12:53 PM UTC

Hi,

 

we're concerned with the memory usage our our latest powerbuilder application.

It was originally build with PB17R3 and is now running with PB19R2.

It has been migrated to PB19R3 for memory testing purpose but the results are the same.

the application is 32 bits

 

The application is built over our homebrewed framework (which certainly contains some design flaws).

It contains quite a bit of overhead and services.

 

Here is the tests we're using.

Open 10 times the same window

Close all the windows

Open the same window 10 times

Close all windows

Rince and repeat.

 

When closing the windows some of the consumed memory is freed but not all ot it.

Each time we lose between 3 and 10 MB of RAM.

Use it long enough it consumes hundreds of MB of RAM when a freshly openned app consumes around 70 MB.

It's the same whether the app is compiled in p-code and ran from the IDE.

Sometimes (but rarely) I can open the windows without additionnal memory usage.

Sometimes (but very rarely) additionnal memory will be randomly be freed.

If the app is ran from the IDE when you close the app and return to the IDE, PB190.exe still has a high memory usage.

 

I'm having a hardtime identifying the leak, I tested old version of the app the problem was present from the begining but was less severe.

 

Let's say before opening the windows I had a 100MB memory usage

I open the windows and it goes up to 150MB

I close all the windows memory goes back to 103MB

 But sometime it'll briefly drop back to 100MB and going up to 103MB

 

Is there a tool to see the memory consuption of each object in memory ? Or any other tool that might be 

 

The usual suspects

I checked the code each CREATE is matched with a DESTROY

each openUserObject is matched with a closeUserObject

I used CDMatch to check I don't have npt destroyed objects

Interrestingly I have a bunch of destroyed object which are not created.

They're all autoinstentiated nvos and structures, could this be part of the problem ?

 

 

The master datawindow and datastore objects have a this.reset() and this.dataObject = "" in the destructor event

 

I red in a previous post something about arrays

String   ls_col1[], ls_null[]  

//populate your array, then finish with

ls_col1 = ls_null

I'm currently working on that but it's going to take some time because we have a lot of arrays used in the framework.

 

We already use UseHwnd=no in the pb.ini

 

I also tried that

However, a neat little trick I used to use is to momentarily minimize the PB App (say on an IDLE event) by using the SEND command. If you send a Minimize to the MDI Frame window, do a a few yields and the then send he MDI Frame a "restore" command ... I have found that the PBVM would actually release memory that is marked as "free".

 

That didn't do the trick, plus it's really annoying having the application pop back in the front when you're not using it.

 

more and more of our customers uses RDP connexions to run the app therefore there's limited ressources per user.

meaning once the leak is fixed we'll try to tackle overall memory usage for the application.

 

I tried to throw some additionnal GarbageCollect

 

Now I have a few more questions about memory management and memory usage:

Does readonly argument versus by value make a difference ?

In a some of our service objects arguments for objects are by value where they should be by reference (because those objects are modified) but even if they're passed by value they're still correctly modified. The resaon they're passed by value is because I can't do a my_service_object.of_function(this) when calling it from let's say my master datawindow.

Does that have an impact on memory management. And what would be the correct way to do things ?

 

We do have "read-only" datawindows but it's safe to assume some of them have update properties set. is there significant impact here ?

 

what else should I be on the lookout for ?

 

Thanks in advance

 

Regards,

François

Ricardo Colarina Accepted Answer Pending Moderation
  1. Tuesday, 23 March 2021 04:17 AM UTC
  2. PowerBuilder
  3. # 1

Hi François,

Maybe someone in the community might be able to point out if there are any cons to using this Windows API, but

SetProcessWorkingSetSize(-1, -1, -1) helped with freeing memory usage for a PB Windows Service application I did some way back.

Cheer,

Ricardo

 

Comment
There are no comments made yet.
François ROSSIGNOL Accepted Answer Pending Moderation
  1. Monday, 15 March 2021 12:26 PM UTC
  2. PowerBuilder
  3. # 2

Hi Benjamin

 

my guess was it was all pointers when it came to objects but one of my coworkers kept bothering me on the subject so I told him I'd ask.

we completly missed that section of the help, I feel embarrassed because the help section is usualy my first stop.

 

thank you for your answer

Comment
There are no comments made yet.
Benjamin Gaesslein Accepted Answer Pending Moderation
  1. Monday, 15 March 2021 10:23 AM UTC
  2. PowerBuilder
  3. # 3

Hello François.

Does readonly argument versus by value make a difference ?

In a some of our service objects arguments for objects are by value where they should be by reference (because those objects are modified) but even if they're passed by value they're still correctly modified. The resaon they're passed by value is because I can't do a my_service_object.of_function(this) when calling it from let's say my master datawindow.

Does that have an impact on memory management. And what would be the correct way to do things ?

When you pass objects to a function, what you're actually passing is a pointer variable. The method changes the type of pointer you get; "by reference" passes the actual pointer to the object in memory, "by value" passes a copy of the pointer, and "read-only" passes a read-only copy of the pointer. (PB being written in C++ I can take a guess at what happens behind the scenes: by reference passes a variable holding the actual address in memory, by value passes a variable with a pointer to the original address in memory, read-only passes a const pointer to the address)

In all three cases, the state of the original object can change. However only when using "by reference" can you change the original pointer to point to a different object. I.e. let's say of_function(ref n_object o) creates a new object of type n_object and assigns it to "o" -> o will now point to the newly created object instead of the object that was passed to it. The only reason to use "by reference" is if you want to reassign a different object.

You can also reassign the passed-in pointer when you pass "by value" but the original pointer will not change in this case, the newly created object will only be available within the method. In "read-only" mode, you cannot reassign the pointer at all.

This is the reason "my_service_object.of_function(this)" will not compile if you pass by reference; "this" is a read-only pointer and can never be reassigned to point to another object.

 

Source: https://docs.appeon.com/pb2019/powerscript_reference/ch06s06.html

 

In conclusion, whatever method you're using should not have any effect on memory, it's basically just pushing around pointers.

Comment
There are no comments made yet.
François ROSSIGNOL Accepted Answer Pending Moderation
  1. Monday, 15 March 2021 07:42 AM UTC
  2. PowerBuilder
  3. # 4

Hi thanks for the answers

 

Thanks Mike for the links for the tickets

some more informations about that we do use a lot of openUserObjects

I build our framework like a blank canvas where almost everything is created on the fly as needed. When I red the tickets it hit me that it was what I was facing, but I also red that this was supposed to be fixed in build 2353 which is the one we're using.

I'll still investigave and test some more towards that.

 

Chris

the 1) is in place since the beggining, I think I got that one from some of your old posts.

 

Blob usage is minimal but I'll give it a whirl once I finished with the arrays.

 

We do not use tab contrôls but I'll keep it in mind.

 

thanks for the advices.

 

François

Comment
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Friday, 12 March 2021 18:40 PM UTC
  2. PowerBuilder
  3. # 5

Hi François;

  You seem to have done some great work to try and reduce the App's overhead!

  For the App "minimize" (aka MDI Frame) - that trick used to work back in the PB 10.x / 11.x and early 12.x builds of PB.  I used to use that trick in my STD Framework but I noticed by PB 12.6 that this no longer had a memory releasing effect.  :-(

  Other things that I do in my framework are ...

1) DataWindow Control Destructor event (preferably in a DC ancestor) ...

  • THIS.Reset ()
  • THIS.DataObject = ""
  • Yield ()

2) Memory release for large arrays of any variable types, for example ...

  • Blob   lblb_data[]
  • Blob   lblb_null []
  • SetNull (blb_null )
  • //FOR NEXT LOOP using lblb_data array
  • // More processing using lblb_data array
  • lblb_data  = lblb_null   // Free memory at end of processing

3) Tab controls ... try to always use "CREATE on Demand" property ON

HTH

Regards ... Chris

Comment
There are no comments made yet.
mike S Accepted Answer Pending Moderation
  1. Friday, 12 March 2021 13:17 PM UTC
  2. PowerBuilder
  3. # 6

i've seen problems too with openUserObject, but it seems to max out after awhile.  That doesn't help your RDP situation, but at least it doesn't seem to grow until it crashes

bug reports that are related to memory usage (not being released)

 

 

https://www.appeon.com/standardsupport/search/view?id=4479

https://www.appeon.com/standardsupport/track/view?id=5242

 

Comment
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.