Abl - Persistent Procedure

maretix

Member
Good day to all of you.

My question is about PERSISTENT PROCEDURE.

I have a program that for a million of records (different product) needs to retrieve a price.
All calculation depends on several financial factors ..so i have a CalcPrice.p very complex.

I thinked to write a program that use persistent procedure to use CalcPrice.p in memory and not reload every time.

My program (simple versione to explain my question)


DEFINE hproc AS HANDLE.

RUN CalcPrice.p SET PROCEDURE IN Hproc. /* CalcPrice.p is an external program that calls Others .p */

FOR EACH <table products> NO-LOCK:
....
....

RUN CalcPrice .p NO-ERROR .

/* Is it correct ??? In this manner ,, I really do good performance to my program ???
....
....

END.

Thanks in advance.
 

tamhas

ProgressTalk.com Sponsor
Well, it's a start. Once you run CalcPrice.p and set the handle, you don't need to run it again. Instead, you run internal procedures in it, i.e., run GtePrice() in Hproc. If CalcPrice.p calls the same programs over and over, then the initial block of CalcPrice.p, before the internal procedures, should also run those persistent so that you can run IPs in them. You should also read up on super procedures since that would allow you to do the same thing without an explicit handle. This can be useful if there are any nested procedures since you don't have to pass in the handle. Depending on Progress version, you could also do the whole thing by turning CalcPrice.p into a class.
 

GregTomkins

Active Member
I think your syntax is wrong. It should be something like:

Code:
RUN CalcPrice.p PERSISTENT SET Hproc. /* This is like 'CalcPrice calcprice = new CalcPrice();' in Java or C# */
FOR EACH Thing:
RUN someProcedure IN Hproc. /* This is like 'calcprice.someProcedure()' in Java or C# */
END.

If for example CalcPrice.p has to look up a bunch of configurational data each time it starts, but not after that, then running it this way could save a ton of time. If CalcPrice is just doing in-memory calculations, I suspect its benefit would be very minor. It depends on what exactly happens inside CalcPrice.p. It should be easy enough to benchmark it.

I suspect others will disagree with me, but in our shop, we don't use PP's very much. If we were processing 1,000,000 records in some batch job, that job is generally going to run in a few seconds and we would not invest a lot of time into its performance. For real-time processing, we use them here and there, but for the most part, we (successfully) rely on DB cache to keep things fast, and overall, most days, performance would not make our top-10 list of problems. (For context, our system runs maybe 1,000 concurrent users and a few 100,000 transactions per day per DB, so it's a reasonable size, but not huge).
 

tamhas

ProgressTalk.com Sponsor
Note that running an external procedure is expensive compared to running an internal procedure, whether or not there is startup, but especially if there is start up. So, in a million iteration loop, it can be significant. But, the other benefit of PPs and SPs and classes is that it encapsulates reusable code.
 

GregTomkins

Active Member
Sure, but if you run it once a day for 20 seconds, who cares if you can get it down to 18 seconds.

External procedures also encapsulate reusable code. I would argue at least as effectively, although, I don't think it really makes much difference unless you care about caching configurational-type data (in which case certainly it could make a huge difference).
 

maretix

Member
Thank you very much for all your responses.

I use Progress 10.2b version on AIX Unix System.
CalcPrice.p is a program that execute inside it others .p
It is a 'brick' of our company's program. i have ti use it to calculate what price the company can apply to a certain customer.

I need to calculate for a customer and for 1.000.000 products.


My original program was (simple version to understand) :


FOR EACH <table products> NO-LOCK:

RUN CalcPrice .p NO-ERROR . /* Without Persistent Procedure it lasts a lot of time spending also a lot of CPU Time..

END.

So i thinked to persistent procedures ...
What i do not understand , it is how to call CalcPrice.p several time over a loop ... optimazing performance ....
In CalcPrice.p program i have no methods or internal procedure to call.... so after i do an instance of CalcPrice.p , i run the same CalcPrice because i have no internal procedure to call...
How can i do that ???
I need to create a new .p that will contain an internal procedure that will run CalcPrice.p ????
It is a company program written based on character client , no classes ...

Something like this ???

Main.p

DEFINE hproc AS HANDLE.
RUN ContainerPersistentProcedure SET PROCEDURE IN Hproc. /* CalcPrice.p is an external program that calls Others .p */

....
.....

RUN GetPrice In hproc .




ContainerPersistentProcedure.p (a new external.p to be able to call CalcPrice.p as an internal procedure)
...
...
RUN Getprice.

Procedure Getprice:

RUN CalcPrice.p NO-ERROR. /* Original program */

End Procedure.


Can is it work and obtain my goal ???
Forgive my ignorance...:)
Thanks in advance.
 

tamhas

ProgressTalk.com Sponsor
To get the benefits of PP, you are going to have to restructure CalcPrice.p so that it has a main block for all setup activity and then one or more IP which you call to get actual results. You might also have some IP which are private that are used by the public IPs to do work. This should make the whole program much more readable as a side benefit.
 

maretix

Member
To get the benefits of PP, you are going to have to restructure CalcPrice.p so that it has a main block for all setup activity and then one or more IP which you call to get actual results. You might also have some IP which are private that are used by the public IPs to do work. This should make the whole program much more readable as a side benefit.
Thank you very much TAMHAS and all of you,
I think i will do exactly what you explained me.
Thanks again.
 
Top