User Tools

Site Tools


newsletters:2025-09

This is an old revision of the document!


September 2025 newsletter

If you'd like to see the latest (much more responsive) folk2 and gadget in person, our next Folk open house is in the evening on Thursday, October 30, in East Williamsburg, Brooklyn.

What we've been up to

Internals notes

Mason Jones has been writing overview notes on the internals of the new parallel folk2 evaluator (a lot of it applies to folk1 also):

These should be good for people who want to understand what's going on and maybe contribute to the core, and it's great to see Mason develop that understanding himself also.

folk2 kernel

Omar: We made folk2 the default system we run at Hex House last month, which has been a big step and has forced us to clean up a lot of missing functionality and bugs that appear in daily use (and when demoing to visitors).

A lot of the work this month has either been those mundane, small-ish fixes, or it's been the big -atomically project to try to stamp out blinking in a principled way. Less of the speculative performance stuff that we were trying the last couple of months (maybe we'll pick that up after we merge folk2?)

(We've also been doing a lot of unrelated new feature/branch work on top of folk2; since it's such a breaking change, there's very little development happening on top of folk1 anymore.)

WIP: -atomically

We keep running into blinking, especially for camera-slice and clock-time animations, especially under load:

So I've been craving one (hopefully final) new concept for folk2. This is the -atomically block, which you can think of as like a 'transaction' or 'convergence arena'. Rough example:

When -atomically the clock time is /t/ {
  Wish $this is labelled $t

  # Do something really slow to compute x and y
  
  Wish $this draws a circle with x $x y $y
}

The -atomically block should guarantee that the circle doesn't blink out (use previous version if new one isn't converged yet), that you always see exactly one circle (unless the block really goes away for a while), and that you always see the circle that corresponds with the label (no partial states: either all the statements from the version appear or none do).

The way it works is that each invocation of the block gets an associated version object, and all downstream statements of the invocation are tagged with that version. The version has an inflight counter that increments every time a new work item is dispatched from a statement and decrements when the work item completes. When the inflight counter on a version hits 0, that version is considered converged, and statements from that version can be returned as results from Query! -atomically.

Query! -atomically should always return results from the most recently converged version for each key, I think (and no results from earlier or later versions of the same key).

Design discussion with Mason

I had a discussion with Mason where we concluded it was worth implementing:

Some early notes

Incomplete atomically arenas still make statements that get reacted to – the only difference is that they get filtered out of Query! results if you call with the option Query! -atomically. This is so we exclude them from 'side effects' at the boundary between Folk and the outside world (like the GPU and blinking).

Now implementing it. We have 2 test files that work right now, test/atomically.folk and test/atomically2.folk, if you want to see more usage examples.

Still need to clean up some memory leaks with the implementation and actually test it 'in production' with real GPU statements and camera input and so on.

Debugging repeated "Added <program>"

There's a bug where sometimes folk2 gets in a state where a program keeps getting reintroduced (not every frame, but a couple times a second), even though it's consistently on the table the whole time:

Have been trying to debug why that statement (tag 785 has a program) keeps showing up as a re-add, but no luck yet.

Speed up points-at

points-at was quite slow: 500us for each page on the table for each points-at, so often multiple milliseconds.

It turned out that there was a database query hidden inside it!

The $quadLib change function was doing a synchronous Query! to find any changers that are around to convert from one space (like camera-space) into another space (like projector-space).

I got rid of the 'page-local spaces' that all quads used to be specified in; now they all are in camera space immediately. Then I replaced the whole space-changer system with a single claim the quad changer is /quadChange/ that exposes a function quadChange that knows how to convert any known space to any other known space. (This claim is based on a Collect of all declared changers, which should almost never change now that we don't have page-local spaces; it should only change when calibration changes.)

Speed up camera slices

Camera slices were often blinking out, especially if you had a lot of other stuff on the table. I profiled it and it was taking an incredibly long time (often 10ms+) to copy each camera slice to the GPU:

(gpu/textures.folk:661 is the code that does an image copy to GPU:)

The solution was mostly just doing one command buffer submission instead of a bunch in sequence. Then (I don't think this helped as much) made us wait on a fence for the command buffer afterward (note that slice copy can happen on any thread, it just gets scheduled through Folk, it doesn't run on the render thread necessarily, so it has to be thread-safe)

Now we're closer to 3 or 4ms, I think. Not great but much better.

WIP: Speed up the animation port

Recall that we ported animation to folk2 last month. That port works OK, but it degrades as you put more programs on the table, timing messes up, and it makes a lot of Holds and takes up a lot of GPU slots and stuff because of all the synthetic objects.

We don't actually need a canvas per frame box, so I've been trying to write a version that just has quads for the frames (to get camera slices) but no canvases, and which draws everything straight to the display buffer.

That led me to realize that the quadChange I did earlier doesn't handle inverse changes, so I just added those. Haven't gotten to finish this yet, though.

Other improvements

Subscribe/Notify for events (on folk2)

Mason implemented 'pub-sub' 'events' where you subscribe to events with ''Subscribe:'' and dispatch events with ''Notify:''. This is a completely new feature that uses the Folk trie to dispatch point events (as opposed to statements which persist in memory).

We had a long discussion in Discord to get to this syntax :-)

I like the colon : in Notify: and Subscribe: as a specifier that it's event-oriented, as opposed to the ! for imperative (like Hold! and Assert!) or no punctuation for reactive (like Claim and Wish and When).

The subscribers live in the reactive database (and can be reactively removed), and the dispatch happens through the trie, but the events are immediate and not reactive or persistent.

I'm really impressed by how little code it is, for something we've thought about doing for years to cover cases like printing and key presses that don't quite fit into the continuous persistent statement framework of, like, program positions or presence.

folk2 shared-object tests

Mason and Omar have been working on some different strategies for avoiding copying/reparsing across threads.

Omar has some branches that have a per-thread, string-representation-keyed cache of Jim objects.

Mason has some branches that actually go into the Jim interpreter and share immutable objects between threads with atomic reference counting. (some thorny issues with code-representation objects and with shimmering here)

(Surprisingly?) neither is that much faster than baseline folk2!

I still think we're leaving performance on the table, but I'm not sure how. All our work items in folk2 still take like 50-100 microseconds each at minimum, sometimes hundreds of microseconds, and that just feels way slower than it should be to me. And calibration frames taking 200ms also feels way slower than it should be.

Hold! -save (on folk2)

Mason implemented a new ''-save'' option for ''Hold!'' that saves the held statement to disk, so it even survives across system reboots.

We're excited that this could remove the need for a lot of the ad hoc file-writing and file-reading we've been doing (for calibration, printed programs, editor config, etc) and make the equivalent functionality happen simply through statements. Also makes it easier to persist the state of programs so you don't lose all your work if/when the system crashes?

Like the Notify:/Subscribe:, this was just a couple hundred lines of code for an idea (persistent statements) that we'd been thinking about for years.

unix-commands.folk revamp (on folk2)

Mike Subelsky revamped the unix-commands.folk runner so that it works in folk2 and does bounded streaming of output lines (so even heavy output should work, I think).

folk2 lacks (and doesn't need) the process system and global variable support in folk1, so he had to rewrite it in terms of Hold! and an infinite loop.

Examples:

Wish $p runs Unix command "echo" with arguments [list "Hello" "World"]
Wish $p runs Unix command "curl" with arguments [list "-fsS" "http://wttr.in/Baltimore?format='%l:+%C'"]
Wish $p runs Unix command "ls" with arguments [list "-sSh" "/home/folk/folk2"]
Wish $p runs Unix command "ping" with arguments [list "google.com"]
Wish $p runs Unix command "sh" with arguments [list "-c" "while :; do date +%s.%3N; sleep 0.5; done"]

Still think it would be cool to build on the interface to have an easy version that auto-displays the output on $p (which is how the folk1 version worked), and to have the output claims ($p has Unix output lines and $p has Unix error output) scoped to the process so multiple processes can run on one page.

Folk gadget

Omar: I finally installed the Nord-Lock washers from a few weeks ago to keep the projector from swiveling inside the chassis. They seem to work pretty well. I don't see any rotation by the marker mark I put on the bolt and chassis. It replaces the tape on the left:

20251002-175647.jpeg 20250929-150221.jpeg

So that's one source of de-calibration fixed, hopefully.

Trying to reconfigure AnyBeam projector

One big obstacle to perfect calibration is just that the projector does orientation/surface sensing of some kind and keeps screwing up the projected image.

I tried a few different strategies to turn off auto-keystone and auto-rotate on the AnyBeam projector:

  • Run AnyBeam Android app in Android Studio emulator on macOS
  • Run AnyBeam Android app in Waydroid environment on Linux
  • Run Windows .exe in wine on macOS
  • Run Windows .exe in wine on Linux
  • Decompile Android app and generate Python (or whatever) that does the same serial commands

20250929-150302.jpeg 20250929-150316.jpeg

No luck yet – I haven't even gotten a response from the projector (it should show an onscreen UI) – I either get nothing, an error (on the Android app), or it hangs (Python direct to serial port).

Still to try:

  • Run Windows .exe in VMware
  • Run Windows .exe on native Windows on a PC
  • Run Android app on native Android

Once this is done, I'll want to recalibrate the projector, and then hopefully we'll have a solid calibration that perfectly matches the table calibration.

Outreach

Website updates

Omar: I moved this website from PHP shared hosting to a VM on Azure. It feels a lot snappier and more reliable to me now, especially images/video loading.

(DokuWiki is quite cool to migrate, because all its code and data are in one folder, so you just copy it from old host to new host and you're good, as long as it can host PHP. No database or other config files outside /var/www/html or whatever to move.)

I also upgraded DokuWiki. We have exactly one change to the base DokuWiki that I manually re-applied, to make resized images look acceptable on hi-DPI displays:

Open house

An especially small one this time, but we had the studio open all afternoon, and it was great to cowork with Mike (who came in from Baltimore) who was playing with audio stuff.

20250929-150103.jpeg 20250929-150122.jpeg 20250929-150134.jpeg

What we'll be up to in October

  • Omar: Probably merge folk2
    • Omar: Try to fix some remaining crashes
    • Omar: Try to test -atomically in production
    • Omar: Work on animation port
  • Omar: Continue trying to configure gadget projector
  • Omar: Maybe stereo-calibrate gadget and do some UI experiments with the full stereo setup (segmentation, projection-mapping, lassoing)

Omar

Andrés

newsletters/2025-09.1759442161.txt.gz · Last modified: by osnr

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki