The fun thing here is that it seems GCE has security checks to prevent people from creating millions of free accounts instead of one paid one but they are bypassed by Chrome. If this is true then I would expect to see it appear in an antitrust case at some point.
What’s actually going on here is that the post is a total fabrication. None of it ever happened. And the blog owner didn’t even come up with the story themselves, they stole it off a Tweet thread. That’s why the story is so incoherent and none of the technical details make any sense: they were mangled during translation.
(The first versions of this post to go around explicitly stated this was fictional. But given the main point of this post is clearly to generate leads for the blogger’s consulting business, it’s easy to see why that disclaimer was removed.)
It’s more likely that said security checks are bypassed by making a few requests from each real user’s browser, as opposed to making a lot of requests from some server. Like how DDoS is much harder to detect than DoS from a single source; the developer made a botnet out of users of the extension.
(I work for Google but am unfamiliar with such security checks.)
One neat aspect of the Microsoft authentication system is that it works for both Microsoft’s consumer account system (Microsoft Account) and Microsoft’s business authentication system (Office 365). This means that if you, like me, don’t want to authenticate to Tailscale using an account that you don’t pay for, you can easily get a $3/month email subscription to Office 365 and use that. I’m far more confident that Microsoft isn’t going to yeet me out of my paid Office 365 subscription than I am that Google won’t shut down my Google Account.
I’m far more confident that Microsoft isn’t going to yeet me out of my paid Office 365 subscription than I am that Google won’t shut down my Google Account.
Being able to pay for the account you’re using for SSO isn’t really a differentiator here. Google also has both free consumer and paid business account types, that you could use for authentication.
Fair point, but there’s an easily obtainable customer support phone number for Office 365. As far as I can tell, without access to your account there’s no way to reach Google Workspace support. I think that’s a better way to explain what I failed to articulate.
I’m among those people who repeatedly claim that atomic commits are the one advantage of monorepos. This article tells me it isn’t a strong reason because this ability is rarely or never used. Maybe, I’m not a big fan of monorepos anyways.
I agree with the author that incremental changes should be preferred for risk mitigation. However, what about changes which are not backwards-compatible? If you only change the API provider, then all users are broken. You cannot do this incrementally.
Of course, changes should be backwards compatible. Do Google, Facebook, and Microsoft achieve this? Always backwards compatible?
You’d rewrite that single non-backwards compatible change as a series of backwards compatible ones, followed by a final non-backwards compatible change once nobody is depending on the original behavior any more. I’d expect it to be possible to structure pretty much any change in that manner. Do you have a specific counter-example in mind?
We used to have an internal rendering tool in a separate repo from the app (rendering tests were slow).
The rendering tool ships with the app! There’s no version drift or anything.
When it was a separate repo you’d have one PR with the changes to the renderer, another to the app, you had to cross-reference both (lot easier to check changes when you also see usage changes by consumers), then merge on one side, then update the version on the other side, and only then do you end up with a nice end-to-end change
It’s important to know how to make basically any change backwards compatible, but the costs of doing that compared to the easy change is extremely high and error prone IMO. Especially when you have access to all the potential consumers
That approach definitely works, but it doesn’t come for free. On top of the cost of having to roll out all the intermediate changes in sequence and keep track of when it’s safe to move on, one cost that I see people overlook pretty often is that the temporary backward compatibility code you write to make the gradual transition happen can have bugs that aren’t present in either the starting or ending versions of the code. Worse, people are often disinclined to spend tons of effort writing thorough automated tests for code that’s designed to be thrown away almost immediately.
You don’t have to, at least if you use submodules. You can commit a breaking change to a library, push it, run CI on it (have it build on all supported platforms and run its test suite, and so on). Then you push a commit to each of the projects that consumes the library that atomically updates the submodule and updates all callers. This also reduces the CI load because you can test the library changes and then the library-consumer changes independently, rather than requiring CI to completely pass all tests at once.
I’m working in an embedded field where microcontrollers imply tight resource constraints. That often limits how many abstractions you can introduce for backwards-compatibility.
A simple change could be a type which has “miles” and then “kilometers”. If you extend the type (backwards compatible) it becomes larger. Multiplied by many uses all across the system that can easily blow up to a few kilobytes and cross some limits.
Another example: A type change meant that an adapter had to be introduced between two components where one used the old and the other the new type. Copying a kilobyte of data can already cross a runtime limit.
I do admit that microcontrollers are kinda special here and in other domains the cost of abstractions for backwards-compatibility is usually negligible.
I’ve used maps in a load of programs. I sometimes want the behaviour of C++‘s std::map, where the object have a total ordering (that I define) and iteration should reflect that ordering. I can’t think of a single time when I’ve wanted iteration order to be insertion order. About the only use case I can think of is if you’re implementing some kind of event coalescing mechanism, where you insert things into a set (i.e. don’t insert them if equivalent events are there already) and remove them in FIFO order but that’s such a niche use case that I’d probably want a custom data structure for it rather than trying to use the standard one.
The benefit of insertion order iteration is that it is deterministic. Years of experience in JS basically said you can’t do anything that is semi deterministic without suffering pain. So the options are similar to Go, etc that deliberately randomize enumeration order or going fully deterministic.
Couple that with the desire to support mutation while iterating a map/set and insertion order is the only thing that really makes sense.
The latter requirement makes sense as for whatever reason mutating structures while enumerating them is a common idiom in web content so having new structures that don’t support the idiom would just result in people continuing to use objects as their associative arrays and simply add Map and Set to the things that they complain about :)
The benefit of insertion order iteration is that it is deterministic
I think that’s actually a problem, not a benefit, because it means that you can easily depend on a property of a specific data structure implementation. LLVM, for example, has a build mode that reverses iteration order for all container types for which iteration order is not defined. This catches places where people have accidentally depended on iteration order for deterministic output (so does testing on multiple platforms, because the order often depends on memory layout and that will differ between memory allocators). If you require iteration order to be explicitly specified (undefined, insertion order, total order of elements) as part of the data structure’s definition then you never get into the case of someone replacing a map with a different implementation and removing deterministic behaviour that you depend on. It’s a dangerous default because you can always move from undefined to defined (and implement undefined as defined in different ways on different platforms) without breaking code, but you can’t move from defined to undefined.
JS is a language for the web, so nothing can be undefined. The only bits that still have real variation allowed are those that for historical reasons could not be merged without breaking existing content, and even those are edge cases (adding and removing properties on an object’s prototype chain while iterating the object properties being the classic example).
So start from “the behavior must be defined” - for consistently random enumeration between engines you’d need to specify that different iterators of the same object would need different enumeration order, that enumerating the same object (without mutation) multiple times would require different enumeration order each time, etc
And then we get to the elephant in the room - consistent enumeration in the face of mutations while iterating. You would need all extant iterators to visit new elements, and skip deleted ones, without visiting existing entries again, unless a property was removed and re-added.
Order of insertion is not particularly expensive, works for disparate types for keys, and has an easily explained semantic effect, and also works cleanly when mutating while enumerating the same object.
Sometimes I want a consistent order, and I don’t care what it is. If insertion order is convenient, then it’s probably good enough. For instance, I’ve worked with APIs that dumped a hashmap as JSON where the key order changes between every call. It’s usually just a minor nuisance, but it would be nice if it were consistent.
Why do you care what the order of keys in a json object is? It’s explicitly non specified.
If I read some JSON file, modify it, and then write it back again then it’s quite nice if the key order just stays the same. Especially if you have them in a git repo so diffs are actually useful. This is not an uncommon scenario. For example yarn add pkg changing the entire order of package.json and package.lock wouldn’t be especially great. The same applies to other file formats that don’t specify an order such as YAML or TOML; in many of those cases it’s even more important as often the file is also intended for manual editing.
From the spec, it seems that json objects can have duplicate keys, so in theory you’d need a multimap :-). Goes to show how underspecified json is. In my little corner of the programming world, people parse json objects into association lists, so the order is preserver anyway, but thank you for the relevant use case.
Usually, it’s just annoying, like when trying to diff the output between calls. Although it can cause real problems, such as when the hash sum of the response is used as a cache key (not that there aren’t other ways to fix that).
If you are using some software that generates json as its on disk representation (e.g., PowerBI) and you need to version control it you can have really bad diffs if it changes every time it’s loaded and saved. Makes it hard to do proper pull requests. That’s an example of a bad serialization format pick by the software maker, but something you just have to live with as a user.
Edit: I just said the same thing as arp242. This is why you read the child comments before reply…
I can’t think of a single time when I’ve wanted iteration order to be insertion order.
One example is where you’re getting data from some external source (file, command output), don’t care about certain duplicates, and use a map to filter those out. But you do want to preserve the original order in which the output was given. Basically, what the uniq command does, except without the requirement that lines need to be adjacent. I want this on a somewhat semi-regular basis, and have written more “map + array for order” loops than I can remember.
I think if I need something like this I’d start with a set for detecting duplicates and an array / vector for the canonical version. The set wants very fast probing, so I’m happy with something that’s optimised for random access and I don’t care if it supports iteration at all. As the data comes in, I check if it’s in the set, if it isn’t I add it there and append to the array. In C++, I’d probably use a facade object in the set that actually looked in the array for the data, which then looks basically like the data structure described in the article. If I needed this more than once, I could wrap it up in a reusable template class (and provide both the map and array types as template parameters so I could tune it for a particular use case).
I don’t really know C++, but in Go a map is the “obvious” and easiest data structure to use. In Python you can use sets, but a lot of times the performance difference (if there even is any, it will probably use more memory but might run a few ns faster) will be negligible and using a single dict will be easier. In Ruby or PHP you’d probably use a hash or array, etc.
Either way, my point is merely that this is actually a somewhat common-ish use case. And besides, if you’re going to preserve order then you might as well default to insertion order. A lot of times order won’t matter at all and insertion order is a reasonable non-surprising default.
I think I’d then phrase this slightly differently to the article. It’s not that the map hates you, it’s that Go and Python hate you by privileging one map type over all others. The most efficient map implementations do not provide a stable sort, so by privileging one map implementation you’re left in a world where people either hate you because using an efficient map for their use case is more clunky or they hate you because using a map that has the properties that they need for their use case is more clunky.
The general lesson is: one-size-fits-all data structures are a bad idea. This is a lot more obvious for built-in strings than for built-in maps because a lot of languages define a single concrete string representation and the use cases for strings are very different across application workloads.
As I mentioned in another comment: in the case of Python it was an accidental property that fell out of making dicts more efficient, so clearly it’s not all that horribly inefficient.
Aside: in Go maps aren’t ordered (explicitly randomized actually). I just used this as an example where it would be convenient.
I 100% agree. If I want this particular behavior (a queue without duplicates) I do it by combining a queue and a hashset (my main use case is graph traversal). In general that might involve keeping things in the set even after they’re processed, which this jack-of-all-trades, master-of-none data structure fails to accomplish.
Why do people insist on having one single data structure that does everything?
this jack-of-all-trades, master-of-none data structure
In the case of Python it was more of an accidental side-effect that fell out of a new dict implementation. People liked it and it was added to the language specification. It’s more memory-efficient and either equal or faster in runtime performance. It was inspired by the more performance-focused PyPy.
If it was slower or if there was some weird confusion between data structures like PHP’s “arrays” – which can be either an an “array” or “hashmap” with some surprising “magic” conversions and fairly high performance impact – then, sure, I’d agree. But nothing at all was sacrificed here, and it’s convenient in quite a few cases. There is no trade-off, no “mastery” was lost. It’s just a win.
There’s a loss in that it’s now unnecessarily constraining future implementation options. Every promise is a loss of flexibility. Even if an order-preserving hash table was the best available implementation now, who is to say that it’s still the best one in two years?
Given that Python has managed quite well without this more efficient implementation for almost 30 years, that this has been researched to some extent and spectacular breakthroughs in the foreseeable future are unlikely (though not impossible of course), and that insertion order is considered a desirable feature by many, I think the trade-off is a pretty good one.
Python has managed quite well without efficiency in all areas. I wouldn’t look there if you’re looking for arguments about data structures where efficiency matters.
I also agree that insertion order is something that I’ve wanted incredibly rarely.
“It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures.” - Alan Perlis
If you have one data structure you can have many types of transformations. It’s harder to get that level of depth with many data structures.
That said you do probably want more orthogonal data structures. Otherwise, you can have bad performance problems. E.g., using a linked list for everything in functional languages can have nasty performance issues.
PHP preserves insertion order and that’s used for all kinds of things. It can be used to deduplicate arrays. It can be used to round-trip tree structures (e.g. edit a config file without sorting the keys). It’s even used for DSLs.
It can be thought of as a vector that comes with a fast lookup index. Of course you could achieve the same (and more flexible) with a vec and a separate hashmap, when it’s a single data structure it’s just easy, and there’s no need to worry about keeping consistency between vec and its index.
In the implementations that I’m aware of (Python and Rust’s indexmap), this sort of hashmap tends to be faster in macro-benchmarks. This is likely due to iteration being faster over the dense array of KV pairs, and iteration is pretty common. Certainly that is worth caring about.
I definitely reach for indexmap all the time. Insertion order is useful sometimes, but sorting the map is also frequently useful. Also, just being able to quickly access KV pairs via indexing is a great way to avoid hashing in many cases.
This is likely due to iteration being faster over the dense array of KV pairs, and iteration is pretty common.
That’s very workload dependent. A lot of the places I’ve used maps, I never iterate: I want associative lookup and that’s why I chose a map as the interface to the underlying data structure. In some uses, I really care about fast insertion and removal, in some I care about lookup performance at the expense of everything else. In some I care about a broader balance. If I care about iteration performance then I might want to use a map with guaranteed iteration order but for the use cases where I don’t care about iteration performance (I’d guess that most of the code I’ve written that iterates over a map does so purely for debugging / asserting invariants on the map contents) I don’t want a set of additional constraints.
Last time I benchmarked a map on anything I cared about, Hopscotch and Robin Hood maps had the best overall performance (one was slightly lower memory consumption, the other slightly faster throughput). The maps with guaranteed iteration order that I tried were measurably worse in both metrics.
It is buried in the footnotes of the post, but the ultimate reason behind going closed source is that Google built their enterprise GDrive syncing client for mac off a fork of osxfuse. The original author of osxfuse feels entitled to some compensation for that and is doing his damnedest to make it happen.
I do not know the history of this software. But (3-clause) BSD is compatible with GPL so you can license your contributions (new code) under GPL and distribute the whole work under GPL.
That applies to the previous BSD style licence too. I.e. if a giant megacorp like Google wanted to support this single developer they could have, but they chose not to. I don’t think GPL would have changed this. I suspect it would have meant they would have just developed the necessary features themselves, in house.
The benefit is reproducible hermetic builds and never having builds with undeclared dependencies that only work by accident. No big deal for tens of files, but absolutely essential with thousands of files in half a dozen languages. I would have killed for bazel at one point in my life (but not installed a JRE… There are limits).
As for why the post just highlights problems, it sounds like they’re making a new tool. Need to have problems to solve for that.
In which case “Recommended Improvements for Bazel” seems like a more apropos title. That’s really my only issue with the piece: the title doesn’t match the content.
The chronology is clearly that he got to the page for updating payment information without resetting the password, just by following the link. The password reset was only done later to collect information on “Eve”. So the step 6 as written is correct.
You’re half right, in that Sony added an ARM coprocessor to the console for that purpose. It’s just that something went wrong, and the downloads have to be handled by the main CPU even in rest mode :) Sony never elaborated on the exact reason. They just implied that the ARM processor wasn’t fast enough, but that sounds like total nonsense. A potato can handle a 100Mbps HTTP download.
Network effects. Default choices. AWS launches with linux support, so people pick linux, then they pick docker, etc etc etc.
Linux does solve a great many problems that OpenBSD does not. (Well, it offers a great many features and buttons and such which look like solutions. :)) I’m not sure that one operating system that solves all problems is the best approach, though. there’s a lot of disagreement about how even a desktop OS should work and how components should fit together.
I had also heard that performance on newfangled hipster tasks (http service, MP scheduling, databases) was nontrivially worse, so I started trying to run an OpenBSD instance on AWS to run some side by side tests in order to invalidate those rumors. Apparently one guy once heard of a file you can UUCP from sunsite.unc.edu that enables 80-character mode so that you can give it a shot, but that was from a Byte magazine reader article so I cannot vouch for its veracity. I had to give up when my eyelids started twitching uncontrollably.
The reputation for security doubtless partially stems from the fact that installing the thing requires delivering the One True Ring to a locked basement cabinet guarded by leopards in an abandoned mausoleum underneath a nuclear waste disposal site in Afghanistan. Minimization of attack surface and all that. Somewhere, a Haskell core developer is putting down his glasses and rubbing his eyes in admiration.
And historically, perofrmance. I haven’t seen any good performance comparisons in the last few years (that I remember anyway), but several years ago there were several comparisons done that showed somewhat poor openbsd (and netbsd as I recall) scalability (multi-core performance, etc). Linux has often been one of the top performers in those types of benchmarks.
The following HN comment from Brendan Gregg might be worth a read. It’s answering in detail basically the same question, just for Illumos rather than OpenBSD: https://news.ycombinator.com/item?id=12837972
The reply is a touch acerbic, but makes some good points too I think. Like why not just give up when linux is 1000 developers ahead? Because half of them are wasting their time inventing ten different tracing frameworks. Ok, admittedly it would be nice for openbsd to have one perf tool, but I think we’re not so far behind as it may seem.
Also, for something like inteldrm, there’s a team of devs who keep churning the code, which causes kettenis some struggle when he tries to import it, but on the whole we get most of the benefits of that driver at a considerable manpower discount. The precise economics aren’t quite that simple, but not all of the effort spent on linux is locked in linux either.
Sure, I agree on both of those points. Some effort will be wasted to duplication and churn, some will have little effect as it can be easily reused by other projects.
But if the larger developer base is at all positive, it will add up over the decades. E.g. 20 years ago the common wisdom would have been that the BSD TCP stack was both battle hardened and state of the art, while the one in Linux was flaky and scaled badly with load. It’s definitely the other way around these days (to a different extent for different BSDs), with a steadily increasing delta. And then repeat the same story over dozens of subsystems.
Clearly there are things that more manpower doesn’t help with. Like deleting code to reduce attack surface; I’m pretty sure that the larger the team, the harder that is to achieve :) It’s not that developers of non-Linux operating systems should just give up, or anything like that. But the assertion at the start of this thread on Linux’s technical inferiority doesn’t feel realistic to me.
That interesting comment reminds me a lot of the Worse is Better effect that got UNIX to dominance in the first place. There were better systems including some focused on good docs, reliability, and high security. I write about them a lot. ;) They lost with them being in close to legacy mode or gone depending on the product/project. The Linux situation, esp as Brendan Gregg describes it, looks like a repeat of that with Linux doing it to the other UNIX’s. I already knew this seeing the likes of SGI, IBM, and Oracle get on the Linux bandwagon despite having proprietary UNIX’s to push. In contrast, OpenBSD is trying the UNIX version of The Right Thing. It will fail in broad sense because that always happens.
It’s destined to a niche of those that care about The Right Thing. You’ve all done a great job keeping it up despite your filter on the kind of contributors you accept and not giving into market’s crap that much. I saw Theo backtrack a bit with VMM admitting OpenBSD might have to do a little more for marketability. Still, the project will probably need a like-minded sponsor with lots of money and/or talent to break past what we’ve seen so far since The Right Thing is always swimming upstream vs Worse is Better which sometimes creates tsunami’s. Those of us focused on quality might always be also-rans in larger scheme of things. (shrugs)
How do you search for a package in OpenBSD? How do you get a description in your search results? You can search package names by downloading the index.txt file from the packages directory on a mirror. But anything more sophisticated you have to use the ports tree and the janky makefile system with non-intuitive syntax and cryptic errors to do any interesting searches.
It’s actually possible to download and install a Linux distro that comes with a desktop environment, installs quickly, and works fine right away. When I was first getting into non-Windows operating systems in middle school, I tried out OpenBSD because the whole secure OS thing sounded cool to me. I screwed with it for hours, felt like I was getting nowhere, then gave up and installed Linux Mint.
I run OpenBSD now, but I’m also a systems programmer / SRE at a database company, so I’m not exactly an “average user” that represents the trend of the market.
yep. i use pkg_info, i browse the ports mailing list, read the website, and also look at my mirror of choice from time to time.
i just use cwm that’s in base. i had previously used gnome and xfce from packages. i reckon my willingness to read documentation mostly gets me to where i need to be… other things figured out by trial and error, mailing list, and searching the internet.
i don’t think it’s a bad thing. i’m implying that everyone saying openbsd is difficult to install or use aren’t reading these things and i don’t really understand why.
Ahhhh. I’m somewhat amazed that I didn’t know that. But I will still call it unintuitive. See, I expected something like pkg_search, or to find something searching for “search” in man pkg_info. Searching “OpenBSD search for package” on Google returns a bunch of ancient results about ports. It IS mentioned in the packages FAQ though, but the preview text on Google mentions ports specifically. So I must have searched for it, seen those results, rolled my eyes, looked in the man pages, seen nothing, and decided to just download the index file.
Compare to most Linux package managers, which when run with no arguments tell you the commands to install and search. The word “search” specifically is much more well known than “query” because of Google.
So even though I’m a bit lazy and it’s clearly my fault for not knowing this as a sophisticated user, I think helping rather than blaming the user isn’t the right strategy towards getting adoption. Linux is really good about that, OpenBSD not so much.
or to find something searching for “search” in man pkg_info.
Query is close. I guess it’s a difference in terminology.
Searching “OpenBSD search for package” on Google
This seems to be a common trend among Linux users, google is consulted with more authority than local documentation. I personally do the same thing.. when finding issues with linux machines I always go to google first.. the crap documentation (often lacking entirely) has trained me to do so!
I think helping rather than blaming the user isn’t the right strategy towards getting adoption. Linux is really good about that, OpenBSD not so much.
Where was there lack of help and who is doing blaming?
I realize query and search are close, but search is definitely the layman terminology.
Googling isn’t just a Linux strategy, that’s what Windows and Mac users do too. Apple in particular is pretty good about making their support pages show up on Google.
I didn’t originally mean people blaming the user directly, but rather a UX that “blames the user” in its design, and for OpenBSD I mostly see this in docs or commands. Not being able to find the -Q flag in the man page by searching (querying?) for search is poor UX. It implicitly becomes the users fault for not reading the whole manual. There are no examples either, where surely a common operation like search would be demonstrated. And OpenBSD commands don’t self document or provide assistance, whereas Linux commands will often list the most common usage if you don’t type a valid command. Using OpenBSD feels a bit RTFM, wheras on Linux stumbling around in an interactive session is much more viable, as most things try and point you in the right direction.
This goes both ways, on OpenBSD it’s way more likely that if you can’t figure something out, it actually is documented somewhere. But that documentation could be more accessible and searchable.
But also user blaming happens directly on misc@. I am part of no other community that ever makes me think “wow these people are such outrageous stuck up assholes, I’m not even sure I want to be a a part of this anymore.” Mostly OpenBSD people are intelligent, articulate, and kind. For example, I’ve had nothing but good experiences talking with OpenBSD folks on lobsters. But wow some of the stuff on misc makes my blood boil.
I’ve considered contributing to OpenBSD docs to make them more accessible, especially FAQs / new user guides, but my experiences on misc have always stopped me. I worry that I’ll be shot down for going against the OpenBSD philosophy, and I won’t even be rightly told why, just be told I’m a moron. It sucks, because I love OpenBSD and I want to share it and make it easier for people to learn about, but I feel discouraged from contributing.
still don’t understand how you missed -Q in the pkg_info man page because it’s right at the top in synopsis.
I wanted to search, I scanned the first line for search, /searched for search, moved on. I’m just too impatient. But a lot of people are too impatient, and worse a lot of people just don’t care enough to persist.
That was Files-11 on OpenVMS with versioning and stuff. Especially integrated with high-uptime stuff like clustering and distributed lock manager. Or NonStop’s Guardian with its crazy reliability. Or first system (SCOMP) certified to high security that added ring and segmented protection to them with system-wide security policy.
I do agree it was one of best decades for applied IT with all kinds of awesome shit happening based on what CompSci had worked on in 1960’s-1970’s with better hardware available. A lot of things started coming together that couldn’t before.
Or they need to run certain applications that are only available on Linux, or they need drivers that are only available on Linux, or they want a filesystem that has more features than UFS/FFS, etc.
OpenBSD picked a niche and perfected itself in that niche. I think it is a shining example that picking one problem and solving it well, is often better than being a jack of all trades, master of none.
(Which does not mean that it cannot be used as a general purpose OS with some care.)
Even as someone who likes the FSF, I doubt many Linux users are there because of (rather than despite, or indifferent to) the GPL. It’s not hard for me to imagine an alternate universe without the BSD lawsuits where FreeBSD or something got popular as the mainstream free hobbyist Unix in the 1990s, and I seriously doubt FSF diehards would have been able to keep more than a handful of people from going with that bandwagon, had it developed (and had they actually wanted to).
Same reason as many other similar situation throughout the industry. People know something else, a lot is built on other systems, marketing, and once you have a certain amount of people using tech X it’s really hard to use something else.
Another side effect that kicks in with Linux Distributions, Operating Systems and Programming languages is that at many places if you introduce a technology that isn’t the currently dominant one you will be personally blamed for every single bug or different obstacle it has. It will often be blamed on it, despite also existing on the dominant OS.
Something related is that sadly a lot of software that companies and people end up using at some point is written in unnecessarily non-portable ways. I once worked at a company that used a software running a bash script (stored inside a string in a program) and it had a typical non-portable #!/bin/bash instead of #!/usr/bin/env bash. As usually I’d report that and even create a pull request on a huge (in terms of stars, in the tens of thousands) and very hyped software, expecting it would be accepted. After being baffled that the authors didn’t even know about /usr/bin/env and what it does, a link to Wikipedia didn’t help either the conversation stalled. Since that project was being used by the front end developers I kept patch sets for such things around.
And while those tiny things are really not hard in general these tiny things add up. I know the problem even exists if you don’t use Ubuntu, but for example Alpine in the Linux world.
Having these kind of portability issues leads to the dominant technology in a field to quite often not be the best. The most famous example is how long Internet Explorer stuck, despite Opera and the Mozilla browser, until Firefox came along.
When there is a lot of users and developers even pretty bad technology can stick, because there will be widely used workarounds for problems, there will be progress on fronts, even when the architecture is flawed, etc. Change is rarely that quick, especially when many parties are involved and put their money and effectively lives on it.
Of course that doesn’t mean that Linux is bad and OpenBSD is great, just that technical superiority or being a bit better than others usually is far from a good indicator for dominance in a field. Especially if marketing and politics have a big presence, but even without. People simply need to have heard of it and a good reason to switch and get into something new to them and settle there. When there is no direct financial effect, that is significant enough people tend to not just switch utilities from one moment to the next. And even when you know OpenBSD really well and are convinced its better introducing that in an existing company might not be an option. Of course you can always switch, but why give up a safe, well-paying job with great coworkers for an operating system?
Honestly, I found this utterly fascinating for some strange (fetishistic?) reason.
When I get home, if I remember, I would like to grep through four additional large and source-available and influential older code bases that seemed to have escaped mention: IBM MVS 3.8, Xerox UTS/CP-V, MIT/GE/Bell/Honeywell/Bull/etc Multics, and UM MTS (Michigan Terminal System).
These all should predate BSD in many cases by decades and might well have earlier references.
I had a look through MULTICS, didn’t find anything plausible. The other three sound like they’re worth a shot :)
(MULTICS was a bit of a pain. Also AFAIK the only public source for it is a late-stage source dump with no versioning history; so it’s hard to say with any degree of confidence when any specific part was written).
There are actually two releases, if I recall correctly - an unofficial “leaked” one that originated from MIT, and the officially blessed one from Bull.
While neither release contained modern revision control, major edits and changes were always described in the comments at the beginning of the file, so you are right, it is of little help here; unless you could discover an “XXX” comment referenced in a source file with a pre-81 header — but even then it would likely be impossible to prove the edit date definitively.
I think the sources for the other older systems I mentioned resides on SHARE and Bitsavers.
Google develop it, but that’s where it ends. They have basically no control over about getting any kernel level changes installed on actual running devices. 75% of the active Android Install base is on versions over two years old. And the much slower release cadence makes things even worse.
If they add a new TCP feature today to Android, in a year it’ll probably be running on 0.5% of devices. If they add a feature to QUIC on mobile Chrome, it’ll be on 80% of the devices in two months.
An actual modulo is just too expensive (unless N is a constant, and the compiler has an optimization for that). For the other two designs you don’t need to use mod to support arbitrary values of N, a single conditional will suffice to wrap the values. That won’t work when the indices have an unlimited range.
(Also, surely only powers of two are going to be factors of another power of two?)
Turns out my entire post is wrong. In lock free code, you actually want the opposite of this trick - keeping reader/writer pos separate. If you have head + length you need to update both variables (e.g. enqueue is rougly head++ length–) which requires a CAS loop that’s twice as wide.
If you’re doing an SPSC ring buffer you can keep the reader/writer pos as non-atomic ints in separate cache lines, and add an atomic flag to each node saying whether it was last read or written. You don’t waste any slots and you only get contention when the queue is nearly empty/full.
The fun thing here is that it seems GCE has security checks to prevent people from creating millions of free accounts instead of one paid one but they are bypassed by Chrome. If this is true then I would expect to see it appear in an antitrust case at some point.
What’s actually going on here is that the post is a total fabrication. None of it ever happened. And the blog owner didn’t even come up with the story themselves, they stole it off a Tweet thread. That’s why the story is so incoherent and none of the technical details make any sense: they were mangled during translation.
(The first versions of this post to go around explicitly stated this was fictional. But given the main point of this post is clearly to generate leads for the blogger’s consulting business, it’s easy to see why that disclaimer was removed.)
Thank you for the added context!
that’s hilarious =P
But now I have to flag and hide this post =P
It’s more likely that said security checks are bypassed by making a few requests from each real user’s browser, as opposed to making a lot of requests from some server. Like how DDoS is much harder to detect than DoS from a single source; the developer made a botnet out of users of the extension.
(I work for Google but am unfamiliar with such security checks.)
and then chrome can be automated with webdriver or playwright
One neat aspect of the Microsoft authentication system is that it works for both Microsoft’s consumer account system (Microsoft Account) and Microsoft’s business authentication system (Office 365). This means that if you, like me, don’t want to authenticate to Tailscale using an account that you don’t pay for, you can easily get a $3/month email subscription to Office 365 and use that. I’m far more confident that Microsoft isn’t going to yeet me out of my paid Office 365 subscription than I am that Google won’t shut down my Google Account.
No, you just have to worry about Solarwinds.
Being able to pay for the account you’re using for SSO isn’t really a differentiator here. Google also has both free consumer and paid business account types, that you could use for authentication.
Fair point, but there’s an easily obtainable customer support phone number for Office 365. As far as I can tell, without access to your account there’s no way to reach Google Workspace support. I think that’s a better way to explain what I failed to articulate.
I’m among those people who repeatedly claim that atomic commits are the one advantage of monorepos. This article tells me it isn’t a strong reason because this ability is rarely or never used. Maybe, I’m not a big fan of monorepos anyways.
I agree with the author that incremental changes should be preferred for risk mitigation. However, what about changes which are not backwards-compatible? If you only change the API provider, then all users are broken. You cannot do this incrementally.
Of course, changes should be backwards compatible. Do Google, Facebook, and Microsoft achieve this? Always backwards compatible?
You’d rewrite that single non-backwards compatible change as a series of backwards compatible ones, followed by a final non-backwards compatible change once nobody is depending on the original behavior any more. I’d expect it to be possible to structure pretty much any change in that manner. Do you have a specific counter-example in mind?
We used to have an internal rendering tool in a separate repo from the app (rendering tests were slow).
The rendering tool ships with the app! There’s no version drift or anything.
When it was a separate repo you’d have one PR with the changes to the renderer, another to the app, you had to cross-reference both (lot easier to check changes when you also see usage changes by consumers), then merge on one side, then update the version on the other side, and only then do you end up with a nice end-to-end change
It’s important to know how to make basically any change backwards compatible, but the costs of doing that compared to the easy change is extremely high and error prone IMO. Especially when you have access to all the potential consumers
That approach definitely works, but it doesn’t come for free. On top of the cost of having to roll out all the intermediate changes in sequence and keep track of when it’s safe to move on, one cost that I see people overlook pretty often is that the temporary backward compatibility code you write to make the gradual transition happen can have bugs that aren’t present in either the starting or ending versions of the code. Worse, people are often disinclined to spend tons of effort writing thorough automated tests for code that’s designed to be thrown away almost immediately.
You don’t have to, at least if you use submodules. You can commit a breaking change to a library, push it, run CI on it (have it build on all supported platforms and run its test suite, and so on). Then you push a commit to each of the projects that consumes the library that atomically updates the submodule and updates all callers. This also reduces the CI load because you can test the library changes and then the library-consumer changes independently, rather than requiring CI to completely pass all tests at once.
I’m working in an embedded field where microcontrollers imply tight resource constraints. That often limits how many abstractions you can introduce for backwards-compatibility.
A simple change could be a type which has “miles” and then “kilometers”. If you extend the type (backwards compatible) it becomes larger. Multiplied by many uses all across the system that can easily blow up to a few kilobytes and cross some limits.
Another example: A type change meant that an adapter had to be introduced between two components where one used the old and the other the new type. Copying a kilobyte of data can already cross a runtime limit.
I do admit that microcontrollers are kinda special here and in other domains the cost of abstractions for backwards-compatibility is usually negligible.
I’ve used maps in a load of programs. I sometimes want the behaviour of C++‘s
std::map
, where the object have a total ordering (that I define) and iteration should reflect that ordering. I can’t think of a single time when I’ve wanted iteration order to be insertion order. About the only use case I can think of is if you’re implementing some kind of event coalescing mechanism, where you insert things into a set (i.e. don’t insert them if equivalent events are there already) and remove them in FIFO order but that’s such a niche use case that I’d probably want a custom data structure for it rather than trying to use the standard one.The benefit of insertion order iteration is that it is deterministic. Years of experience in JS basically said you can’t do anything that is semi deterministic without suffering pain. So the options are similar to Go, etc that deliberately randomize enumeration order or going fully deterministic.
Couple that with the desire to support mutation while iterating a map/set and insertion order is the only thing that really makes sense.
The latter requirement makes sense as for whatever reason mutating structures while enumerating them is a common idiom in web content so having new structures that don’t support the idiom would just result in people continuing to use objects as their associative arrays and simply add Map and Set to the things that they complain about :)
I think that’s actually a problem, not a benefit, because it means that you can easily depend on a property of a specific data structure implementation. LLVM, for example, has a build mode that reverses iteration order for all container types for which iteration order is not defined. This catches places where people have accidentally depended on iteration order for deterministic output (so does testing on multiple platforms, because the order often depends on memory layout and that will differ between memory allocators). If you require iteration order to be explicitly specified (undefined, insertion order, total order of elements) as part of the data structure’s definition then you never get into the case of someone replacing a map with a different implementation and removing deterministic behaviour that you depend on. It’s a dangerous default because you can always move from undefined to defined (and implement undefined as defined in different ways on different platforms) without breaking code, but you can’t move from defined to undefined.
JS is a language for the web, so nothing can be undefined. The only bits that still have real variation allowed are those that for historical reasons could not be merged without breaking existing content, and even those are edge cases (adding and removing properties on an object’s prototype chain while iterating the object properties being the classic example).
So start from “the behavior must be defined” - for consistently random enumeration between engines you’d need to specify that different iterators of the same object would need different enumeration order, that enumerating the same object (without mutation) multiple times would require different enumeration order each time, etc
And then we get to the elephant in the room - consistent enumeration in the face of mutations while iterating. You would need all extant iterators to visit new elements, and skip deleted ones, without visiting existing entries again, unless a property was removed and re-added.
Order of insertion is not particularly expensive, works for disparate types for keys, and has an easily explained semantic effect, and also works cleanly when mutating while enumerating the same object.
Sometimes I want a consistent order, and I don’t care what it is. If insertion order is convenient, then it’s probably good enough. For instance, I’ve worked with APIs that dumped a hashmap as JSON where the key order changes between every call. It’s usually just a minor nuisance, but it would be nice if it were consistent.
Why do you care what the order of keys in a json object is? It’s explicitly non specified.
In your case it’s probably an indication that the API uses a proper seeded hashtable internally, to avoid DoS issues.
If I read some JSON file, modify it, and then write it back again then it’s quite nice if the key order just stays the same. Especially if you have them in a git repo so diffs are actually useful. This is not an uncommon scenario. For example
yarn add pkg
changing the entire order ofpackage.json
andpackage.lock
wouldn’t be especially great. The same applies to other file formats that don’t specify an order such as YAML or TOML; in many of those cases it’s even more important as often the file is also intended for manual editing.From the spec, it seems that json objects can have duplicate keys, so in theory you’d need a multimap :-). Goes to show how underspecified json is. In my little corner of the programming world, people parse json objects into association lists, so the order is preserver anyway, but thank you for the relevant use case.
Usually, it’s just annoying, like when trying to diff the output between calls. Although it can cause real problems, such as when the hash sum of the response is used as a cache key (not that there aren’t other ways to fix that).
If you are using some software that generates json as its on disk representation (e.g., PowerBI) and you need to version control it you can have really bad diffs if it changes every time it’s loaded and saved. Makes it hard to do proper pull requests. That’s an example of a bad serialization format pick by the software maker, but something you just have to live with as a user.
Edit: I just said the same thing as arp242. This is why you read the child comments before reply…
One example is where you’re getting data from some external source (file, command output), don’t care about certain duplicates, and use a map to filter those out. But you do want to preserve the original order in which the output was given. Basically, what the
uniq
command does, except without the requirement that lines need to be adjacent. I want this on a somewhat semi-regular basis, and have written more “map + array for order” loops than I can remember.I think if I need something like this I’d start with a set for detecting duplicates and an array / vector for the canonical version. The set wants very fast probing, so I’m happy with something that’s optimised for random access and I don’t care if it supports iteration at all. As the data comes in, I check if it’s in the set, if it isn’t I add it there and append to the array. In C++, I’d probably use a facade object in the set that actually looked in the array for the data, which then looks basically like the data structure described in the article. If I needed this more than once, I could wrap it up in a reusable template class (and provide both the map and array types as template parameters so I could tune it for a particular use case).
I don’t really know C++, but in Go a map is the “obvious” and easiest data structure to use. In Python you can use sets, but a lot of times the performance difference (if there even is any, it will probably use more memory but might run a few ns faster) will be negligible and using a single dict will be easier. In Ruby or PHP you’d probably use a hash or array, etc.
Either way, my point is merely that this is actually a somewhat common-ish use case. And besides, if you’re going to preserve order then you might as well default to insertion order. A lot of times order won’t matter at all and insertion order is a reasonable non-surprising default.
I think I’d then phrase this slightly differently to the article. It’s not that the map hates you, it’s that Go and Python hate you by privileging one map type over all others. The most efficient map implementations do not provide a stable sort, so by privileging one map implementation you’re left in a world where people either hate you because using an efficient map for their use case is more clunky or they hate you because using a map that has the properties that they need for their use case is more clunky.
The general lesson is: one-size-fits-all data structures are a bad idea. This is a lot more obvious for built-in strings than for built-in maps because a lot of languages define a single concrete string representation and the use cases for strings are very different across application workloads.
As I mentioned in another comment: in the case of Python it was an accidental property that fell out of making dicts more efficient, so clearly it’s not all that horribly inefficient.
Aside: in Go maps aren’t ordered (explicitly randomized actually). I just used this as an example where it would be convenient.
I 100% agree. If I want this particular behavior (a queue without duplicates) I do it by combining a queue and a hashset (my main use case is graph traversal). In general that might involve keeping things in the set even after they’re processed, which this jack-of-all-trades, master-of-none data structure fails to accomplish.
Why do people insist on having one single data structure that does everything?
In the case of Python it was more of an accidental side-effect that fell out of a new dict implementation. People liked it and it was added to the language specification. It’s more memory-efficient and either equal or faster in runtime performance. It was inspired by the more performance-focused PyPy.
If it was slower or if there was some weird confusion between data structures like PHP’s “arrays” – which can be either an an “array” or “hashmap” with some surprising “magic” conversions and fairly high performance impact – then, sure, I’d agree. But nothing at all was sacrificed here, and it’s convenient in quite a few cases. There is no trade-off, no “mastery” was lost. It’s just a win.
There’s a loss in that it’s now unnecessarily constraining future implementation options. Every promise is a loss of flexibility. Even if an order-preserving hash table was the best available implementation now, who is to say that it’s still the best one in two years?
Given that Python has managed quite well without this more efficient implementation for almost 30 years, that this has been researched to some extent and spectacular breakthroughs in the foreseeable future are unlikely (though not impossible of course), and that insertion order is considered a desirable feature by many, I think the trade-off is a pretty good one.
Python has managed quite well without efficiency in all areas. I wouldn’t look there if you’re looking for arguments about data structures where efficiency matters.
I also agree that insertion order is something that I’ve wanted incredibly rarely.
If you have one data structure you can have many types of transformations. It’s harder to get that level of depth with many data structures.
That said you do probably want more orthogonal data structures. Otherwise, you can have bad performance problems. E.g., using a linked list for everything in functional languages can have nasty performance issues.
PHP preserves insertion order and that’s used for all kinds of things. It can be used to deduplicate arrays. It can be used to round-trip tree structures (e.g. edit a config file without sorting the keys). It’s even used for DSLs.
It can be thought of as a
vector
that comes with a fast lookup index. Of course you could achieve the same (and more flexible) with a vec and a separate hashmap, when it’s a single data structure it’s just easy, and there’s no need to worry about keeping consistency between vec and its index.In the implementations that I’m aware of (Python and Rust’s
indexmap
), this sort of hashmap tends to be faster in macro-benchmarks. This is likely due to iteration being faster over the dense array of KV pairs, and iteration is pretty common. Certainly that is worth caring about.I definitely reach for
indexmap
all the time. Insertion order is useful sometimes, but sorting the map is also frequently useful. Also, just being able to quickly access KV pairs via indexing is a great way to avoid hashing in many cases.That’s very workload dependent. A lot of the places I’ve used maps, I never iterate: I want associative lookup and that’s why I chose a map as the interface to the underlying data structure. In some uses, I really care about fast insertion and removal, in some I care about lookup performance at the expense of everything else. In some I care about a broader balance. If I care about iteration performance then I might want to use a map with guaranteed iteration order but for the use cases where I don’t care about iteration performance (I’d guess that most of the code I’ve written that iterates over a map does so purely for debugging / asserting invariants on the map contents) I don’t want a set of additional constraints.
Last time I benchmarked a map on anything I cared about, Hopscotch and Robin Hood maps had the best overall performance (one was slightly lower memory consumption, the other slightly faster throughput). The maps with guaranteed iteration order that I tried were measurably worse in both metrics.
Please,can someone post a working link to the dolan paper? Inquiring minds want to know!
http://drwho.virtadpt.net/files/mov.pdf
Thanks!
source
If he have used copyleft (GNU GPL) license, he would be able to do dual-licensing and negotiate that compensation.
He didn’t really choose the license though. This is a fork of macfuse, which was written and released as open source by… Umm… Google.
I do not know the history of this software. But (3-clause) BSD is compatible with GPL so you can license your contributions (new code) under GPL and distribute the whole work under GPL.
That applies to the previous BSD style licence too. I.e. if a giant megacorp like Google wanted to support this single developer they could have, but they chose not to. I don’t think GPL would have changed this. I suspect it would have meant they would have just developed the necessary features themselves, in house.
I read this and I don’t see how it is exceptional to “all the others”. All I got was a list of things that need to be improved.
The benefit is reproducible hermetic builds and never having builds with undeclared dependencies that only work by accident. No big deal for tens of files, but absolutely essential with thousands of files in half a dozen languages. I would have killed for bazel at one point in my life (but not installed a JRE… There are limits).
As for why the post just highlights problems, it sounds like they’re making a new tool. Need to have problems to solve for that.
In which case “Recommended Improvements for Bazel” seems like a more apropos title. That’s really my only issue with the piece: the title doesn’t match the content.
The chronology is clearly that he got to the page for updating payment information without resetting the password, just by following the link. The password reset was only done later to collect information on “Eve”. So the step 6 as written is correct.
they’re… on freebsd… they could’ve easily used ipfw queues to give lower priority to store downloads… omg
IIRC, the downloads are actually handled by the ARM SoC in the southbridge, for downloading while the main AMD SoC is off.
You’re half right, in that Sony added an ARM coprocessor to the console for that purpose. It’s just that something went wrong, and the downloads have to be handled by the main CPU even in rest mode :) Sony never elaborated on the exact reason. They just implied that the ARM processor wasn’t fast enough, but that sounds like total nonsense. A potato can handle a 100Mbps HTTP download.
Source: http://www.dualshockers.com/ps4-consumes-70w-while-downloading-in-standby-because-it-uses-the-main-apu-and-not-just-the-arm-chip/
Given all the aspects in which it would seem to be technically superior, how come OpenBSD isn’t eating away at some of Linux’s market share?
Network effects. Default choices. AWS launches with linux support, so people pick linux, then they pick docker, etc etc etc.
Linux does solve a great many problems that OpenBSD does not. (Well, it offers a great many features and buttons and such which look like solutions. :)) I’m not sure that one operating system that solves all problems is the best approach, though. there’s a lot of disagreement about how even a desktop OS should work and how components should fit together.
I had also heard that performance on newfangled hipster tasks (http service, MP scheduling, databases) was nontrivially worse, so I started trying to run an OpenBSD instance on AWS to run some side by side tests in order to invalidate those rumors. Apparently one guy once heard of a file you can UUCP from sunsite.unc.edu that enables 80-character mode so that you can give it a shot, but that was from a Byte magazine reader article so I cannot vouch for its veracity. I had to give up when my eyelids started twitching uncontrollably.
The reputation for security doubtless partially stems from the fact that installing the thing requires delivering the One True Ring to a locked basement cabinet guarded by leopards in an abandoned mausoleum underneath a nuclear waste disposal site in Afghanistan. Minimization of attack surface and all that. Somewhere, a Haskell core developer is putting down his glasses and rubbing his eyes in admiration.
Hardware support is what keeps me from switching.
And historically, perofrmance. I haven’t seen any good performance comparisons in the last few years (that I remember anyway), but several years ago there were several comparisons done that showed somewhat poor openbsd (and netbsd as I recall) scalability (multi-core performance, etc). Linux has often been one of the top performers in those types of benchmarks.
Go fast until the wheels fly off?
The following HN comment from Brendan Gregg might be worth a read. It’s answering in detail basically the same question, just for Illumos rather than OpenBSD: https://news.ycombinator.com/item?id=12837972
The reply is a touch acerbic, but makes some good points too I think. Like why not just give up when linux is 1000 developers ahead? Because half of them are wasting their time inventing ten different tracing frameworks. Ok, admittedly it would be nice for openbsd to have one perf tool, but I think we’re not so far behind as it may seem.
Also, for something like inteldrm, there’s a team of devs who keep churning the code, which causes kettenis some struggle when he tries to import it, but on the whole we get most of the benefits of that driver at a considerable manpower discount. The precise economics aren’t quite that simple, but not all of the effort spent on linux is locked in linux either.
Sure, I agree on both of those points. Some effort will be wasted to duplication and churn, some will have little effect as it can be easily reused by other projects.
But if the larger developer base is at all positive, it will add up over the decades. E.g. 20 years ago the common wisdom would have been that the BSD TCP stack was both battle hardened and state of the art, while the one in Linux was flaky and scaled badly with load. It’s definitely the other way around these days (to a different extent for different BSDs), with a steadily increasing delta. And then repeat the same story over dozens of subsystems.
Clearly there are things that more manpower doesn’t help with. Like deleting code to reduce attack surface; I’m pretty sure that the larger the team, the harder that is to achieve :) It’s not that developers of non-Linux operating systems should just give up, or anything like that. But the assertion at the start of this thread on Linux’s technical inferiority doesn’t feel realistic to me.
That interesting comment reminds me a lot of the Worse is Better effect that got UNIX to dominance in the first place. There were better systems including some focused on good docs, reliability, and high security. I write about them a lot. ;) They lost with them being in close to legacy mode or gone depending on the product/project. The Linux situation, esp as Brendan Gregg describes it, looks like a repeat of that with Linux doing it to the other UNIX’s. I already knew this seeing the likes of SGI, IBM, and Oracle get on the Linux bandwagon despite having proprietary UNIX’s to push. In contrast, OpenBSD is trying the UNIX version of The Right Thing. It will fail in broad sense because that always happens.
It’s destined to a niche of those that care about The Right Thing. You’ve all done a great job keeping it up despite your filter on the kind of contributors you accept and not giving into market’s crap that much. I saw Theo backtrack a bit with VMM admitting OpenBSD might have to do a little more for marketability. Still, the project will probably need a like-minded sponsor with lots of money and/or talent to break past what we’ve seen so far since The Right Thing is always swimming upstream vs Worse is Better which sometimes creates tsunami’s. Those of us focused on quality might always be also-rans in larger scheme of things. (shrugs)
Linux is easier to use.
How do you search for a package in OpenBSD? How do you get a description in your search results? You can search package names by downloading the index.txt file from the packages directory on a mirror. But anything more sophisticated you have to use the ports tree and the janky makefile system with non-intuitive syntax and cryptic errors to do any interesting searches.
It’s actually possible to download and install a Linux distro that comes with a desktop environment, installs quickly, and works fine right away. When I was first getting into non-Windows operating systems in middle school, I tried out OpenBSD because the whole secure OS thing sounded cool to me. I screwed with it for hours, felt like I was getting nowhere, then gave up and installed Linux Mint.
I run OpenBSD now, but I’m also a systems programmer / SRE at a database company, so I’m not exactly an “average user” that represents the trend of the market.
pkg_info -Q
is what you want. That said - it looks like it doesn’t respect the-d
or-c
flags (I have a diff to make it work with it though)yep. i use pkg_info, i browse the ports mailing list, read the website, and also look at my mirror of choice from time to time.
i just use cwm that’s in base. i had previously used gnome and xfce from packages. i reckon my willingness to read documentation mostly gets me to where i need to be… other things figured out by trial and error, mailing list, and searching the internet.
You make it seem like reading the documentation is a bad thing? This should be the preferred approach.
On linux the preferred approach is asking half assed questions on stack overflow.
i don’t think it’s a bad thing. i’m implying that everyone saying openbsd is difficult to install or use aren’t reading these things and i don’t really understand why.
Ahhhh. I’m somewhat amazed that I didn’t know that. But I will still call it unintuitive. See, I expected something like pkg_search, or to find something searching for “search” in man pkg_info. Searching “OpenBSD search for package” on Google returns a bunch of ancient results about ports. It IS mentioned in the packages FAQ though, but the preview text on Google mentions ports specifically. So I must have searched for it, seen those results, rolled my eyes, looked in the man pages, seen nothing, and decided to just download the index file.
Compare to most Linux package managers, which when run with no arguments tell you the commands to install and search. The word “search” specifically is much more well known than “query” because of Google.
So even though I’m a bit lazy and it’s clearly my fault for not knowing this as a sophisticated user, I think helping rather than blaming the user isn’t the right strategy towards getting adoption. Linux is really good about that, OpenBSD not so much.
Query is close. I guess it’s a difference in terminology.
This seems to be a common trend among Linux users, google is consulted with more authority than local documentation. I personally do the same thing.. when finding issues with linux machines I always go to google first.. the crap documentation (often lacking entirely) has trained me to do so!
Where was there lack of help and who is doing blaming?
I realize query and search are close, but search is definitely the layman terminology.
Googling isn’t just a Linux strategy, that’s what Windows and Mac users do too. Apple in particular is pretty good about making their support pages show up on Google.
I didn’t originally mean people blaming the user directly, but rather a UX that “blames the user” in its design, and for OpenBSD I mostly see this in docs or commands. Not being able to find the -Q flag in the man page by searching (querying?) for search is poor UX. It implicitly becomes the users fault for not reading the whole manual. There are no examples either, where surely a common operation like search would be demonstrated. And OpenBSD commands don’t self document or provide assistance, whereas Linux commands will often list the most common usage if you don’t type a valid command. Using OpenBSD feels a bit RTFM, wheras on Linux stumbling around in an interactive session is much more viable, as most things try and point you in the right direction.
This goes both ways, on OpenBSD it’s way more likely that if you can’t figure something out, it actually is documented somewhere. But that documentation could be more accessible and searchable.
But also user blaming happens directly on misc@. I am part of no other community that ever makes me think “wow these people are such outrageous stuck up assholes, I’m not even sure I want to be a a part of this anymore.” Mostly OpenBSD people are intelligent, articulate, and kind. For example, I’ve had nothing but good experiences talking with OpenBSD folks on lobsters. But wow some of the stuff on misc makes my blood boil.
I’ve considered contributing to OpenBSD docs to make them more accessible, especially FAQs / new user guides, but my experiences on misc have always stopped me. I worry that I’ll be shot down for going against the OpenBSD philosophy, and I won’t even be rightly told why, just be told I’m a moron. It sucks, because I love OpenBSD and I want to share it and make it easier for people to learn about, but I feel discouraged from contributing.
again i feel the direct opposite here.
i was able to find everything i needed without asking for help and without googling for the most part.
still don’t understand how you missed -Q in the pkg_info man page because it’s right at the top in synopsis.
maybe i’m a stuck up asshole too.
I don’t think so.
I wanted to search, I scanned the first line for search, /searched for search, moved on. I’m just too impatient. But a lot of people are too impatient, and worse a lot of people just don’t care enough to persist.
The OpenBSD faq is great https://www.openbsd.org/faq/faq15.html#PkgFind
i’m an average to below average user and i use openbsd as my daily driver.
i don’t program and my knowledge of computers is intermediate at best.
i also work in a non-tech field.
i think it’s the easiest and most straight-forward OS to use.
so, obviously i disagree with this.
I wonder what you’re doing on lobste.rs :)
Interesting! So, how do you look for packages you need to install? How’d you get going with a desktop environment?
The file system isn’t great…
Please. Greatest filesystem of the 80s. Best decade, best filesystem.
That was Files-11 on OpenVMS with versioning and stuff. Especially integrated with high-uptime stuff like clustering and distributed lock manager. Or NonStop’s Guardian with its crazy reliability. Or first system (SCOMP) certified to high security that added ring and segmented protection to them with system-wide security policy.
I do agree it was one of best decades for applied IT with all kinds of awesome shit happening based on what CompSci had worked on in 1960’s-1970’s with better hardware available. A lot of things started coming together that couldn’t before.
Or they need to run certain applications that are only available on Linux, or they need drivers that are only available on Linux, or they want a filesystem that has more features than UFS/FFS, etc.
OpenBSD picked a niche and perfected itself in that niche. I think it is a shining example that picking one problem and solving it well, is often better than being a jack of all trades, master of none.
(Which does not mean that it cannot be used as a general purpose OS with some care.)
Even as someone who likes the FSF, I doubt many Linux users are there because of (rather than despite, or indifferent to) the GPL. It’s not hard for me to imagine an alternate universe without the BSD lawsuits where FreeBSD or something got popular as the mainstream free hobbyist Unix in the 1990s, and I seriously doubt FSF diehards would have been able to keep more than a handful of people from going with that bandwagon, had it developed (and had they actually wanted to).
Same reason as many other similar situation throughout the industry. People know something else, a lot is built on other systems, marketing, and once you have a certain amount of people using tech X it’s really hard to use something else.
Another side effect that kicks in with Linux Distributions, Operating Systems and Programming languages is that at many places if you introduce a technology that isn’t the currently dominant one you will be personally blamed for every single bug or different obstacle it has. It will often be blamed on it, despite also existing on the dominant OS.
Something related is that sadly a lot of software that companies and people end up using at some point is written in unnecessarily non-portable ways. I once worked at a company that used a software running a bash script (stored inside a string in a program) and it had a typical non-portable #!/bin/bash instead of #!/usr/bin/env bash. As usually I’d report that and even create a pull request on a huge (in terms of stars, in the tens of thousands) and very hyped software, expecting it would be accepted. After being baffled that the authors didn’t even know about /usr/bin/env and what it does, a link to Wikipedia didn’t help either the conversation stalled. Since that project was being used by the front end developers I kept patch sets for such things around.
And while those tiny things are really not hard in general these tiny things add up. I know the problem even exists if you don’t use Ubuntu, but for example Alpine in the Linux world.
Having these kind of portability issues leads to the dominant technology in a field to quite often not be the best. The most famous example is how long Internet Explorer stuck, despite Opera and the Mozilla browser, until Firefox came along.
When there is a lot of users and developers even pretty bad technology can stick, because there will be widely used workarounds for problems, there will be progress on fronts, even when the architecture is flawed, etc. Change is rarely that quick, especially when many parties are involved and put their money and effectively lives on it.
Of course that doesn’t mean that Linux is bad and OpenBSD is great, just that technical superiority or being a bit better than others usually is far from a good indicator for dominance in a field. Especially if marketing and politics have a big presence, but even without. People simply need to have heard of it and a good reason to switch and get into something new to them and settle there. When there is no direct financial effect, that is significant enough people tend to not just switch utilities from one moment to the next. And even when you know OpenBSD really well and are convinced its better introducing that in an existing company might not be an option. Of course you can always switch, but why give up a safe, well-paying job with great coworkers for an operating system?
Docker / namespaces
Honestly, I found this utterly fascinating for some strange (fetishistic?) reason.
When I get home, if I remember, I would like to grep through four additional large and source-available and influential older code bases that seemed to have escaped mention: IBM MVS 3.8, Xerox UTS/CP-V, MIT/GE/Bell/Honeywell/Bull/etc Multics, and UM MTS (Michigan Terminal System).
These all should predate BSD in many cases by decades and might well have earlier references.
Maybe someone will beat me to it.
I had a look through MULTICS, didn’t find anything plausible. The other three sound like they’re worth a shot :)
(MULTICS was a bit of a pain. Also AFAIK the only public source for it is a late-stage source dump with no versioning history; so it’s hard to say with any degree of confidence when any specific part was written).
There are actually two releases, if I recall correctly - an unofficial “leaked” one that originated from MIT, and the officially blessed one from Bull.
While neither release contained modern revision control, major edits and changes were always described in the comments at the beginning of the file, so you are right, it is of little help here; unless you could discover an “XXX” comment referenced in a source file with a pre-81 header — but even then it would likely be impossible to prove the edit date definitively.
I think the sources for the other older systems I mentioned resides on SHARE and Bitsavers.
For posterity, there wasn’t anything of great interest in these codebases.
“The companies that designed these protocols happen to control the servers and the client application program, but not really the client OS”
This isn’t entirely the case for QUIC, since Google does develop Android, which is easily the most popular OS in the world.
Google develop it, but that’s where it ends. They have basically no control over about getting any kernel level changes installed on actual running devices. 75% of the active Android Install base is on versions over two years old. And the much slower release cadence makes things even worse.
If they add a new TCP feature today to Android, in a year it’ll probably be running on 0.5% of devices. If they add a feature to QUIC on mobile Chrome, it’ll be on 80% of the devices in two months.
This article misses a few things:
UINT32_MAX % N == 0
% N
instead of& (N - 1)
This trick can be a nice win when writing lock free queues, but for normal queues it’s so marginal it’s probably not worth it.
An actual modulo is just too expensive (unless N is a constant, and the compiler has an optimization for that). For the other two designs you don’t need to use mod to support arbitrary values of N, a single conditional will suffice to wrap the values. That won’t work when the indices have an unlimited range.
(Also, surely only powers of two are going to be factors of another power of two?)
Yeah you’re right, it’s funny I never noticed that.
Turns out my entire post is wrong. In lock free code, you actually want the opposite of this trick - keeping reader/writer pos separate. If you have head + length you need to update both variables (e.g. enqueue is rougly head++ length–) which requires a CAS loop that’s twice as wide.
If you’re doing an SPSC ring buffer you can keep the reader/writer pos as non-atomic ints in separate cache lines, and add an atomic flag to each node saying whether it was last read or written. You don’t waste any slots and you only get contention when the queue is nearly empty/full.