jlm-blog
~jlm

6-Jun-2023

The Shockwave Flash that was

Filed under: web — jlm @ 09:55

swf is dead, a closed-source project shut down by its owner (Adobe) a few years ago.
Kazerad, best known as the artist-author of the web comic Prequel Adventure, wrote a touching eulogy for it on twitter here.


[Read it “unrolled” (all 15 parts together) here.]

26-Apr-2023

How is this glibc deadlock still unaddressed?

Filed under: programming — jlm @ 13:29

Why Programming is Hard, Volume CXX: the maintainers of critical pthread implementations will ignore multiple bugfixes from parallel programming experts for a longstanding deadlock bug for three years and counting.

24-Apr-2023

Do not meddle with the Application Binary Interface

Filed under: programming — jlm @ 15:18

Why Programming is Hard, Volume CXIX: a comprehensive explanation by JeanHeyd Meneide of how ABI stability stops us from having nice things despite enormous amounts of high-quality work on ABI-consistency and related issues. Naturally, it’s a dispiriting read. Fortunately, half a year later there’s this follow-up on how to fix it.

29-Nov-2022

twitcode #5: Extract HyperRogue achievements from log file

Filed under: programming — jlm @ 17:28

The game HyperRogue is very interesting. Its main gimmick is that it’s played on a hyperbolic plane (surface with negative curvature) instead of an Euclidean plane (surface with zero curvature) like 99.99% of 2-D games are. Playing in this kind of geometry is compellingly mind-bending. Other than the geometry involved, the main way the game differs from typical roguelikes is that the player character doesn’t gain levels or skills in the course of play — instead, the game opens up new “lands” with new environmental challenges and/or monsters with new attributes as the player demonstrates their skill by meeting the unlock requirements for each land.

The game supports “achievements”, where whenever your gameplay meets the condition of some challenge (some very easy, some nightmarishly hard, most of medium difficulty), it records this in a log file. Of course, met achievements aren’t all that the log file contains, but it’s nice enough to start each “met achievement conditions” record with “ACHIEVEMENT” and a marginally-descriptive achievement name, followed by other relevant information. Unfortunately, you can’t get a list of your fulfilled achievements merely by running  grep '^ACHIEVEMENT ' hyperrogue.log  because the game logs when you fulfill an achievement’s conditions separately for every run, not just the first run to fulfill it. So, to extract the records of each achievement’s first fulfillment, we ignore any record with an achievement name we’ve seen before and print out the line otherwise (ie, if we haven’t seen it before), which is nigh-trivial in awk [link]:

/^ACHIEVEMENT / {
    if (!($2 in ach)) {
        ach[$2] = 1;
        print;
    }
}

At 86 characters, it’s the fifth example from me of “twitcode” (programs under 140 bytes). And being in awk, it’s the fifth language I’ve twitcoded as well.

20-Nov-2021

Who’s logic bombing whom?

Filed under: covid, humor, web — jlm @ 16:58

This is how we know Star Trek is fiction:
[Available vaccines are unavailable]

This kind of thing is how humans break computers in that world. Here in reality, it’s how computers break us humans.

15-Apr-2020

One line of javascript to be console friendly

Filed under: web — jlm @ 08:38

From early on in styling this blog, I’ve had the sidebar on the top right, with the main blog content flowing against it, then after it ends lower in the page, below it. (You won’t notice this if your browser is very wide, as I cap the width of the main body at 50 em, but if you shrink it some you’ll see this.) Frankly, I’m surprised this is so unusual in blog and related webpage themes, which generally keep the space beneath sidebars empty, just wasting that space. (At least, when it’s not filled with ads.) This is super easy to do: in the page’s layout, have the sidebar’s markup come before the main body and give it the CSS style rule float: right. The browser will do everything from there, filling the page with the content that follows the sidebar’s markup, line wrapping when it hits the sidebar while also filling the space below it, doing a better job than most javascript-based layout renderings do.

There’s only one thing I consider a problem with this technique. In text console browsers (lynx, links, elinks, etc.), it shows the sidebar before the main content because the sidebar is in the markup earlier, which is way less friendly than if it appeared after. If I move it after the body, then it shows up better on the console, but now it’s at the bottom of the page in the graphical browsers used by all sane people, which is no good. I’ve had a soft spot for the console browsers from almost my first encounter with the web, long before I started this blog. The reasons for that is another story, but there’s no way I’m going to sacrifice the view in graphical browsers for improving the console browser experience, so I’ve kept the sidebar earlier in the markup than the main content all 15 years I’ve run this blog. And all that time I’ve felt tiny, insignificant tinges of regret for not offering a better experience for the extremely rare visitor from a console browser.

Every so often I’d think about tweaking WordPress to swap the order of the main content and the sidebar if the user-agent was a console browser, but that seemed inelegant and ugly, plus likely to be a pain with doing it in PHP, learning the appropriate WordPress internals, and likely having to carry a patch forward across WordPress versions. Or I’d think about doing it in javascript: have the sidebar be after the content in the markup so it shows up well in the console browsers that don’t execute javascript, but run a script to move it earlier in the graphical browsers that do. But then I’d have to learn javascript and DOM manipulation, which seemed like it was going to be a pain too.

Well, it turns out it is so not a pain it’s almost funny. I’m familiar with giving elements “names” with the id HTML attribute, for use in sub-page links and CSS #-references. Those names turn out to be great for getting DOM handles in javascript: just call document.getElementById("TheName"). And moving an element from where it is in the original markup to inside another element is just NewEnclosingElement.appendChild(ElementBeingMoved). Putting those together, I simply:

  • Replaced the <?php get_sidebar(); ?> in the theme’s header.php file with <div id="sidebar"></div>
  • Gave that element a float: right CSS rule
  • Added this to the theme’s footer.php file:
    <?php get_sidebar(); ?>
    <script type="text/javascript">
    document.getElementById("sidebar").appendChild(document.getElementById("menu"))
    </script>
    

(WordPress names the <div> that encloses the sidebar “menu”. I picked the name “sidebar” for the <div> which “menu” gets moved into.)

And … that’s it. The blog now looks like I want it to in both lynx and firefox. I probably shouldn’t have waited 15 years to look into this!

31-Mar-2020

TIL: gshadow has user lists

Filed under: linux — jlm @ 21:37

While I was chatting (well, rapid-fire emailing) with a friend who works as a system administrator, he dropped a bit of Linux trivia on me: It’s not just /etc/group which has user lists, the /etc/gshadow file also has user lists — more than /etc/group does, even! After the crypted password is a list of group administrators, then a list of shadow members. The former have the ability to change the group’s password as well as its membership using the gpasswd command. The latter can make the group be their primary group by calling newgrp without needing a password. (See man gshadow.)

21-Mar-2020

Simple Scala puzzle

Filed under: programming — jlm @ 10:46

Who can guess what this tiny* Scala program does?

object O extends App {
    val x = 123456789L
    val y = 0F
    val z = x − (if (true) x else y)
    println(z)
}

(Apparently this mysterious snippet had been going around a while ago, but I only recently encountered a variation.)

Answer: Prints “−3.0”.

Why?

Short answer: The if/else causes x to get promoted to Float, which rounds it up to 123456792.

Long answer after the fold.

(more…)

17-Feb-2020

Unit tests are not enough

Filed under: programming — jlm @ 20:48

[I wrote this for another blog back in 2011, but it was lost to public view when that blog disappeared. It’s still valid today, though!]

In one of our datastructures, there’s an entry for a 64-bit unique resource identifier. This turned out to be a little too vague a description: Is it an 8-byte array, a 64-bit wide integer, or an instance of a 64-bit UUID class? One of our developers though one thing, and another thought another. No problem, right? The first compile by the one who chose wrong will show the type error. Except we’re using Python, so no type checking until the code runs. Still no problem, because our devs wrote unit tests, so the type error will show up on their first run, right?

Unfortunately, unit tests help not an iota in situations like this. The developer expecting UUID objects writes unit tests which consume UUID objects, and the dev expecting byte arrays writes unit tests which produce byte arrays.

So, integration tests, then? It turns out our devs did these too, verifying that their code integrated with the fancy datastructure class, but this still didn’t catch the mismatch! This is because the datastructure class doesn’t actually do anything with the resource identifier that would trigger a type check: it just accepts it as an entry in a slot when an item is inserted, and gives it out as one of the slot entries when items are looked up, and Python is happy to let an instance of any type pass through unchecked.

It’s only when we plug everything together that this trivial type mismatch shows up. So the moral: Make end-to-end tests early. You need them to turn up even problems as basic as this, and the earlier you find problems, the better.

2-Feb-2019

Less is more, CPU edition

Filed under: general, programming — jlm @ 17:11

I fixed an interesting bug recently. By way of background, I work on industrial robotics control software, which is a mix of time-critical software which has to do its job by a tight deadline (variously between 1 and 10 ms) or a safety watchdog will trigger, and other software that does tasks that aren’t time sensitive. We keep the timing-insensitive software from interfering with the real-time software’s performance by having the scheduler strictly prioritize the deadline-critical tasks over the “best effort” tasks, and further by massively overprovisioning the system with far more CPU and memory than the tasks could ever require.

The bug (as you may have guessed) is that the deadline was sometimes getting missed, triggering the watchdog. What makes the bug interesting is that it was caused by us giving the system too much excess CPU and memory!

The deadline overruns happen when the computer runs best-effort tasks. It only runs those tasks a small fraction of the time, but no matter, they shouldn’t be interfering with the deadline completion at all (and having our software fail its deadlines is unacceptable, of course). The real-time tasks’ peak usage is only about a quarter of the computer’s CPU capacity, and the system gives them that always: 100% of the time they want CPU, they get CPU. They are never delayed, and never have to wait on a resource held by a best-effort task. When they miss the deadlines, it’s always because they’ve gotten jobs that take the usual amount of work to complete, and had their usual amount of time to do it, yet the jobs somehow just take more time to finish. There’s no resource contention, nor are the caches an issue.

Yet when the best-effort tasks execute, the calculations done by the real-time tasks run slower on the same CPU for the same job with the same cache hit rate and with no memory or I/O contention. What’s going on? After hitting some false leads, I discovered that they’re going slower because the CPUs are running at a lower frequency. It turns out the CPUs’ clocks have been stepped down because they’re getting too hot. (Yes, the surrounding air is much warmer than it “should” be, but we don’t have a choice about that.)

The computer is hot because all the CPUs are going at full blast, because all of the best-effort tasks are executing because the computer can fit them all in memory. Half a minute later, the tasks are done, the computer cools off, the CPU frequency gets stepped back up, and the deadline overruns cease. An hour later, the hourly background tasks all go again, the fans spin up to full, but they’re not enough and the CPU frequency steps down, hence the watchdog alerts about missed deadlines.

Okay, maybe we should change the background tasks so they execute in a staggered fashion. But before thinking about how I might do that, I tried disabling ⅔ of the computer’s CPUs instead. The hourly processing now takes 200s instead of 30, but it’s still far below 3600, and that’s what matters. Now the computer stays nice and cool, so the CPUs stay nice and quick, and the deadlines all get met. We were using too many CPUs to get the calculations we needed to get done fast, done fast. Who’d’a thunk?

Powered by WordPress