Who pays the cost an interface hides?
Zero-cost abstractions, a different allocator, concurrency inside a component: an interface spares callers the details, but time, memory and coordination costs do not vanish. They change hands.
Questions in this reading · 10
- Where did the hidden cost go?
- How many execution orders can one serial program allow?
- How does an unauthorized read become visible?
- Must a framework deliver its promises through a browser runtime?
- Must a concurrent design expose concurrency to its callers?
- Who guarantees the cost observed in one compilation?
- Who keeps an interface simple?
- How does a fallback allocator return a block to the allocator that supplied it?
- Once Lisp can generate machine code, what does it still need to call an existing C++ function?
- Who pays for specializing generic code?
Where did the hidden cost go?
One hash lookup may probe a dense run of entries; another may chase pointers to distant addresses. Carruth’s data-structures talk follows the actual accesses. Carry that question into his talk on abstractions: tidy instructions at one call site can coexist with compilation costs or a calling-convention penalty at another boundary. A performance promise needs a workload, a boundary and an account of who pays.
Passages and timestamps · 2
maximize the cache locality of of handling a collisionit just means the cost is paid somewhere elseHow many execution orders can one serial program allow?
Expand a product from the left or the right and the scratch work differs while the answer agrees. Wolfram uses this to illustrate a property one must check for a system of rewrite rules. Keller faces a physical instruction stream: find dependencies, start independent operations and track which results may finish in which order. First specify what an observer gets to see. For the algebra example the final expression suffices. A processor must also respect observable effects such as memory ordering, so checking only the final number can miss a broken promise.
Passages and timestamps · 4
you'll get different ordersyou'll always get the same answergo figure out the dependency graphwhat order should these operations finish inHow does an unauthorized read become visible?
Two workers can finish in a fortunate order and draw a perfectly good frame. Destiny adds a second observation during development. The engine checks the dependency graph and validates access permissions when code touches resources. Alongside “Was the final frame right?” ask “Did any job read something it had no permission to read?” That question can expose a violation even on the lucky schedule.
Passages and timestamps · 2
identifying unsafe patterns, but it's going to be doing it during developmentevery time that you access the data, it's checking dynamically right there and then for whether or not you have permissionMust a framework deliver its promises through a browser runtime?
Harris adds a time dimension to a module boundary: the declarative component interface used by developers need not become the mechanism that runs in a user’s browser. Introducing Svelte 3, he proposes moving some organizational work to the build step and generating code that updates the page. For optional features such as transitions and bindings, his aim is to generate support only for what is used. Separate the capabilities a tool offers from the code one application actually ships. To examine an abstraction, list the intent callers need to express, then ask which decisions are already knowable at build time and which require runtime information. This extends the idea of hiding implementation decisions; the talk alone does not establish that arbitrary programs will become smaller or faster, and this treatment does not verify the on-screen code or benchmark results.
Passages and timestamps · 2
a framework doesn't need to be a thing that runs in the browserwe don't need to include the code that makes that feature possibleMust a concurrent design expose concurrency to its callers?
Pike first gives the scanner and parser their own control flow, then discusses an interface exposing only a request for the next lexical item. Separate three decisions in a module’s promise: how a caller obtains that item, how the scanner preserves its place, and whether multiple activities actually execute simultaneously. He says concurrency can enable parallelism without requiring it; conceptual independence is not a throughput guarantee. In questions he admits he has not measured performance and would consider another buffering implementation if it became critical. The example therefore supports a discussion of separating an interface from internal organization, rather than proving channels are always faster. This treatment does not verify the displayed code or use the initialization restrictions described then to explain current Go.
Passages and timestamps · 2
concurrency enables parallelism doesn't require itto be honest I have not measured itWho guarantees the cost observed in one compilation?
Turner adds a verification boundary to a module’s promises. Describing an optimization after adding const, he does not claim every compiler guarantees it: only one compiler and standard-library combination he had tried produced that result. If callers want both a readable interface and a cost bound, distinguish the functional contract from cost evidence in the actual build. A project can record toolchain versions, optimization settings, target machine and outputs to inspect again after changes. That checklist follows from his qualification; it does not mean this site reproduced the demonstration or that objects, lambdas and lifetime wrappers have no overhead in every setting.
Passages and timestamps · 2
the compiler happened to be able to optimize it.that was the only combination I foundWho keeps an interface simple?
Rob Pike uses Go imports to show how one line for the caller still leaves naming, scope, and linking for the language to handle. Eskil Steenberg describes the work from the other direction. He sketches what the caller needs before filling in the implementation. Both approaches leave details with the people maintaining the library or language.
Linus Torvalds adds a time dimension in his Q&A. Kernel maintainers treat continued operation of existing userspace programs as a constraint, and he acknowledges that breaks still occur. Making an interface easy to use today and keeping it usable for existing callers are two different parts of its life.
Passages and timestamps · 4
it interacts with things like scoping, naming, information hiding, isolation, linking,I start from the outside usuallywe don't break user spacewe do break user space sometimesHow does a fallback allocator return a block to the allocator that supplied it?
Alexandrescu uses memory allocation to show that an interface must work in both directions for allocators to compose. In the design he presents, a pointer and length travel together as a block. If the primary allocator cannot fulfill a request, a fallback allocator can try. At deallocation, the same interface still needs to know where to send the block. His example routes it by asking the primary allocator whether it owns the block. To check whether such an interface composes, follow one block through both steps. Who can supply it, and what part of the contract gets it back to the right place?
Passages and timestamps · 2
it has the pointer and the lengthif you want to write an allocator you got to make it composableOnce Lisp can generate machine code, what does it still need to call an existing C++ function?
In his talk on Clasp, Schafmeister explains how it compiles Lisp and how it connects to C++ libraries. The Clasp compiler emits LLVM intermediate representation, which LLVM lowers to machine code. To call the C++ function in his example from Lisp, he also gives the binding library a Lisp name and a C++ function pointer so the library can generate a wrapper at compile time. Following the call reveals two handoffs. What does the compiler pass to the backend? How does the wrapper connect the name visible from Lisp to the existing function?
Passages and timestamps · 2
implemented a new Common Lisp that uses LLVM as the backend.and it builds the wrapper function at compile time.Who pays for specializing generic code?
Smith uses Coalton to describe how a generic interface can hand the choice of concrete operations to the compiler. Given the types, the compiler generates specialized code for the relevant combinations. This requires access to source or an appropriate representation and can produce more code. Evaluating the performance examples therefore involves runtime, compilation work and generated code size.
Passages and timestamps · 2
much more than safety.you can't monomorphize if you don't have the source code.Try it on your own example
Pick an abstraction you rely on. What does it save you, and which cost does it push to the compiler, the runtime or another team?