BASIC Efficiency Issues
  • Most efficiency issues are simply common sense.  They are equally applicable to Pick Basic and to all other programming languages.
  • In the absence of other information, the general rule is to keep the code as clean and straight forward as possible.  This will not only be generally more efficient, but will help control the maintenance and support problems of complex systems.  Most of the time (99%+) it is much better to spend your time to save a line of code altogether than to worry about the fastest instruction to use.
  • Obvious issues are to avoid redundant opens, excessive variables in pass lists, and large dynamic arrays.  On most systems, the Pick Basic compiler does not do as much to optimize code as some of the newer, more sophisticated compilers.  This means you need to pay more attention to writing clean code, and in particular, to avoiding redundant sub-expressions.   Redundant dynamic array extracts are especially poor – see the dynamic array bullet.  Moving static expressions out of loops is an easily done but often overlooked improvement.
  • Never create a hard loop.  Its detrimental effects on the machine and on other processes is hard to over estimate.  For example, if you use a LOCKED clause in record reads, the locked path MUST have an input statement or a sleep command!  Another area often creating hard loops are background batch jobs.  Ideally, they should use specific inter-process scheduling mechanisms to prevent the need for hard loops.  At the very least, there should be a significant sleep in the loop.  This should be the largest value possible and at least the expected loop time.
  • Tests show most complex programs actually read and write the same records several times!  Saving these extra reads and writes saves group and record lock issues, external bus traffic and map operations as well as CPU cycles.  Two READV's will ALWAYS be more expensive than reading the record outright. The overall performance improvements from this type of clean up can be dramatic.
  • Don't read a record if you don't need the results (yes – it really happens)!  Take advantage of naturally occurring ordering and don't read a record if you already have it read (code tables, division records, regions, company headers, etc.).  Do not use READUs if the application can infer a lock – if the system always reads an order header with a record lock before reading the order details, NO LOCKS are needed on the details!  Do not use private lock structures – the system supported routines are more robust and much more efficient.
  • Never use the form X=OCONV(ID,"Tfile;X;n;n).  This is the equivalent of a file OPEN and a READV every time its executed!  It also hides the data reference from the common file cross reference programs.
  • One of the single biggest improvements is to use static arrays in preference to dynamic arrays.  Handling strings in dynamic arrays cause the system to pass characters from the start of the string to locate the required attribute.  Even half a dozen trips through a mod-erate size string can be substantially more expensive than setting up a static array and doing a MAT read.  If the record is large or the strings are repetitively handled in loops, the improvement in overall CPU time of the program can often be more than one third!
  • Avoid EXECUTEs when simpler internal functions are available.  Using an execute "who" or "sleep" can be 20 times more expensive than the local use of "OCONV('','U50BB') or a sleep statement.  Where possible, send more than one statement to an EXECUTE.
  • You certainly should use subroutines whenever it makes sense by simplifying the design or testing, but avoid external subroutines if internal GOSUB's would do as well.  When calling an external subroutine, be sure you have properly partitioned the design so you are able to do significant work in the subroutine – the expense of a subroutine call with several passed variables can be the equivalent of several dozen in-line statements.  If possible, use unnamed common to pass the variables to subroutines.
  • Use named common sparingly – accessing a named common variable is slightly more expensive than accessing regular variables or unnamed common variables, but is worth it if it saves multiple opens, reads or writes, or evaluations of complex expressions.
  • An admittedly small, but nearly mechanical change involves being conscious of the required type of a variable.  Basic allows painless conversions from numeric data to strings data, or visa versa.  However, because these conversions happen at run-time, they are not totally cost free.  Take the time to properly specify the type of a constant expression or variable.  For example, X<I> = 5 causes the system to do a numeric to string conversion at runtime every time the expression is encountered.  Since the dynamic assignment always requires a string, the expression X<I> = "5" is measurably cheaper.
  • In the same vein, building a print line as a single statement may be slightly harder to edit than 10 or 15 lines of repetitive concatenates, but it is many times cheaper.
  • Understanding a piece of code well enough to make a fix or enhancement is a big investment of your time and energy.  Capitalize on this hard won understanding by adding (or correcting) comments and making small cleanups to some of the code.  As a rule of thumb, if you had a problem understanding the code, or your fix took longer than you thought it should, its important to use your invested time to make the situation better for the next occasion.  I'm not suggesting you disrupt your company schedules, just spent a few extra minutes to clean-up or document the worst of the situation.  Over time, you'll be amazed at how much even large systems improve.
  • Lastly, if the program is truly hopeless, please take the effort to document the problem in writing to your company's management.  It's likely that a proper fix involves a broad redesign rather than a simple patch.  Changes of this magnitude should be decided on by MIS management so they can be properly scheduled and perhaps coordinated with other program or other system changes.

  •