From a244cc57a5a60467fb51124770dfdc87a192c512 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 16 Nov 2023 15:49:23 -0500 Subject: [PATCH 1/6] vere: adds benchmark for opcode 10 --- pkg/vere/benchmarks.c | 59 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/pkg/vere/benchmarks.c b/pkg/vere/benchmarks.c index 91f3bc4ab1..a9215cf864 100644 --- a/pkg/vere/benchmarks.c +++ b/pkg/vere/benchmarks.c @@ -1,6 +1,7 @@ /// @file #include "noun.h" +#include "jets/q.h" #include "ur.h" #include "vere.h" @@ -387,6 +388,63 @@ _cue_soft_bench(void) u3z(vat); } +static void +_edit_bench_impl(c3_w max_w) +{ + u3_assert( max_w && (c3y == u3a_is_cat(max_w)) ); + + c3_w* axe_w = c3_calloc(((max_w + 31) >> 5) << 2); + c3_w bit_w; + u3_noun lit = u3qb_reap(max_w, 1); + u3_noun axe; + + axe_w[0] = bit_w = 2; + + do { + axe = u3i_words((bit_w + 31) >> 5, axe_w); + lit = u3i_edit(lit, axe, 2); + u3z(axe); + + axe_w[bit_w >> 5] |= (c3_w)1 << (bit_w & 31); + bit_w++; + } + while ( bit_w <= max_w ); + + u3z(lit); + c3_free(axe_w); +} + +static void +_edit_bench(void) +{ + struct timeval b4, f2, d0; + c3_w mil_w; + + fprintf(stderr, "\r\nopcode 10 microbenchmark:\r\n"); + + { + gettimeofday(&b4, 0); + + _edit_bench_impl(1000); + + gettimeofday(&f2, 0); + timersub(&f2, &b4, &d0); + mil_w = (d0.tv_sec * 1000) + (d0.tv_usec / 1000); + fprintf(stderr, " opcode 10 1k list: %u ms\r\n", mil_w); + } + + { + gettimeofday(&b4, 0); + + _edit_bench_impl(10000); + + gettimeofday(&f2, 0); + timersub(&f2, &b4, &d0); + mil_w = (d0.tv_sec * 1000) + (d0.tv_usec / 1000); + fprintf(stderr, " opcode 10 10k list: %u ms\r\n", mil_w); + } +} + /* main(): run all benchmarks */ int @@ -397,6 +455,7 @@ main(int argc, char* argv[]) _jam_bench(); _cue_bench(); _cue_soft_bench(); + _edit_bench(); // GC // From a6debdb0940334ce313ae73d8eb177e6a415a128 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 16 Nov 2023 15:52:11 -0500 Subject: [PATCH 2/6] TMP remove mutation optimization from u3i_edit() --- pkg/noun/imprison.c | 116 ++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/pkg/noun/imprison.c b/pkg/noun/imprison.c index 143878e48e..a605a906fd 100644 --- a/pkg/noun/imprison.c +++ b/pkg/noun/imprison.c @@ -661,65 +661,65 @@ _edit(u3_noun big, u3_noun axe, u3_noun som) static u3_noun _edit_or_mutate_cat(u3_noun, c3_l, u3_noun); static u3_noun _edit_or_mutate(u3_noun, u3_noun, u3_noun); -static void -_mutate_cat(u3_noun big, c3_l axe_l, u3_noun som) -{ - if ( c3n == u3du(big) ) { - u3m_bail(c3__exit); - } - else { - u3a_cell* cel_u = (void*) u3a_to_ptr(big); - switch ( axe_l ) { - case 2: - u3z(cel_u->hed); - cel_u->hed = som; - break; - case 3: - u3z(cel_u->tel); - cel_u->tel = som; - break; - default: { - u3_noun* tar = ( 2 == u3x_cap(axe_l) ) - ? &(cel_u->hed) - : &(cel_u->tel); - *tar = _edit_or_mutate_cat(*tar, u3x_mas(axe_l), som); - } - } - cel_u->mug_w = 0; - } -} - -static void -_mutate(u3_noun big, u3_noun axe, u3_noun som) -{ - if ( c3y == u3a_is_cat(axe) ) { - _mutate_cat(big, (c3_l) axe, som); - } - else if ( c3n == u3du(big) ) { - u3m_bail(c3__exit); - } - else { - u3a_cell* cel_u = (void*) u3a_to_ptr(big); - u3_noun mor = u3qc_mas(axe); - u3_noun* tar = ( 2 == u3qc_cap(axe) ) - ? &(cel_u->hed) - : &(cel_u->tel); - *tar = _edit_or_mutate(*tar, mor, som); - cel_u->mug_w = 0; - u3z(mor); - } -} +// static void +// _mutate_cat(u3_noun big, c3_l axe_l, u3_noun som) +// { +// if ( c3n == u3du(big) ) { +// u3m_bail(c3__exit); +// } +// else { +// u3a_cell* cel_u = (void*) u3a_to_ptr(big); +// switch ( axe_l ) { +// case 2: +// u3z(cel_u->hed); +// cel_u->hed = som; +// break; +// case 3: +// u3z(cel_u->tel); +// cel_u->tel = som; +// break; +// default: { +// u3_noun* tar = ( 2 == u3x_cap(axe_l) ) +// ? &(cel_u->hed) +// : &(cel_u->tel); +// *tar = _edit_or_mutate_cat(*tar, u3x_mas(axe_l), som); +// } +// } +// cel_u->mug_w = 0; +// } +// } + +// static void +// _mutate(u3_noun big, u3_noun axe, u3_noun som) +// { +// if ( c3y == u3a_is_cat(axe) ) { +// _mutate_cat(big, (c3_l) axe, som); +// } +// else if ( c3n == u3du(big) ) { +// u3m_bail(c3__exit); +// } +// else { +// u3a_cell* cel_u = (void*) u3a_to_ptr(big); +// u3_noun mor = u3qc_mas(axe); +// u3_noun* tar = ( 2 == u3qc_cap(axe) ) +// ? &(cel_u->hed) +// : &(cel_u->tel); +// *tar = _edit_or_mutate(*tar, mor, som); +// cel_u->mug_w = 0; +// u3z(mor); +// } +// } static u3_noun _edit_or_mutate_cat(u3_noun big, c3_l axe_l, u3_noun som) { - if ( c3y == u3a_is_mutable(u3R, big) ) { - _mutate_cat(big, axe_l, som); - return big; - } - else { + // if ( c3y == u3a_is_mutable(u3R, big) ) { + // _mutate_cat(big, axe_l, som); + // return big; + // } + // else { return _edit_cat(big, axe_l, som); - } + // } } static u3_noun @@ -728,10 +728,10 @@ _edit_or_mutate(u3_noun big, u3_noun axe, u3_noun som) if ( c3y == u3a_is_cat(axe) ) { return _edit_or_mutate_cat(big, (c3_l) axe, som); } - else if ( c3y == u3a_is_mutable(u3R, big) ) { - _mutate(big, axe, som); - return big; - } + // else if ( c3y == u3a_is_mutable(u3R, big) ) { + // _mutate(big, axe, som); + // return big; + // } else { return _edit(big, axe, som); } From acd4a94a473b73d1c54de0e8b50910c6db243381 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Thu, 16 Nov 2023 15:52:46 -0500 Subject: [PATCH 3/6] Revert "TMP remove mutation optimization from u3i_edit()" This reverts commit a6debdb0940334ce313ae73d8eb177e6a415a128. --- pkg/noun/imprison.c | 116 ++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/pkg/noun/imprison.c b/pkg/noun/imprison.c index a605a906fd..143878e48e 100644 --- a/pkg/noun/imprison.c +++ b/pkg/noun/imprison.c @@ -661,65 +661,65 @@ _edit(u3_noun big, u3_noun axe, u3_noun som) static u3_noun _edit_or_mutate_cat(u3_noun, c3_l, u3_noun); static u3_noun _edit_or_mutate(u3_noun, u3_noun, u3_noun); -// static void -// _mutate_cat(u3_noun big, c3_l axe_l, u3_noun som) -// { -// if ( c3n == u3du(big) ) { -// u3m_bail(c3__exit); -// } -// else { -// u3a_cell* cel_u = (void*) u3a_to_ptr(big); -// switch ( axe_l ) { -// case 2: -// u3z(cel_u->hed); -// cel_u->hed = som; -// break; -// case 3: -// u3z(cel_u->tel); -// cel_u->tel = som; -// break; -// default: { -// u3_noun* tar = ( 2 == u3x_cap(axe_l) ) -// ? &(cel_u->hed) -// : &(cel_u->tel); -// *tar = _edit_or_mutate_cat(*tar, u3x_mas(axe_l), som); -// } -// } -// cel_u->mug_w = 0; -// } -// } - -// static void -// _mutate(u3_noun big, u3_noun axe, u3_noun som) -// { -// if ( c3y == u3a_is_cat(axe) ) { -// _mutate_cat(big, (c3_l) axe, som); -// } -// else if ( c3n == u3du(big) ) { -// u3m_bail(c3__exit); -// } -// else { -// u3a_cell* cel_u = (void*) u3a_to_ptr(big); -// u3_noun mor = u3qc_mas(axe); -// u3_noun* tar = ( 2 == u3qc_cap(axe) ) -// ? &(cel_u->hed) -// : &(cel_u->tel); -// *tar = _edit_or_mutate(*tar, mor, som); -// cel_u->mug_w = 0; -// u3z(mor); -// } -// } +static void +_mutate_cat(u3_noun big, c3_l axe_l, u3_noun som) +{ + if ( c3n == u3du(big) ) { + u3m_bail(c3__exit); + } + else { + u3a_cell* cel_u = (void*) u3a_to_ptr(big); + switch ( axe_l ) { + case 2: + u3z(cel_u->hed); + cel_u->hed = som; + break; + case 3: + u3z(cel_u->tel); + cel_u->tel = som; + break; + default: { + u3_noun* tar = ( 2 == u3x_cap(axe_l) ) + ? &(cel_u->hed) + : &(cel_u->tel); + *tar = _edit_or_mutate_cat(*tar, u3x_mas(axe_l), som); + } + } + cel_u->mug_w = 0; + } +} + +static void +_mutate(u3_noun big, u3_noun axe, u3_noun som) +{ + if ( c3y == u3a_is_cat(axe) ) { + _mutate_cat(big, (c3_l) axe, som); + } + else if ( c3n == u3du(big) ) { + u3m_bail(c3__exit); + } + else { + u3a_cell* cel_u = (void*) u3a_to_ptr(big); + u3_noun mor = u3qc_mas(axe); + u3_noun* tar = ( 2 == u3qc_cap(axe) ) + ? &(cel_u->hed) + : &(cel_u->tel); + *tar = _edit_or_mutate(*tar, mor, som); + cel_u->mug_w = 0; + u3z(mor); + } +} static u3_noun _edit_or_mutate_cat(u3_noun big, c3_l axe_l, u3_noun som) { - // if ( c3y == u3a_is_mutable(u3R, big) ) { - // _mutate_cat(big, axe_l, som); - // return big; - // } - // else { + if ( c3y == u3a_is_mutable(u3R, big) ) { + _mutate_cat(big, axe_l, som); + return big; + } + else { return _edit_cat(big, axe_l, som); - // } + } } static u3_noun @@ -728,10 +728,10 @@ _edit_or_mutate(u3_noun big, u3_noun axe, u3_noun som) if ( c3y == u3a_is_cat(axe) ) { return _edit_or_mutate_cat(big, (c3_l) axe, som); } - // else if ( c3y == u3a_is_mutable(u3R, big) ) { - // _mutate(big, axe, som); - // return big; - // } + else if ( c3y == u3a_is_mutable(u3R, big) ) { + _mutate(big, axe, som); + return big; + } else { return _edit(big, axe, som); } From d6988e6f931cfce669ac5542b711f4f2f6937d6f Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 16 Sep 2022 19:19:39 -0400 Subject: [PATCH 4/6] u3: rewrites u3i_edit into a loop (tail recursion modulo cons) --- pkg/noun/imprison.c | 190 +++++++++++++------------------------------- 1 file changed, 56 insertions(+), 134 deletions(-) diff --git a/pkg/noun/imprison.c b/pkg/noun/imprison.c index 143878e48e..530afe47a0 100644 --- a/pkg/noun/imprison.c +++ b/pkg/noun/imprison.c @@ -610,133 +610,6 @@ u3i_list(u3_weak som, ...) return u3kb_flop(lit); } -static u3_noun -_edit_cat(u3_noun big, c3_l axe_l, u3_noun som) -{ - if ( c3n == u3du(big) ) { - return u3m_bail(c3__exit); - } - else { - u3_noun pro; - switch ( axe_l ) { - case 2: - pro = u3nc(som, u3k(u3t(big))); - break; - case 3: - pro = u3nc(u3k(u3h(big)), som); - break; - default: { - c3_l mor_l = u3x_mas(axe_l); - pro = ( 2 == u3x_cap(axe_l) ) - ? u3nc(_edit_cat(u3k(u3h(big)), mor_l, som), u3k(u3t(big))) - : u3nc(u3k(u3h(big)), _edit_cat(u3k(u3t(big)), mor_l, som)); - break; - } - } - u3z(big); - return pro; - } -} - -static u3_noun -_edit(u3_noun big, u3_noun axe, u3_noun som) -{ - if ( c3y == u3a_is_cat(axe) ) { - return _edit_cat(big, (c3_l) axe, som); - } - else if ( c3n == u3du(big) ) { - return u3m_bail(c3__exit); - } - else { - u3_noun mor = u3qc_mas(axe), - pro = ( 2 == u3qc_cap(axe) ) - ? u3nc(_edit(u3k(u3h(big)), mor, som), u3k(u3t(big))) - : u3nc(u3k(u3h(big)), _edit(u3k(u3t(big)), mor, som)); - u3z(mor); - u3z(big); - return pro; - } -} - -static u3_noun _edit_or_mutate_cat(u3_noun, c3_l, u3_noun); -static u3_noun _edit_or_mutate(u3_noun, u3_noun, u3_noun); - -static void -_mutate_cat(u3_noun big, c3_l axe_l, u3_noun som) -{ - if ( c3n == u3du(big) ) { - u3m_bail(c3__exit); - } - else { - u3a_cell* cel_u = (void*) u3a_to_ptr(big); - switch ( axe_l ) { - case 2: - u3z(cel_u->hed); - cel_u->hed = som; - break; - case 3: - u3z(cel_u->tel); - cel_u->tel = som; - break; - default: { - u3_noun* tar = ( 2 == u3x_cap(axe_l) ) - ? &(cel_u->hed) - : &(cel_u->tel); - *tar = _edit_or_mutate_cat(*tar, u3x_mas(axe_l), som); - } - } - cel_u->mug_w = 0; - } -} - -static void -_mutate(u3_noun big, u3_noun axe, u3_noun som) -{ - if ( c3y == u3a_is_cat(axe) ) { - _mutate_cat(big, (c3_l) axe, som); - } - else if ( c3n == u3du(big) ) { - u3m_bail(c3__exit); - } - else { - u3a_cell* cel_u = (void*) u3a_to_ptr(big); - u3_noun mor = u3qc_mas(axe); - u3_noun* tar = ( 2 == u3qc_cap(axe) ) - ? &(cel_u->hed) - : &(cel_u->tel); - *tar = _edit_or_mutate(*tar, mor, som); - cel_u->mug_w = 0; - u3z(mor); - } -} - -static u3_noun -_edit_or_mutate_cat(u3_noun big, c3_l axe_l, u3_noun som) -{ - if ( c3y == u3a_is_mutable(u3R, big) ) { - _mutate_cat(big, axe_l, som); - return big; - } - else { - return _edit_cat(big, axe_l, som); - } -} - -static u3_noun -_edit_or_mutate(u3_noun big, u3_noun axe, u3_noun som) -{ - if ( c3y == u3a_is_cat(axe) ) { - return _edit_or_mutate_cat(big, (c3_l) axe, som); - } - else if ( c3y == u3a_is_mutable(u3R, big) ) { - _mutate(big, axe, som); - return big; - } - else { - return _edit(big, axe, som); - } -} - /* u3i_edit(): ** ** Mutate `big` at axis `axe` with new value `som`. @@ -745,15 +618,64 @@ _edit_or_mutate(u3_noun big, u3_noun axe, u3_noun som) u3_noun u3i_edit(u3_noun big, u3_noun axe, u3_noun som) { + u3_noun pro; + u3_noun* out = &pro; + switch ( axe ) { - case 0: - return u3m_bail(c3__exit); - case 1: - u3z(big); - return som; - default: - return _edit_or_mutate(big, axe, som); + case 0: return u3m_bail(c3__exit); + case 1: break; + + default: { + c3_w dep_w = u3r_met(0, u3x_atom(axe)) - 2; + + do { + u3a_cell* big_u = u3a_to_ptr(big); + const c3_y bit_y = u3r_bit(dep_w, axe); + + if ( c3n == u3a_is_cell(big) ) { + return u3m_bail(c3__exit); + } + else if ( c3y == u3a_is_mutable(u3R, big) ) { + *out = big; + + if ( !bit_y ) { + out = &(big_u->hed); + } + else { + out = &(big_u->tel); + } + + big = *out; + big_u->mug_w = 0; + } + else { + u3_noun old = big; + u3_noun* hed; + u3_noun* tel; + + *out = u3i_defcons(&hed, &tel); + + if ( !bit_y ) { + out = hed; + big = u3k(big_u->hed); + *tel = u3k(big_u->tel); + } + else { + out = tel; + big = u3k(big_u->tel); + *hed = u3k(big_u->hed); + } + + u3z(old); + } + } + while ( dep_w-- ); + } } + + u3z(big); + *out = som; + return pro; } /* u3i_molt(): From fa84fd88e80829cd0ae4da8b38eb6bd06f36e517 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 16 Sep 2022 19:49:36 -0400 Subject: [PATCH 5/6] u3: further optimizes u3i_edit, removing head/tail branches --- pkg/noun/imprison.c | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/pkg/noun/imprison.c b/pkg/noun/imprison.c index 530afe47a0..7e42d331b5 100644 --- a/pkg/noun/imprison.c +++ b/pkg/noun/imprison.c @@ -630,6 +630,7 @@ u3i_edit(u3_noun big, u3_noun axe, u3_noun som) do { u3a_cell* big_u = u3a_to_ptr(big); + u3_noun* old = (u3_noun*)&(big_u->hed); const c3_y bit_y = u3r_bit(dep_w, axe); if ( c3n == u3a_is_cell(big) ) { @@ -637,36 +638,20 @@ u3i_edit(u3_noun big, u3_noun axe, u3_noun som) } else if ( c3y == u3a_is_mutable(u3R, big) ) { *out = big; - - if ( !bit_y ) { - out = &(big_u->hed); - } - else { - out = &(big_u->tel); - } - - big = *out; + out = &(old[bit_y]); + big = *out; big_u->mug_w = 0; } else { - u3_noun old = big; - u3_noun* hed; - u3_noun* tel; - - *out = u3i_defcons(&hed, &tel); - - if ( !bit_y ) { - out = hed; - big = u3k(big_u->hed); - *tel = u3k(big_u->tel); - } - else { - out = tel; - big = u3k(big_u->tel); - *hed = u3k(big_u->hed); - } - - u3z(old); + u3_noun luz = big; + u3_noun* new[2]; + + *out = u3i_defcons(&new[0], &new[1]); + out = new[bit_y]; + big = u3k(old[bit_y]); + *(new[!bit_y]) = u3k(old[!bit_y]); + + u3z(luz); } } while ( dep_w-- ); From e182de8ddd762cf822e59b7b8bd07381ec756c82 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 22 Jul 2022 00:15:10 -0400 Subject: [PATCH 6/6] u3: further optimizes u3i_edit, inlining axis bit math --- pkg/noun/imprison.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/noun/imprison.c b/pkg/noun/imprison.c index 7e42d331b5..cc945cb27a 100644 --- a/pkg/noun/imprison.c +++ b/pkg/noun/imprison.c @@ -626,12 +626,15 @@ u3i_edit(u3_noun big, u3_noun axe, u3_noun som) case 1: break; default: { - c3_w dep_w = u3r_met(0, u3x_atom(axe)) - 2; + c3_w dep_w = u3r_met(0, u3x_atom(axe)) - 2; + const c3_w* axe_w = ( c3y == u3a_is_cat(axe) ) + ? &axe + : ((u3a_atom*)u3a_to_ptr(axe))->buf_w; do { u3a_cell* big_u = u3a_to_ptr(big); u3_noun* old = (u3_noun*)&(big_u->hed); - const c3_y bit_y = u3r_bit(dep_w, axe); + const c3_y bit_y = 1 & (axe_w[dep_w >> 5] >> (dep_w & 31)); if ( c3n == u3a_is_cell(big) ) { return u3m_bail(c3__exit);