Forgot your password?
typodupeerror

Comment Re:I don't currently use Rust (Score 1) 161

heapless is quite useful in many contexts, yes.

As for what my design goals are, it's a pretty typical LRU map. I assumed that the name would tell you what the purpose is, but perhaps not. Please excuse me for belaboring if you are already familiar with these concepts; I don't know what you know, so I figure it's better to be clear. If you do, skip the next paragraph.

An LRU (Least Recently Used) cache is a cache that has a fixed maximum size and when a new item is added that would cause it to exceed that upper bound, it discards the "oldest" entry in the cache, where "oldest" is defined as least-recently used. An LRU map is similar but it is "primary storage" not cache, but still with a fixed capacity so when you try to put more in it than it can hold it has to discard something, and it does that by discarding the least-recently used item.

In my case, I'm writing code that services client code running on other CPUs in the same SoC. The client transactions are moderately long-running, each involving a sequence of requests delivered over the course of a few seconds, though some sessions legitimately go much, much, longer, and each such session requires me to track a non-trivial amount of state, not so much for efficiency as for security; I can't hand the internal state back to the caller because that might allow an attacker to mutate it or roll it back (if rollback weren't a concern, I could outsource a MACed copy of the state). I keep the operation state in a map structure, keyed by an operation ID. But clients can die and clients can misbehave, so I can't safely rely on the clients to always send me the termination message that allows me to clear the operation state.

So, I need some way to ensure that my map doesn't fill up with stale operation data, preventing new operations from being started. LRU eviction is a cheap and effective method. But this means that sometimes clients are going to send a request for an operation that I have evicted, so I have to return an error message. I could just always say "Operation ID not found", but then clients have no way to distinguish between cases where they just waited too long and cases where I suffered a failure or was reset. The clients often respond to these different failure modes in different ways.

For that reason, I keep a "recently-evicted" list -- but that also has to have a fixed size limit. In practice, my recently-evicted list consists of two lists, an "old generation" list and a "new generation" list, both with fixed size limits. Every time an operation is evicted, it's added to the "new generation" list. When the new-gen list is full, I move it to the old-gen list (in practice, I really just change which list is considered new and which old; no need to copy it). This is a cheap way to "age" the eviction records, without actually having to track their age in an LRU fashion (which would ~double the per-entry storage required, halving the number of evictions I can track). When a request for an unknown operation ID comes in, I search both lists to see if the ID has been recently evicted. If so, I remove the ID from the list and report the error to the caller. The reason for removing is to make space for a new eviction record, to maximize the scenarios in which I can notify clients.

Regarding your comment about encapsulation being overused... this is not such a case. The purpose of encapsulation, properly applied, is invariant maintenance, and there are some important invariants that have to be maintained for the LRU map to work. One of those is that insertion must execute the eviction logic, so even if I could move the map out temporarily, that would create an opportunity for bugs if the calling code does not correctly handle eviction and maintenance of the recently-evicted list. Another (less crucial, but still important) is that the recently-evicted list should only contain entries for clients that haven't yet been notified.

That said, there actually a good argument that the `recently_evicted` method is conceptually non-mutating and I should use interior mutability. Either that or I should rename it to "remove_eviction_record", so it's clear that it is inherently a mutating operation. I will do one of those two things on Monday -- thanks for helping to improve my code. I would prefer the rename for clearer semantics, but interior mutability will allow me to avoid the extra map lookup, so I'm leaning that way.

One other comment about something you said, which you might find interesting: You said that in Rust, moves are cheap. This isn't really true. More precisely, it isn't any more or less true in Rust than in any other language. Regardless of language, when you move data, you must copy it, and you're paying the cost of that copy. What makes moves so useful in Rust is not that they're cheaper in time or space but because of the marvelous move invariant that is enforced by the compiler. Namely, that moved-from values cannot be referenced.

To see how important that is, compare with C++, which also allegedly supports move semantics. The modern C++ style makes heavy use of move semantics. But C++'s move semantics are broken in a way that makes them less efficient and more difficult to use safely, and that's because C++, like C, always allows code to reference any value that has a name. That means that moved-from values can be referenced, which means it's critical that moved-from memory not be left in an invalid state when interpreted under the invariants of its type. So the rule is that moved-from C++ objects must be left in a "valid but unspecified state". In practice, this translates into the move ctor/optor having to do work in the moved-from memory, zeroing pointers and whatnot, in order to ensure that what's left behind upholds the invariants of the type, and it means that C++ structs that support move-from must have some valid but not semantically-significant state they can be in.

What makes Rust's move semantics easier to work with, more efficient and safe is that there's no need to ensure that the moved-from memory is in any kind of valid state, because the compiler will not allow the moved-from memory to be accessed. Another way to think about it is that the moved-from memory no longer has any type, so no longer has to maintain any type invariants. It's fine to leave behind bit patterns that used to be pointers or whatever, because those bit patterns will never be used.

Coming from 35 years of C++ programming, this was something of a revelation to me when it hit me a few months ago. And it's the real meaning of "moves are cheap", which isn't a comment about time or space, but a comment about invariant maintenance.

Comment The timeline is of note. (Score 1) 37

It seems worth noting that one of the items in Wyden's rather pointed inquiry is the fact that the feasibility of doing this is known to have been demonstrated for the DoD by outside people familiar with it at least as early as 2016; so while this is the first confirmed case of adversarial use it's the outcome of at least a decade of just ignoring the problem; and a significantly longer period of failing to reasonably anticipate the problem. It's not like there's No Such Agency you could ask about "how could you spy on someone with the internet even?" if you wanted to know how well or poorly readily available information matched a nation state signals intelligence apparatus.

Purely as a matter of cellphones being expensive and somewhat tepidly capable in the before times I assume that there was a period within living memory when merely telling people not to Gordon Gekko on their DynaTAC where the russians can hear you was good enough; but that would have clearly and rapidly been getting less true for at least a quarter century.

Comment Re:What about Wine? (Score 2) 53

Without a real ABI-32 Wine will have to use an emulation layer if the processor can't run natively as a 32 bit process.

Now that Linux is getting a growing game player quota, there are gonna destroy a functionality that make that works?

Since Windows never supported this unusual 32/64-bit hybrid, it will have no impact on WINE.

It's actually kind of a cool idea, though. To someone like me who grew up on 8-bit and 16-bit architectures and is regularly taken aback at the size of data structures on 64-bit platforms -- 16 bytes just for a pointer and a length? -- being able to cut those down while still being able to run at full speed [*] on modern hardware sounds really useful.

[*] Assuming it's really full speed. I suspect there's some overhead.

Comment Re:I don't currently use Rust (Score 1) 161

I checked and, indeed, trying to "move" the "hashmap" generates code to copy enough stuff onto the stack to blow it. I'm going to look into using Pin to let the compiler know that none of that stuff is moveable. Thanks!

Er, actually, the above is incorrect and was a result of my contrived test example. With the real data structures there is no risk of anyone moving them because the code that creates them returns *only* a &'static mut. Effectively, no stack frame ever has ownership of the structures, so there is no risk of them being moved. This is all pretty obvious, actually, and essentially necessary. If there is no heap then everything is either stack-based or something akin to a global.

Comment Re:I don't currently use Rust (Score 1) 161

Yeah, so you apparently missed that I have no heap and the "hashmap" isn't actually a hashmap... and it's actually in the same not-really-moveable space as the data it holds. It would be interesting to look into what would happen if I tried to move it; I think the compiler doesn't actually know that it's not moveable and would generate code to copy it to the stack. That would be more expensive than copying the "contained" data item, since it actually owns its lookup tables by value, rather than holding pointers to heap allocated structure.

As I said, your big-system biased intuitions don't really hold here.

Comment Re:I don't currently use Rust (Score 1) 161

Moving something out of a hashmap and then back into it isn't cheap. I mean, both operations are O(1), but that's amortized and hides significant overhead. I think it's well worth returning a &mut to avoid that, even in the common, std case. In the my noalloc case, it's considerably more complicated than that: The referenced memory isn't really moveable (and it's not really a hashmap). In practice, it would be "copy the data to the stack, leaving the original in-place, then make sure to copy the mutated version back to the original location". The stack consumption of that approach would be worrisome.

This is where the big-system biases of some of the Rust community work against it, and what fuels the certainty of C programmers that C is the right language for tiny devices. In C there would be no question -- you'd just look up the data in the map and return a pointer to it. Very efficient, no needless waste of several hundred bytes of precious stack space or any need to find some other memory region to copy it into. You say that "moves in Rust are cheap" but whether that's true is extremely context-dependent, and it's basically always the case that a pointer is even cheaper.

Unfortunately, the risks of the C approach are very well-understood, and my point in the post with which I entered this discussion was that Rust can be just as good for space and cycle-efficient low-level code as C while also providing significant security and safety benefits. Your arguments would seem to undermine my point about Rust's utility, except that your big-system biases are not, in fact, universal in the Rust ecosystem. There are plenty of people who understand the constraints of writing code on a device with 64K total RAM and a 1K stack who are writing Rust code and ensuring that the language is a good fit.

Comment Definitely a bad look... (Score 4, Interesting) 35

The whole 'responsible disclosure' preaching and the not-terribly-subtle threats seem particularly bad given that there's an entire industry of actively more dangerous people who are not only treated as legal but actively courted by state agents and cops(and often even less savory customers, though they tend to be cagey about those); the ones who actively seek to keep vulnerabilities quiet so that they can continue to sell exploit tools and services based on them. Throwing zero days on github isn't ideal vs. getting them fixed; but it gets them fixed faster than if Cellebrite wants to hang on to a bitlocker bypass or Trenchant, and L3Harris Technologies Company, wants to keep selling 'network investigative techniques' that can bypass default windows defender configurations or whatever the situation is.

From the outside it's hard to know whether MS actually mistreated the researcher badly enough to justify their displeasure(the consensus appears to be that MSRC was never the best to deal with and has actively gone downhill; but this person's position seems significantly angrier than average) or whether they are perhaps wound a little tight; but implying that their legal status is the same as people actively running attacks against user systems is blatantly false and totally ignores the class of researchers who do actively run attacks while being treated as respectable.

It's a particularly bad look when at least Facebook got into a public legal fight with the NSO group over their nerd-merc work against their users; not like that actually solved the problem of attacks on cellphones; but it was an all-too-rare case of industry pushing back against the 'respectable' arms dealers; and not one that MS has an analog to.

Comment Re:Now we know (Score 1) 122

Just how insane he is.

Not insane at all, just uninterested in the well-being of anyone other than himself.

If this happens, Trump will end up being in charge of deciding which companies get the plutonium, and those that do the best job of making Trump feel, er, appreciated, will get the nod. Also, I expect Trump to address safety concerns by setting up a multi-billion dollar fund of taxpayer money to address any necessary cleanups or other issues, a fund that is under his sole ultimate control, without congressional or any other oversight (c.f. Venezuela oil fund, "anti-weaponization fund", etc.). Maybe it'll have confidential quarterly reports issued to the NRC's board of directors (which is traditionally independent but now thoroughly controlled by Trump thanks to SCOTUS' allowing Trump to fire anyone in the executive branch and Trump's immediate action to fire Christopher Hanson as chair of the NRC board and replace him with a lapdog).

Slashdot Top Deals

Line Printer paper is strongest at the perforations.

Working...