Other Tools
This document is unfinished - there a quite a bunch of other tools to be documented ...
Transcript: the smalltalk messages window
In smalltalk, the Transcript plays the role of a console,
where useful information is sent to. For example, the compiler
outputs progress information onto the transcript when compiling methods
from a file or from the browser.
From your programs, you can send output to the Transcript
via the messages:
Transcript show:String
Transcript showCR:String
Transcript cr
OldLauncher: a menu to launch applications and tools
The Launcher allows startup of commonly used tools and utilities.
The OldLauncher class can also be subclassed; so you can create your own
application launcher and/or add/remove entries from the default launcher.
The launcher is typically started from your "private.rc"
startup file.
- Notice:
-
The OldLauncher is obsoleted by the Launcher class, which offers much more
functionality and is easier to use.
The oldLauncher is still provided for backward compatibility (subclassed
OldLauncher used by customers to launch their application),
and for purists ;-)
Launcher: combined Launcher and Transcript tool
With versions after 2.10.5.2, a new Launcher is provided,
which combines the launcher and transcript functions in one view.
This new launcher offers pulldown menus and buttons for the most
common operations.
Additionally, the language, viewStyle and compiler settings can be set via more
convenient dialogs
(in previous versions, these had to be set by evaluating Smalltalk
expressions in a workspace or by editing the startup scripts).
As with the old launcher, this one is typically started from your "private.rc"
startup file.
NewLauncher: Launcher rewritten using GUI Painter tools
Starting with revision 3.3, the Launcher was completely rewritten,
using the new GUI-builder.
The items found in the launchers pullDown-menu
and the buttonPanel can now be changed using the convenient menu-editor.
Also, the launchers functionality was moved to an abstract generic launcher superclass,
which does not provide any GUI, but is purely functional.
This allows for future- and custom launchers to be build easily.
Workspace a view for expression evaluation
Workspaces allow smalltalk expression to be entered and evaluated.
You can also use them as scratchpads or notepads.
Beside the general text editing features, Workspaces allow for Smalltalk code to
be evaluated (interpreted); to do this, select some text which represents
a valid smalltalk expression, and use one of the following menu functions for evaluation:
- doIt - To evaluate the expression
- printIt - To evaluate the expression and paste the result
- inspectIt - To evaluate the expression and open an inspectorView on the result
- browse - To evaluate the expression and open a browser on the results classes
An ongoing expression evaluation can be interrupted by pressing CTRL-C (enters a debugger)
or aborted by pressing CTRL-Y.
Click here for a
tutorial about workspaces.
Inspector: looking into an object
Introduction
Inspectors allow looking into an object. They usually consist of
2 subviews, one showing the names (and possibly indices) of the
objects instance variables, the other showing the value of the selected
instance variable.
There are some specialized inspectors (for example: image inspectors), which
add more subviews and/or show the object additionally in a more user friendly
form.
Opening an inspector
Inspectors can be started:
- by executing:
anObject inspect
or:
anObject basicInspect
to any object.
(see below for the difference between #inspect
and #basicInspect).
- by executing:
Inspector openOn:anObject
- by using the inspectIt-menu function in any codeview.
All codeviews allow inspecting the result of an expression evaluation,
by the inspectIt menu-entry
(there is also a keyboard abbreviation, such as CMD-i available).
- by double-clicking on a name entry in an inspector
Beside the obvious behavior, there are some special situations to consider:
- inspecting large collections
If the inspected object contains a large number of indexed instance variables,
only some of these are shown in the instance variable list initially (to save
some time during startup of the inspector).
In this case, the lists popup menu will contain an entry 'show more' to
increase (double) the number of instance variables shown.
- inspecting dictionaries
The variable list shown when dictionaries are inspected will show the
dictionaries keys instead of the raw (i.e. real) instance variables.
If this is not what you are interested in, use #basicInspect:,
which will open an inspector without this behavior.
- updating after a change
To avoid overhead, inspectors do not update their list automatically.
To force an update (for example, after a collection has changed its
size) click on the self entry in the list.
This will both update the list
AND show the objects new printed representation in the value view.
Without updating, you may run into an index error (and therefore: a debugger),
if you select an entry in a collection which is no longer valid.
For example, try:
#(1 2 3) asOrderedCollection inspect
then, in the inspector, evaluate (doIt):
self grow:2
and finally click on the entry labeled '3' in the namelist.
Since the index 3 is no longer a legal one, you will run into a
debugger due to an index error.
To fix this, `continue' or `abort'
in the debugger, and force an update in the inspector by clicking on the self
entry.
- inspecting instances
Double clicking on a name/index in the instance variable list will open an
inspector on this instance variables value.
Examples (click to execute):
#('one' #two 3.0 4) inspect
#('one' #two 3.0 4) asOrderedCollection inspect
#('one' #two 3.0 4) asOrderedCollection basicInspect
( #('one' #two 3.0 4) asOrderedCollection removeFirst; yourself ) inspect
( #('one' #two 3.0 4) asOrderedCollection removeFirst; yourself ) basicInspect
(Image fromFile:'bitmaps/SBrowser.xbm') inspect
(Image fromFile:'bitmaps/SBrowser.xbm') basicInspect
(Color yellow) inspect
(Color yellow) basicInspect
(Array new:400) inspect
Inspect vs. basicInspect
Sending #basicInspect to an object will always open a
general inspector, which
shows instance variables as they are physically present in the inspected object.
In contrast, #inspect is redefined in some classes to
open an inspector showing
the logical contents.
In some collections, the physical implementation uses an
extra collection to hold the contents.
Try inspecting an (nonempty) instance of Dictionary to see the difference:
|d|
d := Dictionary new.
d at:#foo put:1.
d at:#bar put:2.
d inspect.
d basicInspect.
ProjectView: aid in managing projects
If you are working on multiple projects simultaneously,
a ProjectView can be opened for each of them. A projectView
keeps track of views which were opened under that project
and which changes where made (keeping separate changeLists).
When activated (via a click), all of the projects views will be shown,
other projects' views will be hidden.
For each project, a separate package identifier is kept, which marks
changed methods and new classes - this enables the project view, to keep
track of which code belongs to which project.
Also, separate fileOut directories can be defined per project, affecting
the systemBrowsers fileOut operations: files will be stored in the active
projects fileOut directory.
A very useful default provided by the active project is the default nameSpace;
when classes are loaded (filedIn), they will be placed there.
Thus, class packages containing conflicting (or possibily conflicting)
class names, may be loaded without danger of overwriting any existing class,
by defining a distinct namespace.
As a hint, the author uses 'ST80' whenever loading ST80 code from a
public domain archive - no more overwriting of classes like Workspace,
FileBrowser etc.
The projectViews popupMenu is:
- class documentation
opens the HTML documentation viewer on a list of all classes in
that project.
- show / hide
as described above; show or hide all of the projects views
- changes
open a changeBrowser on the changes made in that project.
- browse
open browsers on all classes and individual (spread) methods,
which were defined in the project.
- fileOut classes
fileout all classes to the projects directory.
- fileOut directory ...
change the projects directory
- repository defaults ... (only in commercial versions)
set the default package within the source repository
- package name ...
define the identifier (tag), with which all classes and methods
will be marked, while accepting within that project
- default nameSpace ...
define the nameSpace, into which classes are loaded on fileIn.
- remove package code
remove all classes and individual methods of this project from the
system
- rename project ...
give the project another name
Use with some care.
Multiple project support is experimental and not yet finished.
The changeList is not complete - only method accept is recorded.
Especially, privacy and nameSpace changes are currently not recorded.
Open a ChangesBrowser to get the full list of changes.
Process Monitor: show & manipulate smalltalk processes
This tool displays a list of active processes and their current state.
Its popupMenu allows common operations to be applied to processes.
A process monitor is a very useful tool to find (and terminate or debug) leftover
background processes - especially during program development & debugging.
The fields are:
- id - the processes ID; this number is assigned by the runtime system when
the process is created. Each process has a unique ID.
- group - the process group ID; this is empty for process group leaders and
the ID of the group leader (the creator) for other processes.
The process group allows for easy termination of some process with all of
its subprocesses.
- name - the processes name; this is provided for your convenience and has
no semantic meaning.
If no explicit name was ever given to the process, its the name and ID
of its creator with " sub" appended.
- state - the processes execution state. See definitions below.
- prio - the processes execution priority.
The priority is an integer in the range 1..31. If two or more
processes are runnable, the system selects the highest priority process
for execution.
If the process has a dynamic priority range, the range is shown behind
its current priority (which may change).
- where - the method in which the process is currently executing or
in which it was suspended (went sleeping).
The states shown are:
- run - the process is runnable (but CPU is not executing it)
- active - the CPU executes this process right now
- wait - the process is waiting on some semaphore
- ioWait - the process is waiting on a IO-semaphore
- wrapWait - the process is waiting in a blocking API call (win32 only)
- eventWait - the process is waiting on an eventQueue-semaphore
- timeWait - the process is waiting on a timer-semaphore
- suspended - the process is suspended, but not waiting on a semaphore
- stopped - manually stopped; like suspended, but will not respond to interrupts
- halted - stopped by CTRL-C (win32 only)
- light - the process has not yet started (it has no stack allocated yet)
- dead - the process has died (these are normally not shown)
The process which ran at the time of the update is marked with
an (*) character. If none is marked, the scheduler was active (or waiting
for an event).
Processes which ran during the last timeSlicing period (1/10th second) are marked
with a (+) character.
The list is updated every few seconds, so be prepared for some delayed
visibility of new processes.
A popup-menu allows some operations to be performed on a selected
process:
- inspect - opens an inspector on the selected process.
- debug - opens a debugger on the selected process.
- resume - resume execution of a suspended process
- suspend - suspend execution of the process
notice, that the process may be resumed by the system due to a timer
or I/O event.
- stop - stop execution of the process
timer or I/O events will not resume a stopped process
- abort - send an AbortSignal to the process
all processes are supposed to return to a save place (typically the
main event handling loop) when an abortSignal arrives. This can be used to
force a process "out of" a long term (or endless) computation.
- terminate - terminate the process
sends a TerminateSignal to the process; the process has a chance to
perform any cleanup actions and is then removed from the system.
- terminate group - terminate the process and all of its group members
use this to terminate a process which has created background processes.
(for example, a workspace in which subprocesses were forked)
- raise prio - raise the processes priority by one
- lower priority - lower its priority by one
By holding down the "CTRL" key while pressing the middle button,
another popupMenu is opened, which allows toggling the display details
flag.
With details on, more info is shown (which you might not be interested in).
The additional information (among others) is:
- usedStack - the size of the stack being in use by the process
- totalStack - the size of the stack as allocated for the process
This is adjusted dynamically by the runtime system.
Other items are only of interest for ST/X runtime system debugging.
Probably the most useful item found is the debug function,
which opens an inspector-like debugger on the selected process.
This may be useful if some process is waiting on
a semaphore and you want to see exactly where the wait is and how it reached
it. With the debuggers monitor option, you can even watch & see what
that process is doing !
Note:
Since at the time of the view update,
the active process is always
the process monitor itself, the distinction between run and active
states is useless here: you will always see that process as being active
in the monitors display.
This tool displays a list of semaphores, their internal count
and the list of processes on its waiting list.
This tool is useful to debug deadlock or endless-wait situations in
multithread applications.
The columns shown are:
- id - an internal id (actually, the semaphores hashKey)
- name - the semaphores userFriendly name (if it has one)
- count - the semaphores count (i.e. the number of waits that go through
without blocking)
- owner - the processId of the process which was dropping the count to
zero the last time (i.e. which got the semaphore). This id is not cleared
when the process releases the semaphore - it stays set, even if the semaphore
is actually free. I.e. it giced the ID of the current or the last owner.
- waiting processes - the number and names of process(es) waiting for the semaphore
to be signalled.
This utility displays the amount of object memory used by the system,
and displays various other statistic values.
Its popUpMenu offers functions to manually perform
either blocking- or nonBlocking background garbage collects.
Some of those functions are provided as debugging & measuring tools,
and not required by the typical user.
The numbers shown are (top to bottom):
- max - the maximum overall amount in bytes (since start of the monitor),
- tot - the current total amount of used memory (new + old + free)
- all - the current used amount of memory (new + old)
- new - the amount of newSpace used
- frl - the amount of memory in free lists (fragmented free space)
- fre - the unused portion of oldSpace (compact free space)
- old - the amount of oldSpace used
- min - the minimum overall amount (since start of the monitor)
the other numbers are less of interest to normal users, but give
some info to VM developers:
- t - the current dynamic tenureAge
- I - the internal state of the incremental garbage collector
- weak - the number of weak objects
- rem - the number of objects in the remembered list (old->new crossrefs)
- lrem - the number of contexts in the lifo list (obj->stack crossrefs)
- minSc - scavengers worst case survivor percentage
- number of scavenges since system started
- % - the fill-grade of NewSpace after the last scavenge
the graphic displays a history of the used amount. Newspace size
is shown in yellow (light grey in b&w displays),
freelistspace in green (dark grey)
and oldspace in white.
The history is updated twice a second.
Use the key-commands 'f' (for faster) and 's' (for slower) to change
the update interval.
Pressing 'r' (for reset) rescales the display.
The typical picture shown is some saw-tooth figure; memory use is usually
growing until a new-space collection reduces the amount.
The memoryMonitor also provides a popup menu for common garbage collect
operations:
- collect garbage - perform a mark&sweep oldSpace collect.
the system will be blocked while doing this.
- collect garbage & symbols - like above, but reclaim unused symbols as well.
- collect garbage & compress - perform a compressing oldSpace collect.
the system will be blocked while doing this.
- background collect - perform a non blocking mark&sweep collect.
the system will continue to react, since this collect is performed
incrementally in the background.
This is executed at low priority; if other user processes (at normal priority)
are currently running, this garbage collect may not make any progress.
- reset statistic values - clears minSc & max amount
The others submenu allows less frequently needed operations
to be invoked:
- scavenge - perform a newSpace collect
- tenure - clean the newSpace; surviving objects
are immediately tenured into the oldSpace
- hi prio incremental collect - perform a non blocking mark&sweep collect.
the system will continue to react, since this collect is performed
incrementally in the background.
In contrast to the above ("background collect"),
the incremental garbage collect is performed at high prioriy and guaranteed
to make some progress.
- cleanup memory - sends all classes a
#lowSpaceCleanup
message, to have them free any cached or buffered data.
If your classes keep any recoverable objects in classVariables (caching),
these should implement this message and release these objects there.
- flush method history - flush method history
The method history (if enabled in the launchers "source & debugger"
settings dialog) keeps previous versions of changed methods.
Over time, this may take up a lot of memory and should be flushed
periodically by selecting this menu item.
- unload autoloaded classes - unloads all classes which were autoloaded
and changes them to become autoloaded again.
Use this, to remove examples, demos and games which are no longer needed.
- compress sources
this writes out all incore method source string to a file called
st.src and replaces the in memory strings by references
into this file. This reduces memory requirements after you have changed
(or filedIn) lots of code.
Be very careful in keeping this file
intact, unchanged and in sync with images.
Since your methods sources are no longer directly
available as string objects after doing this,
your methods source is lost, if this file gets corrupted.
(However, you still have your changes file around for emergency)
Memory usage: displays memory usage by class
This utility
displays the amount of memory allocated by individual classes.
The display can be sorted by different criteria - use its popupMenu to
change this.
Since scanning the memory is a time consuming operation,
there is no automatic update of the list;
use the menus update function to manually update the display.
A memoryUsageView is useful to find memory leaks.
In Smalltalk, these are not caused by not freeing memory, but instead
by keeping references to objects in globals or class variables.
(so, if you find those leaks, dont blame it on the garbage collector;
the collector cannot free the memory as long as any reachable
reference to an object exists.)
The menu includes two very useful functions, which help in finding
those references:
- owners
which opens an
inspector on all objects owning references to instances of the
selected class
(showing the names/indices of the instance variables,
which hold a reference).
- ref chains
which displays chains of references from a global to instances of the
selected class.
Thus, if you have trouble finding out why some object is not garbage collected,
open a memory usage view, select the class and use the ref chains
menu function to find out how those instances are still references.
Notice, that the owners function will not be much of a help,
if the object in question is kept from being freed by a long
chain of references (for example, if its in a long linked list which is
anchored in a global variable).
Also notice, that the ref chains function may be very time consuming.
Event monitor displays events sent to a view
This tool is useful when keyboard mappings are changed or tested.
It outputs the
incoming event-messages on the standard output (xterm-window).
(comparable to the 'xev' XWindow utility).
To try it, open an eventMonitor, place the mouse pointer into it, and press
some key(s) on the keyboard. Watch the xterms output.
This tool displays a views widget hierarchy graphically.
When started via the launcher, a crosshair cursor is shown, and
you should click on some (smalltalk-) view on the screen.
That views widget hierarchy will then be displayed;
visible components are displayed in red color, invisible (i.e.
hidden or unmapped views) are drawn black.
The popupMenu shows various details about a selected widget
and allows further inspection.
A graphical viewTree can be opened via the launchers "tools-views"
pullDown menu; either on a single view (which is to be selected with
the mouse), or on all views.
SUnit - Unit testing framework and TestRunner GUI
This framework (-> Kent Beck, Ward Cunningham and others) allows for convenient
component testing.
This tool was ported to ST/X by Samuel Shuster and Travis Triggs - thanks to you and
all other the Camp Smalltalk freaks !
For automatic testing, testcases (subclasses of TestCase) should define a bunch of methods
named 'test*', which test various aspects of your code.
For checks, the inherited messages #assert:, #should, #shouldNot etc. should be used.
See the provided ExampleSetTest for more info on how to use this.
The TestRunner GUI interface automatically searches for all testCases as present in the system,
and offers execution via a convenient pull-down list:
After selection of the test, run its test-methods by pressing the Run-Button.
All failures will be collected and provided in the lower pull-down list for debugging.
Although simple, this is a very useful tool and we highly recommend its use -
it will make your life MUCH easier.
(please read some good book on eXtreme programming for more information).
Using the TestRunner
The TestRunner is started either by double-clicking on a TestCase class in the browser,
by evaluating:
TestRunner open.
or via the launchers "tools-SUnit" menu item.
- Refresh - Button
Press this button to update the list of offered testCases (in the TestCase-PullDown list)
(Use this after new testCases have been added, or when testCases have been filedIn/autoloaded).
- TestCase Selection - PullDown list
Select a particular TestCase to run.
- Run - Button
Executes all test* methods from the selected testCase; rememberes the results and changes the
information views background color to red, if any test failed or green, if all tests succeeded.
- ReRun Defects - Button
Re-Executes only the failed testCases from the previous run.
- RunAll - Button
Executes all testCases present in the system
- Defects - PullDown List
Displays failed testCases and allows for selective reRun with a debugger opening up at
point of failure.
- Browse - Button
Opens a SystemBrowser on the selected TestCase.
- Debug - Button
ReRun the selected failed testCase with a debugger opening up at point of failure (if it fails).
The main information windows shows progress information (while executing testCases) and the final
result. Its color is changed to yellow while executing, and back to
green (if all ok) or red if any testCase failed.
Copyright © 1995 Claus Gittinger Development & Consulting, all rights reserved
<cg@exept.de>
Doc $Revision: 1.47 $ $Date: 2001/10/16 13:49:17 $