Menu

#11 `isrewcurr` rewrite to slow

Group Name (Dunno)
open
nobody
None
1
2023-11-12
2023-11-11
No

With
(GnuCOBOL) 3.2.0
VBISAM 2.1.1 by Ron Norman patch
The time of the rewrite function is about 1000 times that of BDB, MF C-ISAM or C native C-ISAM

Discussion

  • Juan Carlos Escartí

    Test Results

    GNUCOBOL 3.2 WITH BDB
    real 0m5,873s
    user 0m5,643s
    sys 0m0,074s

    GNUCOBOL 3.2. WITH VBISAM
    real 1m24,979s
    user 1m21,339s
    sys 0m3,608s

    MF II V 1.1 WITH C-ISAM
    real 0m3.205s
    user 0m1.564s
    sys 0m1.596s

     
  • Simon Sobisch

    Simon Sobisch - 2023-11-12

    Thank you for the test program. Can you please adjust TESTRW so that it has no screen section or any CALLs? That makes this more easy to check/debug and also removes the additional overhead from curses.

     

    Last edit: Simon Sobisch 2023-11-12
  • Simon Sobisch

    Simon Sobisch - 2023-11-12

    As 98.6 of the instructions are spent in the VBISAM function isrewcurr(), this isn't a gnucobol issue, so I've moved it to the relevant project tracker.

    Note: sources for my test taken from http://inglenet.ca/Products/GnuCOBOL/vbisam-2.2.tar.Z, run with GnuCOBOL 3.2, bot compiled with -ggdb3 -O1 .

    Also note that this bad performance is related to the many alternate keys with split keys. In other cases the performance would be better.

    I only did a minor adjustment as follows:

    vbkeysio.c (ivbkeycompare, sort_retrun): refactored for improved performance

    @juanc Please try to swap the existing ivbkeycompare function with the following and check for differences in execution time. Warning: I've not run any tests but 1 a minute program run, I even did not verify if the result is still identical, so: use with care, run at least make checkall within GnuCOBOL to verify you don't get any new errors).

    static VB_INLINE int
    sort_retrun (const short kp_type, const int ret)
    {
        if (kp_type & ISDESC) {
            return -ret;
        }
        return ret;
    }
    
    int
    ivbkeycompare (const int ihandle, const int ikeynumber, int ilength,
                   VB_UCHAR *pckey1, VB_UCHAR *pckey2)
    {
        vb_rtd_t *vb_rtd =VB_GET_RTD;
        struct keydesc  *pskeydesc;
        register int     ilengthtocompare;
        int     ipart;
    
        pskeydesc = vb_rtd->psvbfile[ihandle]->pskeydesc[ikeynumber];
        if (ilength == 0) {
            ilength = pskeydesc->k_len;
        }
        for (ipart = 0; ilength > 0 && ipart < pskeydesc->k_nparts; ipart++) {
            const struct keypart  k_part = pskeydesc->k_part[ipart];
            if (ilength >= k_part.kp_leng) {
                ilengthtocompare = k_part.kp_leng;
                ilength -= ilengthtocompare;
            } else {
                ilengthtocompare = ilength;
                ilength = 0;
            }
            switch ((k_part.kp_type & BYTEMASK) & ~ISDESC) {
                case CHARTYPE: {
                    const int   n = memcmp (pckey1, pckey2, (size_t)ilengthtocompare);
                    if (n == 0) {
                        pckey1 += ilengthtocompare;
                        pckey2 += ilengthtocompare;
    /*
                        while (ilengthtocompare--) {
                            if (*pckey1 < *pckey2) {
                                return sort_retrun (k_part.kp_type, -1);
                            }
                            if (*pckey1++ > *pckey2++) {
                                return sort_retrun (k_part.kp_type, 1);
                            }
                        }
    */
                        break;
                    } else if (n < 0) {
                        return sort_retrun (k_part.kp_type, -1);
                    } else {    /* n > 0 */
                        return sort_retrun (k_part.kp_type, 1);
                    }
                }
    
                case INTTYPE:
                    while (ilengthtocompare >= INTSIZE) {
                        const int     ivalue1 = inl_ldint (pckey1);
                        const int     ivalue2 = inl_ldint (pckey2);
                        if (ivalue1 == ivalue2) {
                            pckey1 += INTSIZE;
                            pckey2 += INTSIZE;
                            ilengthtocompare -= INTSIZE;
                        } else if (ivalue1 < ivalue2) {
                            return sort_retrun (k_part.kp_type, -1);
                        } else {    /* ivalue1 > ivalue2 */
                            return sort_retrun (k_part.kp_type, 1);
                        }
                    }
                    break;
    
                case LONGTYPE:
                    while (ilengthtocompare >= LONGSIZE) {
                        const int     lvalue1 = inl_ldlong (pckey1);
                        const int     lvalue2 = inl_ldlong (pckey2);
                        if (lvalue1 == lvalue2) {
                            pckey1 += LONGSIZE;
                            pckey2 += LONGSIZE;
                            ilengthtocompare -= LONGSIZE;
                        } else if (lvalue1 < lvalue2) {
                            return sort_retrun (k_part.kp_type, -1);
                        } else {    /* lvalue1 > lvalue2 */
                            return sort_retrun (k_part.kp_type, 1);
                        }
                    }
                    break;
    
                case QUADTYPE:
                    while (ilengthtocompare >= QUADSIZE) {
                        const off_t       tvalue1 = inl_ldquad (pckey1);
                        const off_t       tvalue2 = inl_ldquad (pckey2);
                        if (tvalue1 == tvalue2) {
                            pckey1 += QUADSIZE;
                            pckey2 += QUADSIZE;
                            ilengthtocompare -= QUADSIZE;
                        } else if (tvalue1 < tvalue2) {
                            return sort_retrun (k_part.kp_type, -1);
                        } else {  /* tvalue1 > tvalue2 */
                            return sort_retrun (k_part.kp_type, 1);
                        }
                    }
                    break;
    
                case FLOATTYPE:
                    while (ilengthtocompare >= FLOATSIZE) {
                        const float       fvalue1 = ldfloat (pckey1);
                        const float       fvalue2 = ldfloat (pckey2);
                        if (fvalue1 == fvalue2) {
                            pckey1 += FLOATSIZE;
                            pckey2 += FLOATSIZE;
                            ilengthtocompare -= FLOATSIZE;
                        } else if (fvalue1 < fvalue2) {
                            return sort_retrun (k_part.kp_type, -1);
                        } else { /* fvalue1 > fvalue2 */
                            return sort_retrun (k_part.kp_type, 1);
                        }
                    }
                    break;
    
                case DOUBLETYPE:
                    while (ilengthtocompare >= DOUBLESIZE) {
                        const double      dvalue1 = lddbl (pckey1);
                        const double      dvalue2 = lddbl (pckey2);
                        if (dvalue1 == dvalue2) {
                            pckey1 += DOUBLESIZE;
                            pckey2 += DOUBLESIZE;
                            ilengthtocompare -= DOUBLESIZE;
                        } else if (dvalue1 < dvalue2) {
                            return sort_retrun (k_part.kp_type, -1);
                        } else { /* dvalue1 > dvalue2 */
                            return sort_retrun (k_part.kp_type, 1);
                        }
                    }
                    break;
    
                default:
    #ifdef  VBDEBUG
                    fprintf (stderr, "HUGE ERROR! File %s, Line %d itype %d\n", __FILE__,
                             __LINE__, k_part.kp_type);
                    exit (1);
    #else
                    break;
    #endif
            }
        }
        return 0;
    }
    

    flamegraph generated by hotspot after the change attached (before the change ivbkeycompare() took > 60 of the process total, that is now down to 46%) .

     

    Last edit: Simon Sobisch 2023-11-12
  • Simon Sobisch

    Simon Sobisch - 2023-11-12

    Ticket moved from /p/gnucobol/bugs/930/

    • summary: VBISAM rewrite to slow --> isrewcurr rewrite to slow
    • Priority: 5 - default --> 1
     

    Last edit: Simon Sobisch 2023-11-12

Log in to post a comment.