diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-05 08:49:48 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-05 08:51:09 +0200 |
commit | c64f9dcd61c1ad7bef3dbf5b7647a2a2da23ac0f (patch) | |
tree | 349aa02b2367d11d252468af983d719f20a00a42 | |
parent | 2cb54d2ac028d648deab6d49a051f53a0bb67fb2 (diff) | |
download | lanes-c64f9dcd61c1ad7bef3dbf5b7647a2a2da23ac0f.tar.gz lanes-c64f9dcd61c1ad7bef3dbf5b7647a2a2da23ac0f.tar.bz2 lanes-c64f9dcd61c1ad7bef3dbf5b7647a2a2da23ac0f.zip |
Enable manual control of GC inside keeper states
Diffstat (limited to '')
-rw-r--r-- | Makefile | 22 | ||||
-rw-r--r-- | docs/index.html | 14 | ||||
-rw-r--r-- | src/keeper.cpp | 54 | ||||
-rw-r--r-- | src/keeper.h | 1 | ||||
-rw-r--r-- | src/lanes.lua | 5 | ||||
-rw-r--r-- | src/linda.cpp | 17 | ||||
-rw-r--r-- | tests/keeper.lua | 15 | ||||
-rw-r--r-- | tests/linda_perf.lua | 64 |
8 files changed, 119 insertions, 73 deletions
@@ -72,25 +72,25 @@ rock: | |||
72 | #--- Testing --- | 72 | #--- Testing --- |
73 | # | 73 | # |
74 | test: | 74 | test: |
75 | $(MAKE) errhangtest | 75 | $(MAKE) atexit |
76 | $(MAKE) irayo_recursive | 76 | $(MAKE) atomic |
77 | $(MAKE) irayo_closure | ||
78 | $(MAKE) basic | 77 | $(MAKE) basic |
79 | $(MAKE) cancel | 78 | $(MAKE) cancel |
80 | $(MAKE) fifo | ||
81 | $(MAKE) keeper | ||
82 | $(MAKE) timer | ||
83 | $(MAKE) atomic | ||
84 | $(MAKE) cyclic | 79 | $(MAKE) cyclic |
85 | $(MAKE) objects | 80 | $(MAKE) errhangtest |
86 | $(MAKE) fibonacci | 81 | $(MAKE) fibonacci |
87 | $(MAKE) recursive | 82 | $(MAKE) fifo |
88 | $(MAKE) func_is_string | 83 | $(MAKE) func_is_string |
89 | $(MAKE) atexit | 84 | $(MAKE) irayo_recursive |
85 | $(MAKE) irayo_closure | ||
86 | $(MAKE) keeper | ||
90 | $(MAKE) linda_perf | 87 | $(MAKE) linda_perf |
91 | $(MAKE) rupval | 88 | $(MAKE) objects |
92 | $(MAKE) package | 89 | $(MAKE) package |
93 | $(MAKE) pingpong | 90 | $(MAKE) pingpong |
91 | $(MAKE) recursive | ||
92 | $(MAKE) rupval | ||
93 | $(MAKE) timer | ||
94 | 94 | ||
95 | basic: tests/basic.lua $(_TARGET_SO) | 95 | basic: tests/basic.lua $(_TARGET_SO) |
96 | $(_PREFIX) $(LUA) $< | 96 | $(_PREFIX) $(LUA) $< |
diff --git a/docs/index.html b/docs/index.html index 24fa4ef..ee5acfa 100644 --- a/docs/index.html +++ b/docs/index.html | |||
@@ -291,6 +291,18 @@ | |||
291 | </tr> | 291 | </tr> |
292 | 292 | ||
293 | <tr valign=top> | 293 | <tr valign=top> |
294 | <td id="keepers_gc_threshold"> | ||
295 | <code>.keepers_gc_threshold</code> | ||
296 | </td> | ||
297 | <td>integer</td> | ||
298 | <td> | ||
299 | If <0, GC runs automatically. This is the default.<br/> | ||
300 | If 0, GC runs after *every* keeper operation.<br/> | ||
301 | If >0, Keepers run GC manually with <tt>lua_gc(LUA_GCCOLLECT)</tt> whenever memory usage reported by <tt>lua_gc(LUA_GCCOUNT)</tt> reaches this threshold. Check is made after every keeper operation (see <a href="#lindas">below</a>). If memory usage remains above threshold after the GC cycle, an error is raised. | ||
302 | </td> | ||
303 | </tr> | ||
304 | |||
305 | <tr valign=top> | ||
294 | <td id="with_timers"> | 306 | <td id="with_timers"> |
295 | <code>.with_timers</code> | 307 | <code>.with_timers</code> |
296 | </td> | 308 | </td> |
@@ -1784,4 +1796,4 @@ int luaD_new_clonable( lua_State* L) | |||
1784 | </p> | 1796 | </p> |
1785 | 1797 | ||
1786 | </body> | 1798 | </body> |
1787 | </html></pre> \ No newline at end of file | 1799 | </html> |
diff --git a/src/keeper.cpp b/src/keeper.cpp index 244cb6a..937d190 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -652,12 +652,18 @@ void init_keepers(Universe* U, lua_State* L) | |||
652 | { | 652 | { |
653 | STACK_CHECK_START_REL(L, 0); // L K | 653 | STACK_CHECK_START_REL(L, 0); // L K |
654 | lua_getfield(L, 1, "nb_keepers"); // nb_keepers | 654 | lua_getfield(L, 1, "nb_keepers"); // nb_keepers |
655 | int nb_keepers{ static_cast<int>(lua_tointeger(L, -1)) }; | 655 | int const nb_keepers{ static_cast<int>(lua_tointeger(L, -1)) }; |
656 | lua_pop(L, 1); // | 656 | lua_pop(L, 1); // |
657 | if (nb_keepers < 1) | 657 | if (nb_keepers < 1) |
658 | { | 658 | { |
659 | std::ignore = luaL_error(L, "Bad number of keepers (%d)", nb_keepers); | 659 | std::ignore = luaL_error(L, "Bad number of keepers (%d)", nb_keepers); |
660 | } | 660 | } |
661 | STACK_CHECK(L, 0); | ||
662 | |||
663 | lua_getfield(L, 1, "keepers_gc_threshold"); // keepers_gc_threshold | ||
664 | int const keepers_gc_threshold{ static_cast<int>(lua_tointeger(L, -1)) }; | ||
665 | lua_pop(L, 1); // | ||
666 | STACK_CHECK(L, 0); | ||
661 | 667 | ||
662 | // Keepers contains an array of 1 Keeper, adjust for the actual number of keeper states | 668 | // Keepers contains an array of 1 Keeper, adjust for the actual number of keeper states |
663 | { | 669 | { |
@@ -668,6 +674,7 @@ void init_keepers(Universe* U, lua_State* L) | |||
668 | std::ignore = luaL_error(L, "init_keepers() failed while creating keeper array; out of memory"); | 674 | std::ignore = luaL_error(L, "init_keepers() failed while creating keeper array; out of memory"); |
669 | } | 675 | } |
670 | memset(U->keepers, 0, bytes); | 676 | memset(U->keepers, 0, bytes); |
677 | U->keepers->gc_threshold = keepers_gc_threshold; | ||
671 | U->keepers->nb_keepers = nb_keepers; | 678 | U->keepers->nb_keepers = nb_keepers; |
672 | } | 679 | } |
673 | for (int i = 0; i < nb_keepers; ++i) // keepersUD | 680 | for (int i = 0; i < nb_keepers; ++i) // keepersUD |
@@ -685,6 +692,11 @@ void init_keepers(Universe* U, lua_State* L) | |||
685 | // therefore, we need a recursive mutex. | 692 | // therefore, we need a recursive mutex. |
686 | MUTEX_RECURSIVE_INIT(&U->keepers->keeper_array[i].keeper_cs); | 693 | MUTEX_RECURSIVE_INIT(&U->keepers->keeper_array[i].keeper_cs); |
687 | 694 | ||
695 | if (U->keepers->gc_threshold >= 0) | ||
696 | { | ||
697 | lua_gc(K, LUA_GCSTOP, 0); | ||
698 | } | ||
699 | |||
688 | STACK_CHECK_START_ABS(K, 0); | 700 | STACK_CHECK_START_ABS(K, 0); |
689 | 701 | ||
690 | // copy the universe pointer in the keeper itself | 702 | // copy the universe pointer in the keeper itself |
@@ -735,8 +747,12 @@ void init_keepers(Universe* U, lua_State* L) | |||
735 | Keeper* which_keeper(Keepers* keepers_, uintptr_t magic_) | 747 | Keeper* which_keeper(Keepers* keepers_, uintptr_t magic_) |
736 | { | 748 | { |
737 | int const nbKeepers{ keepers_->nb_keepers }; | 749 | int const nbKeepers{ keepers_->nb_keepers }; |
738 | unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); | 750 | if (nbKeepers) |
739 | return &keepers_->keeper_array[i]; | 751 | { |
752 | unsigned int i = (unsigned int) ((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); | ||
753 | return &keepers_->keeper_array[i]; | ||
754 | } | ||
755 | return nullptr; | ||
740 | } | 756 | } |
741 | 757 | ||
742 | // ################################################################################################## | 758 | // ################################################################################################## |
@@ -745,11 +761,7 @@ Keeper* keeper_acquire(Keepers* keepers_, uintptr_t magic_) | |||
745 | { | 761 | { |
746 | int const nbKeepers{ keepers_->nb_keepers }; | 762 | int const nbKeepers{ keepers_->nb_keepers }; |
747 | // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) | 763 | // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) |
748 | if( nbKeepers == 0) | 764 | if (nbKeepers) |
749 | { | ||
750 | return nullptr; | ||
751 | } | ||
752 | else | ||
753 | { | 765 | { |
754 | /* | 766 | /* |
755 | * Any hashing will do that maps pointers to 0..GNbKeepers-1 | 767 | * Any hashing will do that maps pointers to 0..GNbKeepers-1 |
@@ -765,6 +777,7 @@ Keeper* keeper_acquire(Keepers* keepers_, uintptr_t magic_) | |||
765 | //++ K->count; | 777 | //++ K->count; |
766 | return K; | 778 | return K; |
767 | } | 779 | } |
780 | return nullptr; | ||
768 | } | 781 | } |
769 | 782 | ||
770 | // ################################################################################################## | 783 | // ################################################################################################## |
@@ -843,5 +856,30 @@ int keeper_call(Universe* U, lua_State* K, keeper_api_t func_, lua_State* L, voi | |||
843 | } | 856 | } |
844 | // whatever happens, restore the stack to where it was at the origin | 857 | // whatever happens, restore the stack to where it was at the origin |
845 | lua_settop(K, Ktos); | 858 | lua_settop(K, Ktos); |
859 | |||
860 | // don't do this for this particular function, as it is only called during Linda destruction, and we don't want to raise an error, ever | ||
861 | if (func_ != KEEPER_API(clear)) [[unlikely]] | ||
862 | { | ||
863 | // since keeper state GC is stopped, let's run a step once in a while if required | ||
864 | int const gc_threshold{ U->keepers->gc_threshold }; | ||
865 | if (gc_threshold == 0) [[unlikely]] | ||
866 | { | ||
867 | lua_gc(K, LUA_GCSTEP, 0); | ||
868 | } | ||
869 | else if (gc_threshold > 0) [[likely]] | ||
870 | { | ||
871 | int const gc_usage{ lua_gc(K, LUA_GCCOUNT, 0) }; | ||
872 | if (gc_usage >= gc_threshold) | ||
873 | { | ||
874 | lua_gc(K, LUA_GCCOLLECT, 0); | ||
875 | int const gc_usage_after{ lua_gc(K, LUA_GCCOUNT, 0) }; | ||
876 | if (gc_usage_after > gc_threshold) [[unlikely]] | ||
877 | { | ||
878 | luaL_error(L, "Keeper GC threshold is too low, need at least %d", gc_usage_after); | ||
879 | } | ||
880 | } | ||
881 | } | ||
882 | } | ||
883 | |||
846 | return retvals; | 884 | return retvals; |
847 | } | 885 | } |
diff --git a/src/keeper.h b/src/keeper.h index e081bea..f7e3951 100644 --- a/src/keeper.h +++ b/src/keeper.h | |||
@@ -24,6 +24,7 @@ struct Keeper | |||
24 | 24 | ||
25 | struct Keepers | 25 | struct Keepers |
26 | { | 26 | { |
27 | int gc_threshold{ 0 }; | ||
27 | int nb_keepers; | 28 | int nb_keepers; |
28 | Keeper keeper_array[1]; | 29 | Keeper keeper_array[1]; |
29 | }; | 30 | }; |
diff --git a/src/lanes.lua b/src/lanes.lua index b4c0070..6af286a 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
@@ -70,6 +70,7 @@ lanes.configure = function( settings_) | |||
70 | local default_params = | 70 | local default_params = |
71 | { | 71 | { |
72 | nb_keepers = 1, | 72 | nb_keepers = 1, |
73 | keepers_gc_threshold = -1, | ||
73 | on_state_create = nil, | 74 | on_state_create = nil, |
74 | shutdown_timeout = 0.25, | 75 | shutdown_timeout = 0.25, |
75 | with_timers = true, | 76 | with_timers = true, |
@@ -91,6 +92,10 @@ lanes.configure = function( settings_) | |||
91 | -- nb_keepers should be a number > 0 | 92 | -- nb_keepers should be a number > 0 |
92 | return type( val_) == "number" and val_ > 0 | 93 | return type( val_) == "number" and val_ > 0 |
93 | end, | 94 | end, |
95 | keepers_gc_threshold = function( val_) | ||
96 | -- keepers_gc_threshold should be a number | ||
97 | return type( val_) == "number" | ||
98 | end, | ||
94 | with_timers = boolean_param_checker, | 99 | with_timers = boolean_param_checker, |
95 | allocator = function( val_) | 100 | allocator = function( val_) |
96 | -- can be nil, "protected", or a function | 101 | -- can be nil, "protected", or a function |
diff --git a/src/linda.cpp b/src/linda.cpp index 37a74b0..5ee4768 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
@@ -885,15 +885,22 @@ static void* linda_id( lua_State* L, DeepOp op_) | |||
885 | { | 885 | { |
886 | Linda* const linda{ lua_tolightuserdata<Linda>(L, 1) }; | 886 | Linda* const linda{ lua_tolightuserdata<Linda>(L, 1) }; |
887 | ASSERT_L(linda); | 887 | ASSERT_L(linda); |
888 | 888 | Keeper* const myK{ which_keeper(linda->U->keepers, linda->hashSeed()) }; | |
889 | // Clean associated structures in the keeper state. | 889 | // if collected after the universe, keepers are already destroyed, and there is nothing to clear |
890 | Keeper* const K{ keeper_acquire(linda->U->keepers, linda->hashSeed()) }; | 890 | if (myK) |
891 | if (K && K->L) // can be nullptr if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup) | ||
892 | { | 891 | { |
892 | // if collected from my own keeper, we can't acquire/release it | ||
893 | // because we are already inside a protected area, and trying to do so would deadlock! | ||
894 | bool const need_acquire_release{ myK->L != L }; | ||
895 | // Clean associated structures in the keeper state. | ||
896 | Keeper* const K{ need_acquire_release ? keeper_acquire(linda->U->keepers, linda->hashSeed()) : myK }; | ||
893 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... | 897 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... |
894 | keeper_call(linda->U, K->L, KEEPER_API(clear), L, linda, 0); | 898 | keeper_call(linda->U, K->L, KEEPER_API(clear), L, linda, 0); |
899 | if (need_acquire_release) | ||
900 | { | ||
901 | keeper_release(K); | ||
902 | } | ||
895 | } | 903 | } |
896 | keeper_release(K); | ||
897 | 904 | ||
898 | delete linda; // operator delete overload ensures things go as expected | 905 | delete linda; // operator delete overload ensures things go as expected |
899 | return nullptr; | 906 | return nullptr; |
diff --git a/tests/keeper.lua b/tests/keeper.lua index 9b38f02..6dbbd15 100644 --- a/tests/keeper.lua +++ b/tests/keeper.lua | |||
@@ -4,7 +4,7 @@ | |||
4 | -- Test program for Lua Lanes | 4 | -- Test program for Lua Lanes |
5 | -- | 5 | -- |
6 | 6 | ||
7 | local lanes = require "lanes".configure{ with_timers = false, nb_keepers = 200} | 7 | local lanes = require "lanes".configure{ with_timers = false, nb_keepers = 1, keepers_gc_threshold = 500} |
8 | 8 | ||
9 | do | 9 | do |
10 | print "Linda names test:" | 10 | print "Linda names test:" |
@@ -12,7 +12,20 @@ do | |||
12 | local unnamedLinda2 = lanes.linda("") | 12 | local unnamedLinda2 = lanes.linda("") |
13 | local veeeerrrryyyylooongNamedLinda= lanes.linda( "veeeerrrryyyylooongNamedLinda", 1) | 13 | local veeeerrrryyyylooongNamedLinda= lanes.linda( "veeeerrrryyyylooongNamedLinda", 1) |
14 | print(unnamedLinda, unnamedLinda2, veeeerrrryyyylooongNamedLinda) | 14 | print(unnamedLinda, unnamedLinda2, veeeerrrryyyylooongNamedLinda) |
15 | print "GC deadlock test start" | ||
16 | -- store a linda in another linda (-> in a keeper) | ||
17 | unnamedLinda:set("here", lanes.linda("temporary linda")) | ||
18 | -- repeatedly add and remove stuff in the linda so that a GC happens during the keeper operation | ||
19 | for i = 1, 1000 do | ||
20 | for j = 1, 1000 do -- send 1000 tables | ||
21 | unnamedLinda:send("here", {"a", "table", "with", "some", "stuff"}) | ||
22 | end | ||
23 | unnamedLinda:set("here") -- clear everything | ||
24 | end | ||
15 | end | 25 | end |
26 | print "collecting garbage" | ||
27 | collectgarbage() | ||
28 | print "GC deadlock test done" | ||
16 | 29 | ||
17 | local print_id = 0 | 30 | local print_id = 0 |
18 | local PRINT = function(...) | 31 | local PRINT = function(...) |
diff --git a/tests/linda_perf.lua b/tests/linda_perf.lua index 9177852..c736428 100644 --- a/tests/linda_perf.lua +++ b/tests/linda_perf.lua | |||
@@ -1,5 +1,5 @@ | |||
1 | local lanes = require "lanes" | 1 | local lanes = require "lanes" |
2 | lanes.configure{ with_timers = false } | 2 | lanes.configure{ with_timers = false, keepers_gc_threshold=20000 } |
3 | 3 | ||
4 | -- set TEST1, PREFILL1, FILL1, TEST2, PREFILL2, FILL2 from the command line | 4 | -- set TEST1, PREFILL1, FILL1, TEST2, PREFILL2, FILL2 from the command line |
5 | 5 | ||
@@ -17,6 +17,8 @@ local finalizer = function(err, stk) | |||
17 | end | 17 | end |
18 | end | 18 | end |
19 | 19 | ||
20 | --################################################################################################## | ||
21 | |||
20 | -- this lane eats items in the linda one by one | 22 | -- this lane eats items in the linda one by one |
21 | local eater = function( l, loop) | 23 | local eater = function( l, loop) |
22 | set_finalizer(finalizer) | 24 | set_finalizer(finalizer) |
@@ -32,6 +34,8 @@ local eater = function( l, loop) | |||
32 | print("eater: done ("..val..")") | 34 | print("eater: done ("..val..")") |
33 | end | 35 | end |
34 | 36 | ||
37 | --################################################################################################## | ||
38 | |||
35 | -- this lane eats items in the linda in batches | 39 | -- this lane eats items in the linda in batches |
36 | local gobbler = function( l, loop, batch) | 40 | local gobbler = function( l, loop, batch) |
37 | set_finalizer(finalizer) | 41 | set_finalizer(finalizer) |
@@ -47,9 +51,13 @@ local gobbler = function( l, loop, batch) | |||
47 | print("gobbler: done ("..val..")") | 51 | print("gobbler: done ("..val..")") |
48 | end | 52 | end |
49 | 53 | ||
54 | --################################################################################################## | ||
55 | |||
50 | local lane_eater_gen = lanes.gen( "*", {priority = 3}, eater) | 56 | local lane_eater_gen = lanes.gen( "*", {priority = 3}, eater) |
51 | local lane_gobbler_gen = lanes.gen( "*", {priority = 3}, gobbler) | 57 | local lane_gobbler_gen = lanes.gen( "*", {priority = 3}, gobbler) |
52 | 58 | ||
59 | --################################################################################################## | ||
60 | |||
53 | -- main thread writes data while a lane reads it | 61 | -- main thread writes data while a lane reads it |
54 | local function ziva( preloop, loop, batch) | 62 | local function ziva( preloop, loop, batch) |
55 | -- prefill the linda a bit to increase fifo stress | 63 | -- prefill the linda a bit to increase fifo stress |
@@ -94,6 +102,8 @@ local function ziva( preloop, loop, batch) | |||
94 | return lanes.now_secs() - t1 | 102 | return lanes.now_secs() - t1 |
95 | end | 103 | end |
96 | 104 | ||
105 | --################################################################################################## | ||
106 | |||
97 | TEST1 = TEST1 or 1000 | 107 | TEST1 = TEST1 or 1000 |
98 | PREFILL1 = PREFILL1 or 10000 | 108 | PREFILL1 = PREFILL1 or 10000 |
99 | FILL1 = FILL1 or 2000000 | 109 | FILL1 = FILL1 or 2000000 |
@@ -109,6 +119,7 @@ local tests1 = | |||
109 | { PREFILL1, FILL1, 13}, | 119 | { PREFILL1, FILL1, 13}, |
110 | { PREFILL1, FILL1, 21}, | 120 | { PREFILL1, FILL1, 21}, |
111 | { PREFILL1, FILL1, 44}, | 121 | { PREFILL1, FILL1, 44}, |
122 | { PREFILL1, FILL1, 65}, | ||
112 | } | 123 | } |
113 | print "############################################ tests #1" | 124 | print "############################################ tests #1" |
114 | for i, v in ipairs( tests1) do | 125 | for i, v in ipairs( tests1) do |
@@ -119,38 +130,7 @@ for i, v in ipairs( tests1) do | |||
119 | print("DURATION = " .. ziva( pre, loop, batch) .. "\n") | 130 | print("DURATION = " .. ziva( pre, loop, batch) .. "\n") |
120 | end | 131 | end |
121 | 132 | ||
122 | --[[ | 133 | --################################################################################################## |
123 | V 2.1.0: | ||
124 | ziva( 20000, 0) -> 4s ziva( 10000, 20000) -> 3s | ||
125 | ziva( 30000, 0) -> 8s ziva( 20000, 30000) -> 7s | ||
126 | ziva( 40000, 0) -> 15s ziva( 30000, 40000) -> 15s | ||
127 | ziva( 50000, 0) -> 24s ziva( 40000, 50000) -> 23s | ||
128 | ziva( 60000, 0) -> 34s ziva( 50000, 60000) -> 33s | ||
129 | |||
130 | SIMPLIFIED: | ||
131 | ziva( 20000, 0) -> 4s ziva( 10000, 20000) -> 3s | ||
132 | ziva( 30000, 0) -> 9s ziva( 20000, 30000) -> 8s | ||
133 | ziva( 40000, 0) -> 15s ziva( 30000, 40000) -> 15s | ||
134 | ziva( 50000, 0) -> 25s ziva( 40000, 50000) -> 24s | ||
135 | ziva( 60000, 0) -> 35s ziva( 50000, 60000) -> 35s | ||
136 | |||
137 | FIFO: | ||
138 | ziva( 2000000, 0) -> 9s ziva( 1000000, 2000000) -> 33s | ||
139 | ziva( 3000000, 0) -> 14s ziva( 2000000, 3000000) -> 40s | ||
140 | ziva( 4000000, 0) -> 20s ziva( 3000000, 4000000) -> 27s | ||
141 | ziva( 5000000, 0) -> 24s ziva( 4000000, 5000000) -> 42s | ||
142 | ziva( 6000000, 0) -> 29s ziva( 5000000, 6000000) -> 55s | ||
143 | |||
144 | FIFO BATCHED: | ||
145 | ziva( 4000000, 0, 1) -> 20s | ||
146 | ziva( 4000000, 0, 2) -> 11s | ||
147 | ziva( 4000000, 0, 3) -> 7s | ||
148 | ziva( 4000000, 0, 5) -> 5s | ||
149 | ziva( 4000000, 0, 8) -> 3s | ||
150 | ziva( 4000000, 0, 13) -> 3s | ||
151 | ziva( 4000000, 0, 21) -> 3s | ||
152 | ziva( 4000000, 0, 44) -> 2s | ||
153 | ]] | ||
154 | 134 | ||
155 | -- sequential write/read (no parallelization involved) | 135 | -- sequential write/read (no parallelization involved) |
156 | local function ziva2( preloop, loop, batch) | 136 | local function ziva2( preloop, loop, batch) |
@@ -183,7 +163,7 @@ local function ziva2( preloop, loop, batch) | |||
183 | for i = 1, preloop, step do | 163 | for i = 1, preloop, step do |
184 | batch_send() | 164 | batch_send() |
185 | end | 165 | end |
186 | print( "stored " .. (l:count( "key") or 0) .. " items in the linda before starting consumer lane") | 166 | print( "stored " .. (l:count( "key") or 0) .. " items in the linda before starting the alternating reads and writes") |
187 | -- loop that alternatively sends and reads data off the linda | 167 | -- loop that alternatively sends and reads data off the linda |
188 | if loop > preloop then | 168 | if loop > preloop then |
189 | for i = preloop + 1, loop, step do | 169 | for i = preloop + 1, loop, step do |
@@ -198,25 +178,14 @@ local function ziva2( preloop, loop, batch) | |||
198 | return lanes.now_secs() - t1 | 178 | return lanes.now_secs() - t1 |
199 | end | 179 | end |
200 | 180 | ||
181 | --################################################################################################## | ||
182 | |||
201 | TEST2 = TEST2 or 1000 | 183 | TEST2 = TEST2 or 1000 |
202 | PREFILL2 = PREFILL2 or 0 | 184 | PREFILL2 = PREFILL2 or 0 |
203 | FILL2 = FILL2 or 4000000 | 185 | FILL2 = FILL2 or 4000000 |
204 | 186 | ||
205 | local tests2 = | 187 | local tests2 = |
206 | { | 188 | { |
207 | -- prefill, then consume everything | ||
208 | --[[ | ||
209 | { 4000000, 0}, | ||
210 | { 4000000, 0, 1}, | ||
211 | { 4000000, 0, 2}, | ||
212 | { 4000000, 0, 3}, | ||
213 | { 4000000, 0, 5}, | ||
214 | { 4000000, 0, 8}, | ||
215 | { 4000000, 0, 13}, | ||
216 | { 4000000, 0, 21}, | ||
217 | { 4000000, 0, 44}, | ||
218 | --]] | ||
219 | -- alternatively fill and consume | ||
220 | { PREFILL2, FILL2}, | 189 | { PREFILL2, FILL2}, |
221 | { PREFILL2, FILL2, 1}, | 190 | { PREFILL2, FILL2, 1}, |
222 | { PREFILL2, FILL2, 2}, | 191 | { PREFILL2, FILL2, 2}, |
@@ -226,6 +195,7 @@ local tests2 = | |||
226 | { PREFILL2, FILL2, 13}, | 195 | { PREFILL2, FILL2, 13}, |
227 | { PREFILL2, FILL2, 21}, | 196 | { PREFILL2, FILL2, 21}, |
228 | { PREFILL2, FILL2, 44}, | 197 | { PREFILL2, FILL2, 44}, |
198 | { PREFILL2, FILL2, 65}, | ||
229 | } | 199 | } |
230 | 200 | ||
231 | print "############################################ tests #2" | 201 | print "############################################ tests #2" |