1993.11.29 22:02 "Speedup of G4 FAX decoding?", by Craig Jackson

1993.12.01 13:30 "Re: Speedup of G4 FAX decoding?", by Karsten Spang

My profiling of G4 FAX decoding with 3.3beta2 seems to point a finger at subroutine call overhead as a significant factor using VAX C on VMS. In particular, the finddiff routine in tif_fax3.c, which is a wrapper for the findspan routine in the same file, shows up a lot in the profiling.

Has anybody considered replacing finddiff with an equivalent macro?

Both finddiff and findspan modify their arguments, so changing them into macros is not completely trivial. It is trivial, however, to move them to the top of the file, and declare them to be "inline". Use the "inline" specifier under GCC, the "#pragma inline" directive under VAXC, or whatever applies to your compiler.

If no one else does this, I will try it out (when I find the time;-)

A customer complained about execution times, so I took the time.

I changed tif_fax3.c to use inline optimization of findspan and finddiff. A test using tiffinfo -D on a "typical" (whatever that means) 6680x4691 pixels g4 compressed TIFF file took 15% less CPU time after the change under VMS using VAXC.

I have verified that gcc accepts the changes, but I have not done any performance tests.

If you know how to make other compilers perform inlining of functions please let me know. I will send out new diff's, if anybody responds to this request.

Diffs follow below.

                            Karsten
--------------------------------------------------------------------------------
E-mail: krs@kampsax.dk                                      Karsten Spang
Phone:  +45 36 77 22 23                                     Kampsax Data
Fax:    +45 36 77 03 01                                     P.O. Box 1142
                                                            DK-2650 Hvidovre
                                                            Denmark

--------------------------------------------------------------------------------
*** tif_fax3.c.orig     Wed Dec  1 13:09:55 1993
--- tif_fax3.c  Wed Dec  1 13:18:14 1993
***************
*** 57,62 ****
--- 57,179 ----
  static        int findspan(u_char**, int, int, const u_char*);
  static        int finddiff(u_char*, int, int, int);

+ /*
+  * Bit handling utilities. Moved to this spot to make gcc inline them
+  */

+ static const u_char zeroruns[256] = {
+     8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,   /* 0x00 - 0x0f */
+     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,   /* 0x10 - 0x1f */
+     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,   /* 0x20 - 0x2f */
+     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,   /* 0x30 - 0x3f */
+     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x40 - 0x4f */
+     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x50 - 0x5f */
+     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x60 - 0x6f */
+     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x70 - 0x7f */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x80 - 0x8f */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x90 - 0x9f */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xa0 - 0xaf */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xb0 - 0xbf */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xc0 - 0xcf */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xd0 - 0xdf */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xe0 - 0xef */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xf0 - 0xff */
+ };
+ static const u_char oneruns[256] = {
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x00 - 0x0f */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x10 - 0x1f */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x20 - 0x2f */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x30 - 0x3f */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x40 - 0x4f */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x50 - 0x5f */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x60 - 0x6f */
+     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x70 - 0x7f */
+     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x80 - 0x8f */
+     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x90 - 0x9f */
+     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0xa0 - 0xaf */
+     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0xb0 - 0xbf */
+     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,   /* 0xc0 - 0xcf */
+     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,   /* 0xd0 - 0xdf */
+     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,   /* 0xe0 - 0xef */
+     4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,   /* 0xf0 - 0xff */
+ };

+ #ifdef VAXC
+ #pragma inline(findspan,finddiff)
+ #endif

+ /*
+  * Find a span of ones or zeros using the supplied
+  * table.  The byte-aligned start of the bit string
+  * is supplied along with the start+end bit indices.
+  * The table gives the number of consecutive ones or
+  * zeros starting from the msb and is indexed by byte
+  * value.
+  */
+ static int
+ #ifdef __GNUC__
+ inline
+ #endif
+ findspan(u_char** bpp, int bs, int be, register const u_char* tab)
+ {
+       register u_char *bp = *bpp;
+       register int bits = be - bs;
+       register int n, span;

+       /*
+        * Check partial byte on lhs.
+        */
+       if (bits > 0 && (n = (bs & 7))) {
+               span = tab[(*bp << n) & 0xff];
+               if (span > 8-n)         /* table value too generous */
+                       span = 8-n;
+               if (span > bits)        /* constrain span to bit range */
+                       span = bits;
+               if (n+span < 8)         /* doesn't extend to edge of byte */
+                       goto done;
+               bits -= span;
+               bp++;
+       } else
+               span = 0;
+       /*
+        * Scan full bytes for all 1's or all 0's.
+        */
+       while (bits >= 8) {
+               n = tab[*bp];
+               span += n;
+               bits -= n;
+               if (n < 8)              /* end of run */
+                       goto done;
+               bp++;
+       }
+       /*
+        * Check partial byte on rhs.
+        */
+       if (bits > 0) {
+               n = tab[*bp];
+               span += (n > bits ? bits : n);
+       }
+ done:
+       *bpp = bp;
+       return (span);
+ }

+ /*
+  * Return the offset of the next bit in the range
+  * [bs..be] that is different from the specified
+  * color.  The end, be, is returned if no such bit
+  * exists.
+  */
+ static int
+ #ifdef __GNUC__
+ inline
+ #endif
+ finddiff(u_char* cp, int bs, int be, int color)
+ {
+       cp += bs >> 3;                  /* adjust byte offset */
+       return (bs + findspan(&cp, bs, be, color ? oneruns : zeroruns));
+ }

  void
  TIFFModeCCITTFax3(TIFF* tif, int isClassF)
  {
***************
*** 742,784 ****
                Fax3PutBits(tif, sp->tag == G3_1D, 1);
  }

- static const u_char zeroruns[256] = {
-     8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,   /* 0x00 - 0x0f */
-     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,   /* 0x10 - 0x1f */
-     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,   /* 0x20 - 0x2f */
-     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,   /* 0x30 - 0x3f */
-     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x40 - 0x4f */
-     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x50 - 0x5f */
-     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x60 - 0x6f */
-     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x70 - 0x7f */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x80 - 0x8f */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x90 - 0x9f */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xa0 - 0xaf */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xb0 - 0xbf */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xc0 - 0xcf */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xd0 - 0xdf */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xe0 - 0xef */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0xf0 - 0xff */
- };
- static const u_char oneruns[256] = {
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x00 - 0x0f */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x10 - 0x1f */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x20 - 0x2f */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x30 - 0x3f */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x40 - 0x4f */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x50 - 0x5f */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x60 - 0x6f */
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   /* 0x70 - 0x7f */
-     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x80 - 0x8f */
-     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0x90 - 0x9f */
-     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0xa0 - 0xaf */
-     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,   /* 0xb0 - 0xbf */
-     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,   /* 0xc0 - 0xcf */
-     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,   /* 0xd0 - 0xdf */
-     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,   /* 0xe0 - 0xef */
-     4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,   /* 0xf0 - 0xff */
- };

  /*
   * Reset encoding state at the start of a strip.
   */
--- 859,864 ----
***************
*** 985,1060 ****
                _TIFFfree(tif->tif_data);
                tif->tif_data = NULL;
        }
- }

- /*
-  * Bit handling utilities.
-  */

- /*
-  * Find a span of ones or zeros using the supplied
-  * table.  The byte-aligned start of the bit string
-  * is supplied along with the start+end bit indices.
-  * The table gives the number of consecutive ones or
-  * zeros starting from the msb and is indexed by byte
-  * value.
-  */
- static int
- findspan(u_char** bpp, int bs, int be, register const u_char* tab)
- {
-       register u_char *bp = *bpp;
-       register int bits = be - bs;
-       register int n, span;

-       /*
-        * Check partial byte on lhs.
-        */
-       if (bits > 0 && (n = (bs & 7))) {
-               span = tab[(*bp << n) & 0xff];
-               if (span > 8-n)         /* table value too generous */
-                       span = 8-n;
-               if (span > bits)        /* constrain span to bit range */
-                       span = bits;
-               if (n+span < 8)         /* doesn't extend to edge of byte */
-                       goto done;
-               bits -= span;
-               bp++;
-       } else
-               span = 0;
-       /*
-        * Scan full bytes for all 1's or all 0's.
-        */
-       while (bits >= 8) {
-               n = tab[*bp];
-               span += n;
-               bits -= n;
-               if (n < 8)              /* end of run */
-                       goto done;
-               bp++;
-       }
-       /*
-        * Check partial byte on rhs.
-        */
-       if (bits > 0) {
-               n = tab[*bp];
-               span += (n > bits ? bits : n);
-       }
- done:
-       *bpp = bp;
-       return (span);
- }

- /*
-  * Return the offset of the next bit in the range
-  * [bs..be] that is different from the specified
-  * color.  The end, be, is returned if no such bit
-  * exists.
-  */
- static int
- finddiff(u_char* cp, int bs, int be, int color)
- {
-       cp += bs >> 3;                  /* adjust byte offset */
-       return (bs + findspan(&cp, bs, be, color ? oneruns : zeroruns));
  }

  int
--- 1065,1070 ----