[net.micro.mac] LighspeedC -- A Review

matthews@harvard.UUCP (Jim Matthews) (04/09/86)

	There have been a couple of postings about the new LightspeedC
compiler, and since I recently ported a large (2200 line) program from
Aztec to that environment, I figured that the net might be interested in
my reaction.  I had been using Aztec for about a year, and my familiarity
with Unix-style utilities and the speed of the Aztec compiler made me
very satisfied.  One week of Lightspeed has convinced me to switch: the
environment is superior, both in design and execution, and the compiler
brings new meaning to the word "fast."  I have some benchmarks below, but
they only tell part of the story.  The best part of Lightspeed is its
"feel" -- a whole range of features make it effortless to use and seemingly
even faster than the numbers would indicate.

Environment
===========
	Lightspeed is one big application, about 170k on the disk, and
requires 512k to run.  The compiler deals with programming tasks using
a data structure called the project.  Projects are basically lists of source
files and libraries included in the program.  A window with the names
of these files is always on the screen.  The visual representation of
the project makes some tasks more natural, as well as fast.  The
segmentation, if any, of the program is represented by the grouping of
the names in the window: to change it you just drag them around.  This
is much nicer than long linker commands.  To edit a source file you 
just double-click on a name -- avoiding both the typing of Aztec and the
SFGetFile dialog of other systems.  The project also contains the object
code produced by compiles (so no .o files) and other information to speed
development.  Make dependencies are generated automatically, i.e. it checks
source files for #includes and keeps track of when you change what.  This
isn't as powerful as Unix make, but it's good enough for most tasks and
best of all, it's totally transparent.  One cost of using the project
format is disk space: the project file for my 76k program totaled over
200k; by contrast, the .o files produced by Aztec for the same program 
totaled 86k.
	The editor is included in the single application: it is comparable
to MDS Edit, with the one significant plus of multi-file search.  This
eliminates much, though not all, of the need for grep.  The integration
between the compiler and editor is very close.  When the compiler finds
an error, you are popped into the editor at the line of the error.  
Compiling open files takes into account changes since your last save
and the Make utility marks the file as not compiled if you then quit
without saving changes.  The editor is quick with scrolling, does not
mess up with large cuts and pastes, and handles at least a dozen open
files.  The one drawback to the close integration of the system is that
you could not easily use another editor if you wanted.  Fortunately, the
included editor is good enough to diminish that problem.
	Programs under development can be run from within Lightspeed,
through some sort of executive.  The program run is real machine code,
and runs as fast as a stand-alone version, but when you quit you return
to Lightspeed with your project still open.  To build a stand-alone
application file takes a little while (for my program, 1 minute), and
yields a standard Mac application.

Speed
=====
	Think is really pushing the speed of the compiler, and rightly
so:  while not quite as impressive as those advertised by Think (reasons
below), my benchmark figures essentially confirm the hype.  Here's what
I got compiling a 2200 line program, broken into 16 source files:

Configuration: 1Mbyte Mac Plus, with one 800k disk drive and one 300k
Ram disk.  In both cases, all system files, source, and libraries were
on the floppy, include files and the compiler/editor/linker were on
the ram disk.

Times are in seconds, turnaround refers to the time necessary to recompile,
link, and run the program after changing one typical source file.

			Aztec ver. 1.06g	LighspeedC Beta

compile all files:	1320			550
link/run:		127			26
turnaround:		258			76
code size in bytes:	70792			76860

	This benchmark may or may not be typical.  I believe that on
a hard disk system, or if the source and project files were on ram-disks,
Lightspeed's edge in compile speed would be even greater.  Most of the
time cited above was spent reading source and writing output to a slow
floppy: the actual compilation is over 250 lines/second (as displayed
by their line counter).  Think claims that it takes 2 minutes to recompile
Lightspeed in itself (1 Mbyte source) on ram disks, and I believe it.
On the other hand, using faster io devices would help Aztec in the link
comparison, since Lightspeed links in ram (for my program, in 1.5 seconds!).
As for code size, I think that the difference may be due to Lightspeed linking
in more stdio code than I need: I'll look into that when I get the release
version with source for libraries.
	So how does Lightspeed do it?  There are a number of reasons.  Since
it's one program, it doesn't have to repeatedly load the compiler.  Most
of the linking is taken care of at compile time (the project document makes
a global symbol table possible) and libraries are linked only when you add
them to the project, not at every make (which makes sense, as they probably
didn't change).  The compiler does everything in ram, with no temp files,
and I'm sure that helps a lot.  Also, there is no cascading error recovery--
the first error sends you back to the editor -- although I don't think that
won them a lot of speed.  On the other hand, the compiler checks for the
number of arguments to toolbox calls, does all the pre-linking, and still
beats Aztec hands down.  So it's very fast, but they seem to have made it
fast the old-fashioned way: painstaking optimization.
	The best thing about Lightspeed's speed is the way it changes your
work habits.  With Aztec I was loath to recompile the program with just
a single change, and having to alter a global include file (and thus
trigger re-compilation of every source file) was a prospect to be met
with dread.  Lightspeed makes it easy to make small changes and then see
what happens.  There's even a "Check Syntax" option that rivals the speed
of an interpreter (since it doesn't write output) making it easy to check
your work during a long type-in session.

Bugs
====
	Alas, there are always bugs.  One that I found is particularly
insidious for programs using floating-point, and apparently was not
fixed before shipping.  An error in the way casted expressions are
processed results in the following:

#define CONSTANT any-integer

	int foo;

	if ((double)foo == (double)(foo-CONSTANT))
		printf("Bug!");

printing out a message.  The bug manifests itself with implicit casts
also -- x/foo evaluates to the same thing as x/(foo-CONSTANT), where
x is a double.  This bug is serious, and Think was very attentive when
I called it in.  A week later, however, I called back and it hadn't
been fixed; meanwhile the compiler is shipping.  Anyone contemplating 
using Lightspeed for floating point should be aware of the problem, 
and perhaps wait for an update.  The work-around is to cast the int 
to a double before the arithmetic, a small loss in performance and 
a large loss in programmer convenience.  I'm still looking
for the last occurances of such expressions in my code.

Portability
===========
	Lightspeed handles standard K&R C, with the following differences/
features of note:

	Structure passing by values
	Argument # checking on toolbox calls
	No inline assembly -- must link in assembler output separately
	"pascal" keyword for pascal-style routines (just like Aztec)
	Explicit string conversion with CtoPstr and PtoCstr (like Aztec)
	16 bit ints, 32 bit longs and floats, 80 bit doubles (uses SANE)

	I ported my program in two evenings with occasional glances at
the documentation, all the while learning how to use the Lightspeed system.
The biggest hassles were renaming include files and dealing with points.
Aztec provides a macro to pass points to LineTo and MoveTo (for example)
by casting them to a long.  Since Lightspeed checks number of arguments,
it had to be replaced with a macro that separates a point into its 
structure elements.  The documentation is written toward users of other
Mac C compilers (Consulair, Megamax, and Aztec) and points out many of
the differences.  All in all, the manual looks good although I didn't need
to look at it much.

	All in all, I think that Lightspeed is simultaneously the cheapest
and best Mac C compiler available.  Think has to fix the floating point
bug, and it would be nice if they provided a means of converting project
files to other formats (there is an MDS => Lightspeed conversion utility)
but otherwise it looks great.  If the advertised Quicksilver Pascal compiler
uses the same technology, Apple's Workshop could have serious competition
before it's even released.

Jim Matthews
matthews@harvard

The above views are mine, and may or may not reflect those of my employer
and Harvard University.

I'm sure that LightspeedC and Quicksilver are trademarks of Think Technologies,
that Aztec is a trademark of Manx Software, and that MDS is a trademark
of Apple Computer Corporation.

db@cbosgd.UUCP (J. Muir) (04/10/86)

In article <848@harvard.UUCP> matthews@harvard.UUCP (Jim Matthews) writes:
>
>	There have been a couple of postings about the new LightspeedC
>compiler, and since I recently ported a large (2200 line) program from
>Aztec to that environment, I figured that the net might be interested in
>my reaction.
> :
>To edit a source file you 
>just double-click on a name -- avoiding both the typing of Aztec and the
>SFGetFile dialog of other systems.

Minor point, but: Aztec 1.06g (which the author later mentions using for his
comparisions) has the "compromise" menu-bar/command-line user interface in its
shell.  If the current directory has any .c files in it, you get Source and
Compile menus added to the bar.  You can then put a check next to the source
file of interest and edit, compile, assemble, link, and/or execute by simply
selecting the appropriate item on the Compile menu.  There are also Compile
options for automatic sequences.  This is much nicer than having to type
commands to the shell (especially without a history mechanism) but it's a
little bizarre to watch.

This scheme works best for relatively small applications consisting of a
single source file.  If you need link options you can set them once using
the LFLAGS environment variable.  Similarly, I set the environment so the
edit item uses the name "vi" for the editor (Z so renamed to avoid typing
frustrations; you can use that to get MDS Edit or whatever editor you use).
I believe FLAGS variables also exist for the compiler and assembler.

For larger applications, you'd want to use the Aztec make facility, which
I haven't used myself because I haven't written any large applications, nor
am I anxious to plunge into makefile-writing (I sure hope New Make catches
on and Macintosh C packages pick up its makefile style).

Dave Bursik/..cbosgd!db