Repository navigation
Conversation
…lare themselves time-dependent. The render cache keeps one result per node path, so memory no longer grows with every animation frame or drag step. Always-rendered nodes, nodes with context or state ports, and time-dependent functions run on every render. Functions declare this with @timedependent (Java), a timeDependent attribute (Python) or ^:time-dependent metadata (Clojure). Cached results are dropped when a code library is reloaded, added or removed. Nodes that read files are cached with the modification time and size of those files in the key. State ports and device.buffer_points are back. A stateful node's previous output lives next to the cache and advances only on a completed render. The file format returns to 21; version 22 files from development builds open as 21. Bundled handles draw in screen space, including pyhandles.SnapHandle, and Handle.setViewTransform has a default. The launch end-to-end test drives the menu shortcut through Swing key bindings, since macOS delivers OS-level keystrokes to the frontmost app.
…ion 22 upgrade. A node's cached result keeps the modification time and size of every file read while computing it, including files read by nodes inside a subnetwork. The result is used only while those files are unchanged, so networks that import files stay cached.
…ed renders over random edits. With -Dnodebox.cache.verify=true, which ant test and ant test-e2e set, every cache hit is computed again and compared by content; a difference fails with the node path. RenderCacheDifferentialTest replays random user edits (frames, mouse, parameters, rewiring, renaming, deleting, undo, rendered node, file changes, code reloads) on every example and on a scenario document with files, user code, state, an always-rendered node and subnetworks, and compares each cached render with an uncached one.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes found while reviewing master for the 3.2 release. The render cache from #535 had three bugs users would hit, and it removed stateful nodes.
User-visible changes
timeDependentin Figment). Such a function runs on every render instead of being cached:read_sensor.timeDependent = True(defn ^:time-dependent read-sensor [x] ...)@TimeDependent.network/httpGetanddevice/sendOSCuse it, which replaces the hard-coded list inRenderCache.import_svg,import_text,import_csv) stay cached.device.buffer_pointswork as in 3.1. A stateful node is never cached, and the nodes upstream of it stay cached. State advances only on a completed, non-canceled render, and resets on Rewind.buffer_pointsalso trims correctly when its size is lowered.pyhandles.SnapHandledraws and hit-tests in screen space (it also lacked an import ofRect).Handle.setViewTransformhas an empty default, so a custom handle that implementsHandledirectly no longer fails on paint.Migration note for the release
Node functions are cached: a node runs again only when its inputs, parameters or code change. In 3.1 every node ran on every render. For user code this means:
p = path.clone()) or build a new object, because a cached result is shared between renders.randomor a file it opens itself must be marked time-dependent.self.toScreen(x, y).Due diligence
pyvectorfunctions clone before they change geometry.bitcraftlab/nodebox-examplesturtle.pymutates theTurtle(aPathsubclass) it receives and returns it, so under caching the path gains extra segments on each edit. This is inferred from the code; I did not run it. The migration note above covers it.Cache checks
The cache must never change what renders. Two checks guard that:
-Dnodebox.cache.verify=truecomputes every cache hit again and compares the results by content. A difference fails with the node path.ant testandant test-e2eset it; the end-to-end suite also fails if the running app hit a difference.RenderCacheDifferentialTest. It replays random user edits on every example document and on a scenario document, and after each step compares a cached render with an uncached one. The edits are frames, mouse moves, parameter changes, rewiring, renaming, deleting, undo, switching the rendered node, file changes and code reloads. The scenario has files, user code, state, an always-rendered node and subnetworks. Each sequence runs with verify mode and without, since verify mode reruns hit nodes and would hide a skipped side effect.Both checks were seen to fail on planted cache bugs, one per dependency the cache tracks: always-rendered nodes cached, code reload ignored, file changes ignored, stateful nodes cached, published-port arguments cached, files inside a network not passed to it, frame nodes cached, and connected inputs left out of the key. The differential test caught all eight. With the key bug planted, the end-to-end suite reported 39 stale hits.
Tests
ant clean test, thenNODEBOX_E2E=1 ant test-e2e: 461 tests, 0 failures, 0 errors, 0 skipped (macOS).RenderCacheTest,PyHandlesTest,DeviceFunctionsTestandNodeLibraryTest. Each failed before its fix.PyHandlesTest. I did not inspect it on screen.