MoreRSS

site iconJeff KaufmanModify

A programmer living in the Boston area, working at the Nucleic Acid Observatory.
Please copy the RSS to your reader, or quickly subscribe to:

Inoreader Feedly Follow Feedbin Local Reader

Rss preview of Blog of Jeff Kaufman

House Party Dances

2025-05-31 21:00:00

Julia and I are in CA for LessOnline this weekend, and we're staying with friends. It happened that they were hosting a party, and while this is not a group of dancing friends they asked if I'd be up for leading some dancing. One of my hosts let me borrow their violin (which I'll also have with me today at LessOnline if anyone would like to jam some), and the space was small enough not to need any amplification.

Playing and calling at the same time is only something I can do if I play simple tunes I know very well while calling simple dances, and both my playing and calling suffer from the multitasking. But my hosts encouraged me not to worry about this and thought we'd have a good time. I think they were right!

We ended up having about seven couples, mostly adults, but also including about three kids 3y-5y who were very excited to dance. I made sure to choose dances that would work for the whole group, and it was definitely the right call to include the kids: their excitement was highly infectious.

Our hosts had moved furniture earlier in the day, clearing an open area about 15 ft square. This ended up being slightly tight for a few figures, but was mostly pretty good.

The crowd was enthusiastic about dancing, and while not everyone danced we easily had enough people to make the dances work. We ended up doing (I didn't write this down at the time; this is approximately right):

Break for cake Another break, pretty long

I think Sasha was the most popular, followed by the set dancing (Longways and Circle), followed by waltzes. It makes sense that the waltzes were less popular: Julia and I taught the basic folk waltz step, but getting into the improvisational lead-follow dynamic and the kinds of figures you might want to lead would have needed much more time and have worse ROI. I'm not sure if I would include these if doing this again, though it was nice to have a few slower-paced dances.

I'm glad I was able to help make this happen!

Comment via: facebook, mastodon, bluesky, substack

Cross-posting to Substack

2025-05-29 21:00:00

Historically people kept up with blogs via RSS, but it's been on its way out for over a decade. These days receiving posts via email is popular, and I should probably make my posts available this way. I considered implementing my own emailing system, but bulk email is (or at least was, I'm not up to date here) a pain. Instead I decided to start cross-posting to Substack: jefftkaufman.substack.com. This will be yet another way to read my posts, similar to the LessWrong mirror and my text-only FB cross-posts.

I have a full RSS feed of all my posts, and Substack imported it fine. It doesn't look like there's an option to do ongoing RSS-based imports, but copy-paste seems to work well enough; I did this post and the previous one that way. At some point I'll look into automatic cross-posting, though right now it looks like Substack doesn't support anything good. And if I'm going to reverse engineer something I'll start with their comments implementation, since I always want to rehost comments.

One aspect that's a bit eerie is the URLs: both Substack and my blog would use /p/post-name-in-title-case as the url for a post titled "Post Name In Title Case". I've been doing this since 2013-10-28 and Substack got started in 2017 so I know I didn't copy them ;)

Comment via: facebook, lesswrong, mastodon, bluesky, substack

Quick Minimal Playhouse

2025-05-28 21:00:00

When I came home from work today Lily was very excited: she wanted to build a playhouse for our 1y11m neighbor Jo. Lily had gotten parental permission, the yard had space, and I was the only remaining obstacle. I'd normally be pretty excited about a project like this, but it was 5pm and I was signed up to cook dinner.

On the other hand, we'd recently been reading the Little House books and Farmer Boy and we'd been joking about how the fathers in the books built things unrealistically quickly. Most recently, Almanzo's father builds a bobsled from scratch in a single a day, including identifying and felling the trees. Still, most of the unrealism comes from what they had to work with: no pre-cut pre-seasoned lumber, no power tools, pegs for fasteners, etc. Perhaps with modern tools we could build a minimal playhouse together and still have dinner on the table by 7pm? Sounds fun!

A key component here is that I already had everything I needed (DIY Pantry Staples) on hand from past projects: plywood, 2x3s and 2x4s, screws, wood glue, plastic sheeting, staples, saw, drill, belt sander.

I decided to make an open lean-to, though three sides would be partly blocked by bracing. I found a piece of plywood about the right size, and glued and screwed 2x3s to the outside edge. Lily and I cut vertical supports at a 22.5° angle, 42" for the back two and 60" for the front two. We carried it all outside and assembled the rest upside down. Nora helped glue on the supports:

Once the supports were in place it needed diagonal braces or it was not going to be sturdy enough. Lily helped me cut these as well, and we glued and screwed these on. I sanded any sharp corners, and then stapled plastic sheeting over the top.

Here's a 3y11m y/o for scale:

And an 11yo:

Possibly we'll paint it, but if not it's done!

It took ~1hr20min from end to end. The longest step was probably when I needed to get a specific piece of wood out from under a large pile of other lumber. And of course this speed was only possible because of the simple design, having the materials and tools on hand, and the speed of power tools.

It was fun, and the kids and I are looking forward to giving to to Jo!

(I made sure to publish this tonight before going to bed, because otherwise Julia will see the pictures on my camera roll and worry that I'm abusing her absence to construct unapproved housing units.)

Comment via: facebook, lesswrong, mastodon, bluesky, substack

Does Sort Really Fall Back to Disk?

2025-05-27 21:00:00

The unix sort command is clever: to sort very large files it does a series of in-memory sorts, saving sorted chunks to temporary files, and then does a merge sort on those chunks. Except this often doesn't work anymore.

Here's what I see if I run man sort and look at the documentation for --buffer-size:

use SIZE for main memory buffer

That's pretty terse! What does my Mac say?

Use size for the maximum size of the memory buffer. Size modifiers %,b,K,M,G,T,P,E,Z,Y can be used. If a memory limit is not explicitly specified, sort takes up to about 90% of available memory. If the file size is too big to fit into the memory buffer, the temporary disk files are used to perform the sorting.

Makes sense! But then the docs for --temporary-directory say:

use DIR for temporaries, not $TMPDIR or /tmp; multiple options specify multiple directories

And these days /tmp is often memory-backed, via tmpfs. This changed in Fedora 18 (2013) and Ubuntu 24.10 (2024), and is changing in Debian 13 (in a month or two).

It seems to me that these days it would be better for --temporary-directory to default to /var/tmp, which is preserved across reboots and so will generally be backed by disk even on systems that use tmpfs for /tmp. In the meantime, sort --temporary-directory /var/tmp will do the trick.

Comment via: facebook, lesswrong, mastodon, bluesky, substack

Example of Splitting a PR

2025-05-25 21:00:00

I'm a big fan of small focused PRs: it's much easier to tell whether they're actually doing the right thing. For example, I recently ran into a common scenario where I started adding some functionality, and realized this required some refactoring. The refactoring also made it clear that the original code was missing some important test coverage, so I added some tests. I ended up with a big set of changes which combined large refactors and a major (intended) change to the output.

This is a bad combination: if my refactoring accidentally changed functionality in a way not captured by the tests we might miss it. And with so many changes it's going to be hard for the reviewer (and even the author) to keep it all in their head at once. Instead, it would have been better if I had first done the refactoring and added tests, and then followed up with the new functionality. The first PR would be a bit noisy but conceptually straightforward and easy to validate because it produces exactly the same output for all inputs. The second PR would be very clean, but would require careful validation to verify that the changes really are an improvement.

I might be tempted to say "oh well, I should have approached this differently, I'll do better next time" but really I did need to combine these two changes when writing them: I didn't know for sure what I would want for the refactoring until I'd tried to use it to implement the functionality change. So if my plan was to do better next time I wouldn't actually do any better.

Instead I took advantage of version control to split my changes into two sets, in an order that is optimized for validation:

  1. I committed all my changes to a new branch, jefftk-new-feature, with a message that only mentioned the feature I was adding, not the refactoring or the new tests.

  2. I made a new branch off of jefftk-new-feature to represent the refactoring and new tests: git checkout -b jefftk-refactor.

  3. On jefftk-refactor I deleted everything related to the new feature, leaving only the refactoring and new tests. I verified that the output was unmodified, as you'd expect for a refactoring-only change. I committed this, with a message that only mentioned the refactoring and tests.

  4. I interactively rebased (git rebase -i HEAD~2) this branch to squash the two commits into one. I only kept the refactoring commit message. This branch is now ready to be my first PR, and is ready to send out for review.

  5. I switched back to jefftk-new-feature, and ran git rebase jefftk-refactor. This rewrote my original big commit as if it was a follow-up to the refactoring commit. There were a few merge conflicts I needed to resolve manually, but nothing too painful. This branch is now ready to be my second PR, and I'll upload it to GitHub so I can reference it in the first PR in case the reviewer is interested in taking a peek at what's coming.

This was a bit more work, but I think it's definitely worth it: I'm much more confident that my refactoring didn't break anything, and I expect it to be much easier to review.

Comment via: facebook, lesswrong, mastodon, bluesky, substack

Qualitative Fit Testing

2025-05-22 21:00:00

As I wrote about last week, it's worth it for everyone to have an elastomeric respirator in case of emergencies: the chance of a severe pandemic is high enough that even under reasonably conservative assumptions the return on investment is ~10x. Because not every mask fits every face and a poorly fitting mask will leak air around the seal—it doesn't matter how good the filters are if they're bypassed—it's good to try on a range and see what's good. I invited some people over to try out a range of masks and play with fit testing.

There are a range of ways to see if a mask fits. A good first test is to put it on and see if you feel air leaking around it. If it's possible to cover the intake you can breath in while wearing it, and you should feel it pull tight against your face. These tests are often enough to rule out masks, and are pretty quick.

Once you've identified a mask you think is plausibly a good fit you can do qualitative fit testing. The idea is, you make some particles with a strong taste or smell, and see how well they can get in while you're wearing the mask. If they can't get in, especially as you move your head around, talk, and grimace, then your seal is pretty good. I got a kit (Gerson QLFT50M) which included several components:

  • A hood the test subject wears over their head, so you don't need to fill the whole room with particles.

  • Saccharin (sweet) or Bitrex (bitter) solution, which have a strong taste you should notice clearly if it makes it through the mask.

  • A squeeze-bulb nebulizer, to turn the strong-tasting liquid into tiny strong-tasting particles.

You put the liquid in the nebulizer, poke the nebulizer through a hole conveniently provided in the front of the hood, and squeeze out particles.

One key thing about the setup is there are two solutions and two nebulizers. One is the weaker sensitivity solution, which you breathe maskless to ensure you can detect the test particles, and the other is a stronger [1] test solution, which ideally doesn't make it through the mask in detectable quantities.

While this seems to be a common design, I really don't like how it relies on the two nebulizers performing identically. Especially since initially mine didn't: the sensitivity testing nebulizer worked great (easy to squeeze, you can see the little bubbles going, fine mist) while the fit testing nebulizer worked much less well (harder to squeeze, needed more adjustment, much less little bubble movement, less mist). After people went home I played with the nebulizers and got a better feel for how to adjust them to get them both performing well. This would have been good to do before!

I'm planning to bring the masks and test kit to LessOnline, which I expect to be enriched for people who would be interested in this sort of thing.


[1] You use a much larger difference for saccharin (100x in the fit test) than Bitrex (12.5x). I'm still confused about this, but some asking Gemini suggests it's because "the 'low, but generally detectable' concentration and the 'significantly stronger, but not unbearable' concentration are vastly different relative to each other for these two substances due to their intrinsic taste properties."

Comment via: facebook, lesswrong, mastodon, bluesky, substack