Here are the costs in seconds for running 100 million iterations of each op. This only really makes sense on *my* machine, but it gives you an idea of what sort of tradeoffs there are. Given that the difference between most ops is negligible, I'd suggest that a lot of work is still happening in the despatch. The script which generated this is attached. add_i 4.5 add_n 5 branch_ic 2 dec_i 4.5 dec_i_ic 4.5 dec_n 4.5 dec_n_nc 6 div_i 10.5 div_n 24.5 eq_i_ic 4.5 eq_ic_ic 4.5 eq_n_ic 5.5 eq_nc_ic 6 ge_i_ic 5.5 ge_ic_ic 5 ge_n_ic 6 ge_nc_ic 6 gt_i_ic 5 gt_ic_ic 5 gt_n_ic 5.5 gt_nc_ic 6.5 if_i_ic 5 if_n_ic 6 inc_i 2 inc_i_ic 4.5 inc_n 5 inc_n_nc 5.5 iton_n_i 6.5 le_i_ic 5 le_ic_ic 5 le_n_ic 5.5 le_nc_ic 5.5 length_i_s 6 lt_i_ic 4.5 lt_ic_ic 4.5 lt_n_ic 5 lt_nc_ic 6 mod_i 11 mul_i 5.5 mul_n 6 ne_i_ic 4.5 ne_ic_ic 4.5 ne_n_nc 5.5 ne_nc_ic 5 noop 3.5 ntoi_i_n 11.5 pushpop_i 14 pushpop_n 14 pushpop_p 14 pushpop_s 14 set_i 4.5 set_i_ic 4.5 set_n_nc 5 sub_i 5 sub_n 5 substr_s_s_i 23.5 time_i 49.5 time_n 49.5 -- Simon: `hello kitty' douche. If you are getting some and you know what hello kitty is... Well, you're an exceptionally lucky man. -- Megahal, trained on IRC.
#!/usr/bin/perl -w use strict; $/="\n-----\n"; my $loops = 100_000_000; print "Calibrating loop...\n"; my $cal = testit("",""); print "Empty loop took $cal seconds\n"; $| =1; my %cost; while (<DATA>) { chomp; my @lines = split /\n/,$_; my $name = shift @lines; print "Testing op $name..."; my $setup =""; my $loop = ""; if (($_ = shift @lines) eq "SETUP") { $setup .= $_."\n" while $_ = shift @lines and $_ ne "LOOP" } else { $loop = $_."\n"; } $loop .= join "\n", @lines; print $cost{$name} = testit($setup, $loop) - $cal; print "\n"; }; open COST, ">costmodel.tab" or die $!; for (sort keys %cost) { print COST "$_", " " x (40-length($_)), $cost{$_},"\n"; } sub testit { my ($setup, $loop) = @_; open PASM, ">cost.pasm" or die $!; unlink "cost.pbc"; print PASM <<EOF; set_i_ic I33, $loops set_i_ic I32, 0 set_i_ic I1, 0 set_i_ic I2, 1 $setup time_i I31 REDO: eq_i_ic I32, I33, DONE, NEXT NEXT: inc_i I32 # This is the main loop $loop # That was the main loop branch_ic REDO DONE: time_i I34 sub_i I34, I34, I31 print_i I34 EOF system("perl assemble.pl cost.pasm > cost.pbc"); die "Didn't assemble cleanly" unless -f "cost.pbc"; # Average runs. my $a = `./test_prog cost.pbc`; my $b = `./test_prog cost.pbc`; return ($a+$b)/2; } __DATA__ add_i add_i I1, I2, I2 ----- sub_i sub_i I1, I2, I2 ----- mul_i mul_i I1, I2, I2 ----- div_i div_i I1, I2, I2 ----- mod_i mod_i I1, I2, I2 ----- set_i set_i I1, I2 ----- set_i_ic set_i_ic I1, 1 ----- eq_i_ic eq_i_ic I1, I2, MYNEXT, MYNEXT MYNEXT: ----- eq_ic_ic eq_ic_ic I1, 1, MYNEXT, MYNEXT MYNEXT: ----- ne_i_ic ne_i_ic I1, I2, MYNEXT, MYNEXT MYNEXT: ----- ne_ic_ic ne_i_ic I1, 1, MYNEXT, MYNEXT MYNEXT: ----- lt_i_ic lt_i_ic I1, I2, MYNEXT, MYNEXT MYNEXT: ----- lt_ic_ic lt_ic_ic I1, 1, MYNEXT, MYNEXT MYNEXT: ----- le_i_ic le_i_ic I1, I2, MYNEXT, MYNEXT MYNEXT: ----- le_ic_ic le_i_ic I1, 1, MYNEXT, MYNEXT MYNEXT: ----- gt_i_ic gt_i_ic I1, I2, MYNEXT, MYNEXT MYNEXT: ----- gt_ic_ic gt_ic_ic I1, 1, MYNEXT, MYNEXT MYNEXT: ----- ge_i_ic ge_i_ic I1, I2, MYNEXT, MYNEXT MYNEXT: ----- ge_ic_ic ge_i_ic I1, 1, MYNEXT, MYNEXT MYNEXT: ----- if_i_ic if_i_ic I1, MYNEXT, MYNEXT MYNEXT: ----- time_i time_i I1 ----- branch_ic branch_ic MYNEXT MYNEXT: ----- inc_i inc_i I1 ----- inc_i_ic inc_i_ic I1, 2 ----- dec_i dec_i I1 ----- dec_i_ic dec_i_ic I1, 2 ----- add_n add_n N1, N2, N2 ----- sub_n sub_n N1, N2, N2 ----- mul_n mul_n N1, N2, N2 ----- div_n div_n N1, N2, N2 ----- set_n_nc set_n_nc N1, 1 ----- eq_n_ic eq_n_ic N1, N2, MYNEXT, MYNEXT MYNEXT: ----- eq_nc_ic eq_nc_ic N1, 1, MYNEXT, MYNEXT MYNEXT: ----- ne_n_nc ne_n_ic N1, N2, MYNEXT, MYNEXT MYNEXT: ----- ne_nc_ic ne_n_ic N1, 1, MYNEXT, MYNEXT MYNEXT: ----- lt_n_ic lt_n_ic N1, N2, MYNEXT, MYNEXT MYNEXT: ----- lt_nc_ic lt_nc_ic N1, 1, MYNEXT, MYNEXT MYNEXT: ----- le_n_ic le_n_ic N1, N2, MYNEXT, MYNEXT MYNEXT: ----- le_nc_ic le_n_ic N1, 1, MYNEXT, MYNEXT MYNEXT: ----- gt_n_ic gt_n_ic N1, N2, MYNEXT, MYNEXT MYNEXT: ----- gt_nc_ic gt_nc_ic N1, 1, MYNEXT, MYNEXT MYNEXT: ----- ge_n_ic ge_n_ic N1, N2, MYNEXT, MYNEXT MYNEXT: ----- ge_nc_ic ge_n_ic N1, 1, MYNEXT, MYNEXT MYNEXT: ----- if_n_ic if_n_ic N1, MYNEXT, MYNEXT MYNEXT: ----- time_n time_n N1 ----- inc_n inc_n N1 ----- inc_n_nc inc_n_nc N1, 2.0 ----- dec_n dec_n N1 ----- dec_n_nc dec_n_nc N1, 2.0 ----- iton_n_i iton_n_i N1, I1 ----- ntoi_i_n ntoi_i_n I1, N1 ----- pushpop_i push_i pop_i ----- pushpop_n push_n pop_n ----- pushpop_s push_s pop_s ----- pushpop_p push_p pop_p ----- length_i_s SETUP set_s_sc S1, "Hello world" LOOP length_i_s I1, S1 ----- substr_s_s_i SETUP set_s_sc S1, "Hello world" set_i_ic I1, 3 set_i_ic I2, 4 # This saves a runtime allocation set_s_sc S2, "" LOOP substr_s_s_i S2, S1, I1, I2 ----- noop noop