I have not tried to disable the output in Rust, because I expect that
the compiler would then eliminate parts of the rest (Forth compilers
are not that sophisticated yet, at least not for stuff like "<# #s #>"
if the result is eventually 2DROPped),
- anton--
0.66user 0.42system 0:01.08elapsed 99%CPU fillseq (all-in-one)...
That's still a more than I expected from such a program, and I find
the high proportion of system time especially surprising, so I wanted
to check out how Forth systems compare. So I wrote a Forth program
for doing the same thing, and here are the results:
0.90user 0.00system 0:00.91elapsed 99%CPU gforth-fast
In order to check out how the Forth systems do without this system...
call overheads, I defined synonyms for TYPE, SPACE and CR that work as
noops, apart from the stack effect. So when the programs do not
output their results, the run times are:
0.68user 0.01system 0:00.70elapsed 98%CPU gforth
0.20user 0.00system 0:00.20elapsed 98%CPU lxf
0.43user 0.00system 0:00.43elapsed 98%CPU sf64
0.31user 0.00system 0:00.32elapsed 99%CPU vfx64
I would have expected the programs to spend a lot of time in division
(inside #S) and to see less performance differences between systems,
so seeing a 3.5 times speedup of lxf over gforth-fast is surprising to
me; apparently the rest costs quite a bit more than the divisions.
Some performance counter results:
3245981222 945394481 cycles
11679661274 2648084410 instructions
1391034028 447127429 branches
1521428 1243916 branch-misses
0.4 18.2 % tma_backend_bound
3.9 6.1 % tma_bad_speculation
24.6 4.3 % tma_frontend_bound
71.1 71.4 % tma_retiring
What does this say about the performance of the program with output...
enabled? If lxf used buffered I/O from glibc, it would probably need
another 0.2s (the difference between gforth-fast without and with
output), but that would still be quite fast.
(Doing buffered I/O is doable in Rust,
but takes a little more work than I want to do at the moment).
One
problem is that it has to convert the number to a string, and it has
to heap-allocate (and later free) that string.
Forth:
---------------------------------------
70 constant linelength
\ synonym type 2drop
\ synonym cr noop
\ synonym space noop
: main ( u1 -- )
dup 0= if exit then
." 0"
1 swap 1 ?do ( len )
i 0 <# #s #> rot 2dup + 1+ linelength > if ( c-addr u len )
if ( c-addr u )
cr then
tuck
else
space 1+ over + -rot then
type loop
if cr then ;
---------------------------------------------
In article <2025Nov22.094635@mips.complang.tuwien.ac.at>,
Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
<SNIP>
I have not tried to disable the output in Rust, because I expect that
the compiler would then eliminate parts of the rest (Forth compilers
are not that sophisticated yet, at least not for stuff like "<# #s #>"
if the result is eventually 2DROPped),
It is hard to see that <# #S #> could be optimised away because of side >effects in the PAD area in normal implementations.
In order to check out how the Forth systems do without this system
call overheads, I defined synonyms for TYPE, SPACE and CR that work as >>noops, apart from the stack effect. So when the programs do not
output their results, the run times are:
| Sysop: | DaiTengu |
|---|---|
| Location: | Appleton, WI |
| Users: | 1,089 |
| Nodes: | 10 (0 / 10) |
| Uptime: | 153:54:10 |
| Calls: | 13,921 |
| Calls today: | 2 |
| Files: | 187,021 |
| D/L today: |
3,760 files (944M bytes) |
| Messages: | 2,457,163 |