From 6f9e86c5c72f849cd464f7891ca8c9c6f79f7e60 Mon Sep 17 00:00:00 2001 From: aaron <83140718+centau@users.noreply.github.com> Date: Mon, 7 Aug 2023 00:58:11 +0100 Subject: [PATCH] --- src/bind.luau | 1 + src/maps.luau | 43 +++++++++++++++++++++------------------ test/benchmark.luau | 49 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/src/bind.luau b/src/bind.luau index a10443a..6f65990 100644 --- a/src/bind.luau +++ b/src/bind.luau @@ -87,6 +87,7 @@ local function bind_parent(instance: Instance, fn: () -> Instance?) end) end +-- todo: could optimize, see: maps.luau values() local function bind_children(parent: Instance, fn: () -> { Instance }) local current_child_set: { [Instance]: true } = {} -- cache of all children parented before update local new_child_set: { [Instance]: true } = {} -- cache of all children parented after update diff --git a/src/maps.luau b/src/maps.luau index 95f3aef..dd87536 100644 --- a/src/maps.luau +++ b/src/maps.luau @@ -9,7 +9,7 @@ local link = graph.link type Map = { [K]: V } --- todo: this could be optimized +-- todo: optimize output array local function indexes(input: () -> Map, transform: (() -> VI, K) -> VO): () -> { VO } local input_cache = {} :: Map local output_cache = {} :: Map @@ -32,9 +32,12 @@ local function indexes(input: () -> Map, transform: (() -> VI, input_nodes[k] = nil end + table.clear(remove_queue) + -- process new or changed values for k, v in next, data do local cv = input_cache[k] + if cv == nil then local node, get_value = create(v) input_nodes[k] = node @@ -72,45 +75,45 @@ local function indexes(input: () -> Map, transform: (() -> VI, return output_get end --- todo: this should be optimized +-- todo: optimize output array local function values(input: () -> Map, transform: (VI, () -> K) -> VO): () -> { VO } - local input_cache_up = {} :: Map - local input_cache_buffer_up = {} :: Map + local cur_input_cache_up = {} :: Map + local new_input_cache_up = {} :: Map local output_cache = {} :: Map local input_nodes = {} :: Map> local output_array = {} :: { VO } local function recompute(data: Map) - local input_cache, input_cache_buffer = - input_cache_up, input_cache_buffer_up - - -- process new or changed values + local cur_input_cache, new_input_cache = cur_input_cache_up, new_input_cache_up + + -- process data for i, v in next, data do - local cv = input_cache[v] + new_input_cache[v] = i + local cv = cur_input_cache[v] + if cv == nil then local node, get_value = create(i) input_nodes[v] = node output_cache[v] = transform(v, get_value) - elseif cv ~= i then - set(input_nodes[v], i) + else + if cv ~= i then + set(input_nodes[v], i) + end + cur_input_cache[v] = nil end - - input_cache_buffer[v] = i end -- remove old values - for v, k in next, input_cache do - if input_cache_buffer[v] == nil then - output_cache[v] = nil - input_nodes[v] = nil - end + for v in next, cur_input_cache do + output_cache[v] = nil + input_nodes[v] = nil end -- update buffer cache - table.clear(input_cache) - input_cache_up, input_cache_buffer_up = input_cache_buffer, input_cache + table.clear(cur_input_cache) + cur_input_cache_up, new_input_cache_up = new_input_cache, cur_input_cache -- output elements table.clear(output_array) diff --git a/test/benchmark.luau b/test/benchmark.luau index 6264e84..b299505 100644 --- a/test/benchmark.luau +++ b/test/benchmark.luau @@ -135,11 +135,14 @@ BENCH("indexes() no change", function() return {} end) + state(state()) -- fill double buffer + START(N) state(data) end) +-- todo: find out what is causing allocation BENCH("indexes() all change", function() local data = {} @@ -153,6 +156,8 @@ BENCH("indexes() all change", function() return {} end) + state(state()) -- fill double buffer + for i, v in data do data[i] = v + 1 end @@ -162,6 +167,26 @@ BENCH("indexes() all change", function() state(data) end) +BENCH("indexes() all remove", function() + local data = {} + + for i = 1, N do + data[i] = i + end + + local state = vide.source(data) + + local _list = vide.values(state, function(v, i) + return {} + end) + + table.clear(data) + + START(N) + + state(data) +end) + BENCH("values() no change", function() local data = {} @@ -175,6 +200,8 @@ BENCH("values() no change", function() return {} end) + state(state()) -- fill double buffer + START(N) state(data) @@ -193,6 +220,8 @@ BENCH("values() all change", function() return {} end) + state(state()) -- fill double buffer + for i = 1, N do local r = math.random(1, #data) data[i], data[r] = data[r], data[i] @@ -203,4 +232,24 @@ BENCH("values() all change", function() state(data) end) +BENCH("values() all remove", function() + local data = {} + + for i = 1, N do + data[i] = {} + end + + local state = vide.source(data) + + local _list = vide.values(state, function(v, i) + return {} + end) + + table.clear(data) + + START(N) + + state(data) +end) + return nil