Refactoring legacy code to OOP — class/object access 5–7× slower than array

45 views
Skip to first unread message

Atul

unread,
5:13 AM (14 hours ago) 5:13 AM
to Harbour Users
Hello everyone,
I am refactoring a legacy Clipper/Harbour console application that processes DBF files and generates reports. The application uses multiple DBFs connected via primary fields. I am implementing hexagonal architecture to separate UI, core logic, and database adapter layers.

Environment:
  Harbour version : 3.0.0
  Compiler        : MinGW
  Platform        : Windows 11, 64-bit
  RDD             : DBFNTX

Previously the report processed ~4,000 records in 2 minutes using
direct DBF navigation. After refactoring to OOP class objects the
same processing now takes 14 minutes — a 7× slowdown.

The refactored code has two phases:
  Phase 1 — data collection: DBF SEEK/navigation, loads data into
             an array of class objects. All DB access is HERE only.
  Phase 2 — processing: pure in-memory loop over the object array.
             NO DBF access, NO SEEK, NO area switching.

The slowdown is entirely in Phase 2. My class has 140 DATA members.
The loop structure is Header → Detail → Sub-detail:

  FOR EACH oHdr IN aHeader       // ~1,000 records
      nn := AScan(aDetails, {|x| x:code+x:key = oHdr:code+oHdr:key })    // ~3,000 records total
      IF nn > 0
         oDtl := aDetails[nn]
         kk := AScan(aSubs, {|x| x:code+x:key = oDtl:code+oDtl:key })    // ~5,000 records total
         IF kk > 0
            oDtl := aSubs[kk]
            // read properties, compute, output
         ENDIF
      ENDIF
  NEXT

Any guidance from those who have done similar legacy refactoring
projects would be greatly appreciated.

Thank you,
Atul Parate

Francesco Perillo

unread,
7:33 AM (12 hours ago) 7:33 AM
to harbou...@googlegroups.com
Member access is slower, for sure.

Can you please post the array version?

Can you please add a member in your classes that holds code+key so that it shouldn't be calculated in the ascan?

Personally I tried to move to an OOP way of accessing dbf but I had the same problem as your, reports would be slower. One solution is to create a method to createvthe report that bypasses the oop to access data. Or reads the data in oop forms when it needs it, not everything in ram...


--
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: https://groups.google.com/group/harbour-users
---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/harbour-users/947f4824-e06d-4d4e-aa9c-5ff689cb99f0n%40googlegroups.com.

Francesco Perillo

unread,
4:57 PM (3 hours ago) 4:57 PM
to harbou...@googlegroups.com
I was having a second look at your code and I still think that using objects is not the way to go.

 Also, you are not providing informations on the relationships of the records, one-to-one, one-to-many, many-to-many... the code seems to be a one-to-one

Without more informations it is difficult to give some clues, but I ask you, out of curiosity, to change the code in this way and report if there is a speed improvement
The new code explicitely uses local variables in the aScan codeblock; I don't know if Harbour optimizes oHdr:code+oHdr:key

LOCAL cKH, cKD
   FOR EACH oHdr IN aHeader       // ~1,000 records
      cKH := oHdr:code + oHdr:key
      nn := AScan(aDetails, {|x| x:code+x:key = cKH })    // ~3,000 records total

      IF nn > 0
         oDtl := aDetails[nn]
         cKD := oDtl:code + oDtl:key
         kk := AScan(aSubs, {|x| x:code+x:key = cKD })    // ~5,000 records total

Nenad Batoćanin

unread,
6:20 PM (1 hour ago) 6:20 PM
to harbou...@googlegroups.com

Hi!

I think AScan does a simple sequential search, so it can't be as fast as index search. Perhaps a replacement for AScan could be made that uses a memory table and a seek search?

 

Regards, NB

Reply all
Reply to author
Forward
0 new messages