Installing and Using Tonic

Download

The latest Tonic distribution is v0.80. It includes support for Jini 1.2.1 and other updates as described in the HISTORY file. The first is intended for Unix/Linux, and can be unpacked with GNU 'gunzip' + 'tar', respectively, while the second can be unpacked on WinXX platforms with any unzip-compatible tool. As of release v0.80 the Tonic package will no longer be made available in the UNIX 'compress' utility format.

You will also need to install or have access to:

The latter can be found here.If your platform does not already have the necessary Java version installed you can download it from one of several locations:

Older Tonic distributions, including those which work against Jini 1.1 and earlier, can be found here. Note that while the Tonic classes have been compiled and tested several times under Windows98, the script utilities described on this site primarily support Unix/Linux. The issue of running Tonic clients on Windows and Macintosh platforms is nominally discussed below.

Configure

The steps described on the remainder of this page should take less than 15 minutes to complete (provided your system is network-enabled or at least has a properly-configured loopback/localhost mechanism). After unpacking, 'cd' into the root of the distribution and run the GNU configure script:

unix% ./configure [options]

Here's a sample invocation

unix% ./configure --with-jinidir=/nfs/jini --with-tspaces=/nfs/tspaces --prefix=/nfs/opt

which tells configure:

The configure script will emit various messages (the locations of your Jini/JavaSpaces and JDK distributions, the number of processors on your host, your internet domain, etc) and then generate configuration scripts, Makefiles, and other support files specifically customized for your site. Check the results to ensure things are in reasonable order. You generally need to run configure only once per version you download, but you may run it as many times as you wish. Use

unix% ./configure --help

to list the many other customization options that are available. Note that while technically all configure switches are optional (e.g. TSpaces is not required to use Tonic), the --with-jinidir should probably always be specified, since if Jini cannot be found automatically (perhaps because it's been installed in some non-standard location) you will not be able to use Tonic at all.

To fully clean your Tonic distribution, including removing the files generated by configure, do

unix% [g]make distclean

Build

Releases prior to v0.80 bundled pre-compiled .jar files with the Tonic distribution. While this was useful in that it did not require users to perform a build step prior to using the package, it lacked flexibility in that the Tonic utility scripts were configured to point directly to the ./lib directory of the Tonic distribution. While convenient for single-user situations, this approach does not scale well to situations involving multiple users potentially interacting with multiple distinct spaces, and did not promote customization of the Tonic runtime.

To provide greater flexibility, almost all of the Tonic utility scripts are now configurable, and support the use of a resource file for additional runtime configuration. The price of this increased flexibility, though, is that one must now explicitly build and install Tonic prior to runtime, which is done in the standard way:

unix% make

followed by

unix% make install


Unless otherwise instructed the configure script will have set the installation location used in the latter step to a standard "system" location (e.g., /usr/local/tonic) which may require root privileges for writing. As noted above, you may customize the installation location (e.g. to avoid needing root privileges) by specifying the --prefix option at configure time. While the the use of GNU make is recommended, the Tonic makefiles have also been verified portable with several other implementations of the make utility.

Start Session

Boot the space by launching the supporting JVM processes in the background:

unix% startSpace

This should emit messages that look like:

Starting HTTP server to furnish JINI/JavaSpaces class files...

						... process id is XXXXX
Starting rmid...
						... process id is XXXXX
Starting Jini lookup server ...
						... process id is XXXXX
Starting JavaSpaces ...
						... process id is XXXXX
To conserve memory Tonic launches these background processes with an initial Java heap size of 3Mb. If this conflicts with your JDK (you'll know because either startSpace or the Tonic runtime will fail), you can increase the heapsize by either using a custom Tonic resource file or by re-running configure with the heapsize option.

You can bring down the entire space (as well as any currently executing Masters and Workers) by issuing the command:

unix% stopSpace


Tuple I/O Benchmarks

If the gods are smiling upon thee you should now be able to run some JavaSpaces applications. Let's start with low-level tuple I/O. Here's how to run the NullIO benchmark, which just writes/takes empty objects to/from the space. Here we run it 5 times, each time using 100 objects.

unix% runJs NullIO 5 100

This should produce something along the lines of:
      found JavaSpaces = com.sun.jini.outrigger.SpaceProxy@1

      1.339 sec to contact space

      Size of NullIO$NullEntry as a serialized class is ~37 bytes
      Size of NullIO$NullEntry as an instantiated+serialized object is ~37 bytes
      Size of NullIO$NullEntry wrapped in a Jini/JavaSpaces Entry is ~333 bytes

      # Testing with zero-field NullEntry:

      # nobj  write   w/sec    sec/w   Kbytes/sec     take    t/sec     sec/t
      # ----  -----   -----    -----   ----------     ----    -----     -----
      100     0.971   102.9866  0.0097  33.4908       1.005   99.5025    0.01
      100     0.868   115.2074  0.0087  37.4649       1.342   74.5156    0.0134
      100     0.881   113.5074  0.0088  36.9121       0.954   104.8218    0.0095
      100     0.925   108.1081  0.0093  35.1563       0.813   123.0012    0.0081
      100     0.77    129.8701  0.0077  42.2332       0.789   126.7427    0.0079

      Mean for 100 objects:

      write: 0.883    113.2503  0.0088  36.8285
      take :                                          0.9806  101.9784    0.0098

Notice how these so-called empty objects are really not so empty when they get funneled through the space. The StringIO, ArrayIO, and Partition2D benchmarks may be run in similar fashion.

Note to Windows and Macintosh Users

Note that as of v0.51 crude DOS .bat translations of the runJs and runWorker Bourne shell scripts have been added to distribution. They should be run from the Tonic util directory within a DOS shell, and need to edited first to remove the hardcoded server name and port numbers. After this, for example,

c:\> cd tonic\util
c:\tonic\util> runJs NullIO 5 100

should produce results similar to those given above. Users with Cygwin installed should in principle be able to use the UNIX scripts as written, but this has not been verified. With the release of OS/X it should in principle be straightforward to run either client or server on the Macintosh platform, but this has also not been verified. It is hoped that these shortcomings will be rectified in the near future. Would you like to help?

Master/Worker Benchmarks

Here's a sequential computation of PI (single process, writes no tuples to the space):

unix% runJs ComputeMaster Pi
	Number of processors/tasks = 1
	Number of iterations = 100000000
	N (problem size) = 10
	Error tolerance = 1.0E-8
	Task: Pi

	Size of Pi as a serialized class is ~179 bytes
	Size of Pi as an instantiated+serialized object is ~366 bytes
	Size of Pi wrapped in a Jini/JavaSpaces Entry is ~1045 bytes

	0.0 sec to generate task(s) (sequential)
	Computing Pi task # 0

	20.709 sec Total : to strictly perform the computation
	PI is approximately 3.1415926735904267
Now let's try the same computation on the same machine, this time using two workers. One way to do this is to launch the workers in two separate windows (if you create these windows as new login processes recall that you would need to run tonic.[c]csh in each, as given above):

unix% runWorker (window 1)
unix% runWorker (window 2)

And then the master, with -P 2 indicating that two "worker processors" will be participating in the computation:

unix% runJs ComputeMaster Pi -P 2
	Number of processors/tasks = 2
	Number of iterations = 100000000
	N (problem size) = 10
	Error tolerance = 1.0E-8
	Task: Pi

	Size of Pi as a serialized class is ~179 bytes
	Size of Pi as an instantiated+serialized object is ~366 bytes
	Size of Pi wrapped in a Jini/JavaSpaces Entry is ~1045 bytes
	found JavaSpaces = com.sun.jini.outrigger.SpaceProxy@1

	1.147 sec Total : time to contact the space
	reducer: starting run ...

	0.27 sec to distribute the tasks

	ComputeMaster: got result for task #0 ...
	ComputeMaster: got result for task #1 ...

	12.815 sec to collect the tasks
	13.105 sec Total : to strictly perform the computation
	PI is approximately 3.141592673590022
Note that in this example the master, workers, and space were all run on the same host, but because it's a multiprocessor we still see a marked performance improvement. Try launching more workers (and changing -P) to see if the runtime can be reduced yet further.

All of the classes derived from Master.java can be run in like fashion. Check the source code and (somewhat-dated) class diagram to better understand the benchmark framework structure and range of optional parameters . You may also specify -h at the commandline:

unix% runJs ComputeMaster -h
	Usage: java ComputeMaster task_name [options]

	Options:

        -e     ## = error tolerance for iterative solvers
               (default = 1e-8)
	-P     ## = number of 'processors', subdivides computation into ## tasks
               (default = 1, sequential execution)
	-niter ## = number of iterations/subintervals 
               (where applicable; default value = 1e8)
	-n     ## = problem size (eg, NxN grid for Jacobi,etc)

	These case-sensitive computation names may be used:

	Pi             PI computation (default task,uses niter=1e8)
	Jacobi         naive Jacobi iterative solver
	Dynamic        dynamic compilation
	NeutronShield  neutron shielding parametric experiment
	Sieve          generate all prime numbers <= N, using a
               	       parallel Sieve of Erastosthenes
	Heat           Monte Carlo simulation of source heating
		       in an isotropic scattering medium

Dynamic Compilation

The Tonic package demonstrates a dynamic compilation technique which takes advantage of the simple, location-transparent code-delivery mechanism of JavaSpaces to give the benefit of native binary speeds while avoiding the JNI portability problems of using pre-compiled shared libraries. Let's take a light propogation simulation (based upon Tiny Monte Carlo, by Scott Prahl) as an example.

To see how long it takes to run sequentially we'll first run C code compiled with -O3 optimization (on a 440Mhz Sun Ultra 10, with 128 Mb):

unix% $Tonic/cbench/bin/heat-seq-cc -n 100000
	Scattering =   20.000/cm
	Absorption =    2.000/cm
	Photons    =   100000,          Shell thickness (microns) = 50.000

	Radius         Heat
	[microns]     [W/cm^3]

	Total run time 10.986038
Now we'll run the same algorithm on the same machine, this time with Java 1.3:

unix% runJs ComputeMaster Heat -n 100000
	Number of processors/tasks = 1
	N (problem size) = 100000
	Task: Heat

	Size of Heat as a serialized class is ~202 bytes
	Size of Heat as an instantiated+serialized object is ~382 bytes
	Size of Heat wrapped in a Jini/JavaSpaces Entry is ~832 bytes

	Scattering = 20.0/cm
	Absorption = 2.0/cm
	Photons    = 100000             Shell thickness (microns) = 50.0n
 	Radius         Heat
	[microns]     [W/cm^3]

	16.1 sec Total : to simulate 100000 photons
Notice how the sequential Java version is 47% slower than C. At first glance this may seem terrible, but relative to JDK1.2.2, which took 51 seconds (464% slower than C) to execute the same code, it's actually quite good. Let's see if we can make it faster by dividing the problem amongst 2 JavaSpaces Workers (one on the same machine, another on a machine of equal speed). Here, again, the algorithm is coded in Java:

unix% runJs ComputeMaster Heat -P 2 -n 50000
	Number of processors/tasks = 2
	N (problem size) = 50000
	Task: Heat

	ComputeMaster: got result for task #1 ...
	ComputeMaster: got result for task #0 ...

	9.142 sec Total : to strictly perform the computation
This is much faster than the sequential Java, but notice that the 2 JavaSpaces Worker processes are barely faster than the single C process. Let's try 3 Workers:

unix% runJs ComputeMaster Heat -P 3 -n 33333
	Number of processors/tasks = 3
	N (problem size) = 33333
	Task: Heat

	ComputeMaster: got result for task #2 ...
	ComputeMaster: got result for task #0 ...
	ComputeMaster: got result for task #1 ...

	6.529 sec Total : to strictly perform the computation
We now see an appreciable speedup over the C code, but are working hard to get it. In the ideal case using 3 processors would yield 3x speedup over 1 processor, but in our case we are seeing 10.98/6.529 = 1.68 speedup, or an efficiency of 1.68/3 = 56%. Now let's turn to the Tonic dynamic compilation technique to see if we increase efficiency and squeeze out more performance. In this approach the Dynamic tuples do not contain Java code, but rather C source code objects, which when extracted by a Worker will be compiled to a native binary library, loaded, and invoked through JNI.

unix% runJs ComputeMaster Dynamic -P 2 -n 50000
	Number of processors/tasks = 2
	N (problem size) = 50000
	Task: Dynamic

	Size of Dynamic as a serialized class is ~218 bytes
	Size of Dynamic as an instantiated+serialized object is ~3514 bytes
	Size of Dynamic wrapped in a Jini/JavaSpaces Entry is ~4001 bytes

	ComputeMaster: got result for task #1 ...
	ComputeMaster: got result for task #0 ...

	5.619 sec Total : to strictly perform the computation
This is considerably better, as with two processors we have a speedup of 10.98/5.62 = 1.95, or 97.5% efficiency. Thus we see that for short, compute-intensive codes the overhead of dynamically compiling to native binaries is small compared to the total algorithm computation time.

Remote Node Configuration

Tonic includes a mechanism which demonstrates how JavaSpaces can be used to simplify configuration of nodes used in a distributed computation. Look in the remnconfig directory and check the README for more information, as well as the following paper.


Valid HTML 4.01!
Last Updated: October 23, 2003
This page was created and is maintained by Michael S. Noble.