Erik Roijackers writes in his e-mail message of 1994/03/23
To be able to call an external executable, it's necessary to write
information to a file. As far as I know, GAP offers the functions
PrintTo and AppendTo. These functions both open a file, write the
information and close it again (am I right?) So when the function
AppendTo is used within a loop, writing in each cycle a small amount
of information, the file is opened and closed again very often,
consuming a huge amount of time.
This is correct. It is just barely tolerable under UNIX. Under TOS (on
the Atari ST), it was impossible, because seeking to the end of the file
took time proportional to the size of a file. So writing a file with <n>
lines took time <n>^2. I don't now whether this is true under DOS.
Is there a way to open a file once, write all the information using
a loop, and close it again?
Hmm, yes and no. In C you open a file, obtain a file pointer, and then
use this to write to the file. Something like this is not possible in
GAP. That means you *cannot* write something like
file := OutputFile( "erwin" ); for i in [1..100] do PrintTo( file, Size( group[i] ), "\n" ); od; CloseFile( file );
We plan something like this, but not for the immediate future.
But there is a hack, which may solve your problem. What you can do, is
to put your loop in a simple function. Then you call this function
from 'PrintTo'. I.e., do the following
Dummy := function () for i in [1..100] do Print( Size( group[i] ), "\n" ); od; end; PrintTo( "erwin", Dummy() );
This makes use of the fact that when the arguments to 'PrintTo' are
evaluated the current output file is the one opened by 'PrintTo', so
everything that would usually go to '*stdout*' (i.e., the screen) is
written to the file.
This doesn't solve all problems, because you cannot interact with GAP
while the output is computed and written to the file, but in many cases
this is sufficient.
I have thought of using strings. First, all the information is stored
in a string (using Concatenation), after which the whole string is
written to a file using PrintTo. It turns out that, at least when
working under DOS, this is even slower than the first option.
In GAP 3.3 'Concatenation' has a ``small'' problem. It creates the
output list as a list of characters (with each character taking 4 bytes)
instead of as a string. So the reason why this is slower is probably
because the string becomes so large that GAP has to do many garbage
You might want to try something like the following code.
cache := ""; for i in [1..100] do Append( cache, String( Size( group[i] ) ), "\n" ); if 8192 < Length(cache) then AppendTo( "erwin", cache ); cache := ""; fi; od;
Hope this helps, Martin.
-- .- .-. - .. -. .-.. --- ...- . ... .- -. -. .. -.- .- Martin Sch"onert, Martin.Schoenert@Math.RWTH-Aachen.DE, +49 241 804551 Lehrstuhl D f"ur Mathematik, Templergraben 64, RWTH, 52056 Aachen, Germany