News for hackers. Stuff that matters.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by xyzelement on Monday August 21, 2023 @01:21AM (#37205748)
To sum up what I learned from the comments:

Is FreeBSD stupid for having used bubblesort to begin with? NO. It worked well for decades before surfacing as a problem in this extreme and unanticipated use case.

Is optimizing this a waste of time? NO. The use case revolves around super frequent bootups to power lambda and for this type of thing every ms matters.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Sharlin on Monday August 21, 2023 @02:28AM (#37206069)
As is often said, O(n^2) (or even 3) is fine until it stops being fine.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by alkonaut on Monday August 21, 2023 @02:42AM (#37206140)
Yeah and it almost always stops being fine. The problem with an O(N^2) solution is that you rarely put in an assert that N < 100 or something like that to guard your assumption that big N "doesn't happen". Because after all it's better that the process eventually completes than that the process crashes. And if you don't dare to put that in, you perhaps shouldn't use O(N^2).

N^2 or N^3 is fine for things that are fixed size and very unlikely to stop being fixed size, or at least unlikely to grow a lot. But any time you think "oh it's just a few files" when there is nothing to stop it from being 1000 files in ten years, or at one rare user: don't use an O(N^2) solution.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kortilla on Monday August 21, 2023 @04:14AM (#37206699)
> Yeah and it almost always stops being fine.

No, it’s just a non-issue in the 99% of cases where it really does stay at small inputs. I come across configuration code all of the time that is stupidly inefficient like this and it’s almost always irrelevant. Tons of stuff works on inputs of <10.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by alkonaut on Monday August 21, 2023 @04:25AM (#37206781)
It's an observation with heavy selection bias: in 100% of the cases where you had to deal with a perf problem it had stopped being fine... Since it also almost invariably is accidentally quadratic and not deliberately quadratic as with BubbleSort, you also have a hard time estimating how many quadratic algorithms you have that haven't caused problems, and perhaps never will.

Adding complexity because of an anticipation that some input will grow to an unreasonable size (at the time of writing) may or may not be a good idea. But using a different off the shelf function or data structure is usually not a high cost for making sure it's not a problem down the line. Of course, that also assumes that there is a good and efficient standard lib of methods and data structures so that "making a more clever choice" isn't also a burden or risk in terms of code size, complexity, risk of bugs.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by GuB-42 on Tuesday August 22, 2023 @05:15PM (#37228619)
The problem is that it is an issue in 1% of cases, and it is hard to know in advance which 1%. So either you do a proper analysis to see how many inputs you really need, or you use an algorithm that scale.

For sorting, getting a n.log(N) algorithm that doesn't break down is usually just a matter of calling a library, or writing <100 lines of code if you really can't use a library. It usually doesn't have much of a negative impact when the number of inputs is small, and it is often simpler than making a proper analysis. So, when in doubt, never use a n^2 sorting algorithm.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by masklinn on Monday August 21, 2023 @05:30AM (#37207161)
Here it took almost 30 years for it to stop being fine, which is a pretty good run.

And it was a blatant O(n) algorithm, easily swapped out, it’s not like they were calling sscanf in a loop and whoopsie turns out C strings are shit so now parsing a 4 characters decimal number is O(buflen^2).

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by alkonaut on Monday August 21, 2023 @05:35AM (#37207200)
One should indeed be forgiven when getting 30 years out of a code base, any code base. It's hard to predict that you'd need to shave milliseconds of cloud/VM startups or from some embedded device, if you can't imagine Clouds, VMs or computers the size of watches.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by toast0 on Monday August 21, 2023 @11:23AM (#37210805)
> Yeah and it almost always stops being fine.

Properly predicting if it will be fine or not is a sign of wisdom. But something like this is a fine place to use something where the complexity blows up. The sort happens in a clear place; early boot is a little hard to debug, but still. It's much worse when you put something N^3 in where when it blows up, the time spent is diffuse.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by JonChesterfield on Monday August 21, 2023 @11:40AM (#37211055)
Old colleague had some wisdom on this which stuck with me. Thanks Ben! Spoken at separate times.

- it's constant time or it's crap

- constant time means your best case is as slow as your worst case

In this case, constant time would be sorting it before the program runs.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Sharlin on Monday August 21, 2023 @02:07PM (#37213173)
> - constant time means your best case is as slow as your worst case

Which is in fact important in crypto code to prevent timing attacks.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @04:09AM (#37206668)
yes, it was stupid to use bubble sort to begin with; there is never an excuse for using bubble sort

    for (size_t i = 0; i < n; i++) {
        for (size_t j = 1; j < n - i; j++) {
            if (a[j-1] > a[j]) {
                item_t tmp = a[j];
                a[j] = a[j-1];
                a[j-1] = tmp;
            }
        }
    }
when you could use insertion sort

    for (size_t i = 1; i < n; i++) {
        for (size_t j = i; j > 0; j--) {
            item_t tmp = a[j];
            if (tmp > a[j-1]) break;
            a[j] = a[j-1];
            a[j-1] = tmp;
        }
    }
which is no more complicated (both are 17 amd64 instructions with -Os), but twice as fast in the random case, and enormously faster in the sorted and almost-sorted cases

(above code only minimally tested: https://godbolt.org/z/43dqz9Gq8)

this is not much of a criticism of freebsd; if you polished your codebase until there was nothing stupid in it, you'd never ship anything. freebsd's code quality is quite high, but probably we can all agree that this was stupid

of course it wouldn't be nearly as fast as mergesort on large inputs, but mergesort is more complicated

(also mergesort is slower on small inputs than insertion sort or bubble sort, but in the case where you're only sorting something once at startup time, that probably isn't important. it might matter if you were sorting a million lists of ten items or something)

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Closi on Monday August 21, 2023 @04:26AM (#37206788)
I think we have different definitions of stupid - the original implementation was perfectly fine for the time and requirements it was written for.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by winternewt on Monday August 21, 2023 @04:34AM (#37206823)
But it could have been better for no additional effort. Doing something worse when the better option is just as easy suggests incompetence.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @04:42AM (#37206862)
i wouldn't go so far as to say incompetence

even the best of us do stupid things sometimes

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Closi on Monday August 21, 2023 @04:51AM (#37206921)
Yeah, but it was working.

And maybe it wasn't 'no additional effort' because they were more confident with quickly writing a bubble sort.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by jazzyjackson on Monday August 21, 2023 @05:18AM (#37207076)
Doing something better when you already have something that works suggests a lack of time management xP
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by winternewt on Thursday August 24, 2023 @08:30AM (#37248023)
At some point there was no sort, and then somebody implemented the sort. That's the point in time that I'm talking about.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by throwawaaarrgh on Monday August 21, 2023 @07:27AM (#37208057)
Never underestimate incompetence. It usually succeeds despite itself.

It also could have been apathy: knowing there was a better solution and just not caring what was implemented. I feel like this is more common than incompetence, especially in larger projects or organizations. Nature tends to take the path of least resistance.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by ska on Monday August 21, 2023 @12:59PM (#37212260)
> But it could have been better for no additional effort.

Not if it was already written.

I don't know anything about this particular codebase, but one thing I have learned over the years is that when you are tempted to say "such and such decision was stupid" in a production codebase, you are almost always missing something.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by moffkalast on Monday August 21, 2023 @05:39AM (#37207233)
Then the requirements were terrible?
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Closi on Monday August 21, 2023 @07:02AM (#37207845)
I don't think the 90's developers could have forseen that 2ms on boot would be huge for cloud serverless compute like lamdba.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by oblio on Monday August 21, 2023 @07:41AM (#37208156)
True, but a lesson we frequently have to learn over and over again is that the code is in software in widespread use, the only valid values for collection sizes are 0 and N -> ∞.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Closi on Monday August 21, 2023 @07:47AM (#37208197)
> the only valid values for collection sizes are 0 and N -> ∞.

Of course there are valid values below that...

If they were designing to a collection size of N -> ∞ then they shouldn't have used Insertion Sort either then, because it is O(n²) in the worst case.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by oblio on Monday August 21, 2023 @07:50AM (#37208222)
True, but make that valid value at least something like 1 million.

It's trivial to start with something that gets human input and someone, somewhere, decides to plug the thing into something else that generates that input.

And we all know that if computers are good at something, it's doing a lot of small things millions of times.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by moffkalast on Monday August 21, 2023 @07:39AM (#37208141)
On an OS whose only gimmick is that it's fast and stable? Idk, maybe they could've.

Besides there's little reason for any codebase of any kind of ever contain bubble sort (except for an academic one, showing it as an example of a bad one). We're talking 20 years ago, not 2000 years ago, the basic sorting algorithms were pretty well researched and established by then.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by SomeoneFromCA on Monday August 21, 2023 @04:26AM (#37206785)
Neither of your code snippets are working, or are an actual implementation of bubble sort.

Since what insertion sort is faster that bubble sort on sorted data?

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @04:41AM (#37206860)
i tested both of them on some input data and they both sorted it correctly

admittedly this was probably after you wrote your comment

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by SomeoneFromCA on Monday August 21, 2023 @05:11AM (#37207032)
Because it misses a crucial step, early exit if there were no swaps. This way it would be extremely efficient in case of already sorted data.

You should probably check wikipedia page. Here: https://en.wikipedia.org/wiki/Bubble_sort.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @05:36AM (#37207205)
i think i wrote that page originally 22 years ago, before the switch from usemodwiki to mediawiki

it's true that, if your data is exactly sorted, or has a small number of items that are far too early (e.g., 43 3 4 5 6 7 8 9 10), you can modify bubble sort to notice this and exit early, at the expense of making it more complicated and even slower in the average case

however, this doesn't help if instead you have a small number of items that are far too late (e.g., 4 5 6 7 8 9 10 43 3), in which case bubble sort takes the same number of passes as it normally would, while insertion sort takes linear time. of course you can complicate bubble sort further into "shaker sort" to handle this, which makes it even more complicated but at least doesn't slow it down any further

but all of this is sort of futile because it's still half as fast as insertion sort in the case of unsorted input, and even without the tweaks, no simpler

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by SomeoneFromCA on Monday August 21, 2023 @05:44AM (#37207267)
I do not have access to the historic definition of bubble sort, but all the modern implentation i've seen so far, all have a check if there were no swaps. I absolutely cannot wrap my mind how exactly it would make it slower in the average case, I almost certain it won't, how exactly this would make code sgnificantly more complex to any meaningful extent.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @06:05AM (#37207397)
we're talking about six lines of code if we don't count the curly braces (which can be omitted)

bubble sort with early exit is

    for (size_t i = 0; i < n; i++) {
        bool sorted = 1;
        for (size_t j = 1; j < n - i; j++) {
            if (a[j-1] > a[j]) {
                item_t tmp = a[j];
                a[j] = a[j-1];
                a[j-1] = tmp;
                sorted = 0;
            }
        }
        if (sorted) break;
    }
which is three more lines of code, which is in some crude sense a complexity increase of 50% over both the simple bubble sort in my earlier comment and over insertion sort

if you compile it https://godbolt.org/z/jdzov8cPn you can see that the inner loop goes from 10 instructions to 11. that doesn't guarantee that it's 9% slower (that depends a lot on the platform, and in particular on a big superscalar cpu it probably just uses a little more power but the same number of clocks) but it does tend in that direction. of course occasionally it will save you a pass or two over the array, which will tend to compensate, but it won't usually save you 9% of the passes

if some item is in position n and needs to be in position m, where m < n, it will require n - m passes of bubble sort to get there. a little thought suffices to show that, for randomly shuffled input, where m = 0 the item has to move about half the size of the array, where m = 1 it has to move about half the size of the array minus one half, where m = 2 it has to move about half the size of the array minus one; but it's the maximum of these three numbers which determines the number of passes after which all three of those positions will have the correct item, and that maximum is heavily skewed to be almost the entire size of the array. the chance that none of those three items is in the last 25% of the array originally is only .75*3 = 42%. and as the value of three increases, it gets worse. so in general early exit doesn't buy you much

as for modern implementations of bubble sort, they're all either didactic classroom exercises like this one or careless mistakes like the original freebsd code; because insertion sort always beats it, there aren't like a community of bubble sort implementors who have annual bubble sort conferences

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by SomeoneFromCA on Monday August 21, 2023 @06:54AM (#37207761)
Your original claim that is more complex or slower is unsubstantiated. Yes, it is trivially more complex to add a flag, but it does not actually make it any more difficult to understand or error prone. Your argument is way too pedantic. Claim about the performance is equally unsubstantiated. To make a proper proof you need to show that on average, we still have all N outer passes executed, before we face no swaps situation. Which almost certainly is never true, especially with non-random data.

Although I certainly agree that Bubble Sort is almost always a bad choice, it still is used in computer graphics, or other situations when you have only one or two misplaced pairs of elements. In this case it will outperform the other algorithms, in average case while maintainig functionally in the less than ideal situation.

Besides it is entirely irrelevant what are the purposes the algorithm is used today, didactic, deliberate or poor judgement, the de facto standard way of doing it today is to check for the early exit. Your argument about poor performance on the already sorted data is a straw man argument, your are stubbornly defending. Well ok, if you believe so...

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @06:58AM (#37207813)
if you aren't convinced that adding the early exit generally hurts performance, well, it's not surprising; measuring performance is difficult and tricky, and you're faced here with claims you don't really have the knowledge to evaluate properly, so it's entirely proper that you are dubious about them, even if you're confused about what a proper proof would consist of

it might help your intuition to think of it this way:

1. with random input, the first ten positions of output are pretty likely (65%) to have an item that was originally in the last 10% of the input, and almost certain (97%) to have an item that was originally in the last 30% of the input. so those ten items alone account for needing 95% of the passes you'd need without an early exit, minus about five, in 65% of cases.

2. the first 20 positions are pretty likely (64%) to have an item that was originally in the last 5% of the input, and almost certain (96%) to have an item that was originally in the last 15% of the input. so those 20 items account for needing 97% of the passes you'd need without an early exit, minus about ten, in 64% of cases.

3. the first 30 positions are pretty likely (64%) to have an item that was originally in the last 3.3% of the input, and almost certain (96%) to have an item that was originally in the last 10% of the input. so those 30 items account for needing 98.5% of the passes you'd need without an early exit, minus about 15, in 64% of cases.

of course, if you're only sorting 30 items, the first ten positions of output are actually a third of all the positions, so "minus five" is pretty significant. and probably if you're sorting more than about 30 items at a time you ought to use a linearithmic sort or a linear-time radix sort instead of a quadratic sort

similarly, it's reasonable to argue that complexity (in the sense of containing many parts, not in the sense of asymptotic computational work required) is subjective, and to disagree about it

but i think these are sort of moot points

insertion sort still beats bubble sort in the situations where you have only one or two misplaced pairs of elements, and generally replaces it as soon as somebody notices

as for 'the de facto standard way of doing it today', i suggest you argue with clrs, not with me

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by SomeoneFromCA on Monday August 21, 2023 @07:19AM (#37207982)
Count number of outer passes of insertion sort (it is N) vs bubble sort (with early exit; it is 2) if you have only a single pair misplaced.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @07:21AM (#37207993)
insertion sort only ever makes one outer pass; it does almost exactly half as many comparisons as bubble sort (n rather than 2n-2) in that case, and the same number of swaps (1)

the wikipedia article has a cleverer early-exit version of bubble sort that keeps track of the last pair it had to swap; it will do 1.5n-1 comparisons in that case on average (because the swapped pair is on average in the middle of the array)

above i linked to working code on godbolt (modulo the extra unnecessary swaps on duplicate keys that you were kind enough to point out earlier); edit a comparison counter and a swap counter into it and you'll see

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by bitRAKE on Monday August 21, 2023 @04:12PM (#37214734)
The early exit can be done without an extra flag, but increased code size.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Flockster on Monday August 21, 2023 @05:54AM (#37207322)
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @06:08AM (#37207422)
well, that's just the first mediawiki revision of the page; i was working on it earlier than that, which is why i was editing the subpage link syntax in that version, but the usemodwiki history has been lost

someone else might have written the original version, i can't remember any more, but i think it was probably me

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by jazzyjackson on Monday August 21, 2023 @05:19AM (#37207084)
meh, an optimization, hardly "not working"
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by SomeoneFromCA on Monday August 21, 2023 @05:30AM (#37207160)
It is not "an optimization", it is in the definition of Bubble Sort. What you have written is not a bubble sort, and therefore, by the fact of being not a bubble sort, is not a working bubble sort.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by thaumasiotes on Monday August 21, 2023 @05:56AM (#37207339)
That's not part of the definition of bubble sort.

It's also not an improvement over the insertion sort. If you look at kragen's code, you'll see that running it on a list of e.g. 6 elements in ascending order will mean that you make 5 comparisons, swap 0 elements, and exit. (You do have to count from 1 to 6 as you do this.)

The insertion sort is implemented as a bubble sort, interestingly enough, but one that doesn't consider the entire array at every iteration. Given that it's equally correct, it's not difficult to understand why it will always be faster than a bubble sort that does consider the entire array at every iteration.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by SomeoneFromCA on Monday August 21, 2023 @06:58AM (#37207810)
It is in the definition in Wikipedia and most other sources I have checked. All the implementations I have seen so far, check if any swaps have happened, and stop if they have not.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @07:04AM (#37207867)
not clrs
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by SomeoneFromCA on Monday August 21, 2023 @05:35AM (#37207202)
In any case, you should retract you claim that Bubble Sort is slower on already sorted case. It is CS101, that bubble sort is one of the fastest in this case.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @05:36AM (#37207209)
oh yeah, you're right, thanks, it does do useless extra work if there are equal values in the list

it should say

    if (tmp >= a[j-1]) break;
however, this doesn't make it fail to terminate, which is a possible reading of your bug report
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by openasocket on Monday August 21, 2023 @02:10PM (#37213217)
If you look at the actual change in FreeBSD (https://cgit.freebsd.org/src/commit/?id=9a7add6d01f3c5f7eba8... ) you'll see that the implementation of bubble sort used in the FreeBSD kernel was not doing early exits.

  /*
  *
  * Perform a bubble sort of the system initialization objects by
  * their subsystem (primary key) and order (secondary key).
  */
 TSENTER2("bubblesort");
 for (sipp = sysinit; sipp < sysinit_end; sipp++) {
  for (xipp = sipp + 1; xipp < sysinit_end; xipp++) {
   if ((*sipp)->subsystem < (*xipp)->subsystem ||
        ((*sipp)->subsystem == (*xipp)->subsystem &&
         (*sipp)->order <= (*xipp)->order))
    continue; /* skip*/
   save = *sipp;
   *sipp = *xipp;
   *xipp = save;
  }
 }
 TSEXIT2("bubblesort");
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @08:43PM (#37217168)
i very much appreciate you and erk posting this because we can also now see that it wasn't actually bubble sort but selection sort
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by gpvos on Monday August 21, 2023 @04:56AM (#37206950)
> above code only minimally tested

There you have your problem: any programmer can write a bubble sort while half asleep and inebriated at the same time, but for an insertion sort you actually have to think a little. There's much more chance of errors.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by moffkalast on Monday August 21, 2023 @05:41AM (#37207243)
This has gotta be the most bullshit justification for writing bad kernel code that will be reviewed and tested by 200 people before it reaches production. Literally any line of code that's as low level has an incredibly large chance of error.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by astrange on Monday August 21, 2023 @06:23AM (#37207512)
Old code in BSD wasn't thoroughly tested except by virtue of being old; there's no QA department and traditionally UNIX code was tested by thinking about it really hard rather than automated testing.

(FreeBSD got a test suite in 10.1, which came out in 2014, not that long ago in UNIX terms.)

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by oblio on Monday August 21, 2023 @07:47AM (#37208193)
Not just in BSD... GNU wasn't much better.

People would be shocked by how little the core tools we use were tested automatically. Some still aren't.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Quekid5 on Monday August 21, 2023 @05:52PM (#37215845)
Quite.

Thankfully the practice of just randomly shelling out to 'random' programs (like the core tools) has been stemmed somewhat, so perhaps we're mostly safe from RCE via that vector. Downloaded files might still be a vector, tho. Maybe I'm an optimist even though I sound very pessimistic.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Quekid5 on Monday August 21, 2023 @06:46AM (#37207695)
If your testing infrastructure is so anemic that a sorting algorithm (of all things) is hard to subject to e.g. property-based/fuzzing tests then it'd probably be worth it to expand that before doing anything else.

I dunno what FreeBSD's test infrastructure is, but I'm just saying that "it needs testing" is not a good reason not to change to a better sort algorithm in this case.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @06:50AM (#37207725)
if only the people working on bsd in 01993 had had access to your wisdom, think how much more successful they would have been
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Quekid5 on Monday August 21, 2023 @06:52AM (#37207752)
This is about changing the sorting algoritm. No snark needed. It should be trivial to add a test for the current algorithm (whenever it was introduced) and to replace it afterwards. Heck, even keep running both for bisimulation testing.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @07:06AM (#37207885)
probably colin was more interested in booting faster than in improving testing infrastructure

if your interests run the other way, that's great, and hopefully you will succeed in improving freebsd's testing infrastructure, but it's hardly a reason for colin not to speed up booting

but i don't think i saw anyone claiming that the change should not be made because it wouldn't be adequately tested?

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Quekid5 on Monday August 21, 2023 @05:38PM (#37215692)
I don't think you fully read the post I was replying to. I was just saying that that poster's argument against changing the sorting algorithm was misguided.

Quote:

> will be reviewed and tested by 200 people before it reaches production

I was only saying that this is a bad argument for any simple-ish sorting algorithm.

(Granted, if you're doing super-complicated sorting algos with fallbacks for different sizes, heurestics for detecting semi-sorted input, etc. you might want something more sophisticated than trivial property-based checking.)

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @08:41PM (#37217155)
i read that as an argument against having done it that way 30 years ago, not against changing it
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Quekid5 on Wednesday August 30, 2023 @05:46PM (#37329592)
No worries!
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by jcelerier on Monday August 21, 2023 @08:14AM (#37208411)
have you ever been bitten by typing a year in a C/C++ program and getting it inadvertently converted to octal?
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Tuesday August 22, 2023 @04:41PM (#37228220)
heh
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @05:04AM (#37206998)
i'm not sure; i made a few mistakes in each of them as i was writing them, but they were both working by the time i first tested them. i do feel like the insertion sort was maybe a little more challenging?

edited to add: someonefromca spotted a bug in the insertion sort; where it says

    if (tmp > a[j-1]) break;
it should say

    if (tmp >= a[j-1]) break;
which is both a performance bug and also breaks the stability property the algorithm otherwise has
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by abecedarius on Monday August 21, 2023 @12:03PM (#37211423)
fwiw that comparison was where I went "wait, is that right?" in my reading.

Maybe a fair judge of mental difficulty would say "you gotta write at least the loop invariant" (termination being too pedantically obvious) -- though admittedly I leave it out more than I used to.

When I was introduced to sorting as a new programmer, via bubblesort, I thought "why that way?" and came up with selection sort as a method that made more obvious sense. It seems to me like bubblesort's alleged intuitiveness is post hoc from the shortness of the code in terms of all-ascending for-next loops -- the intuitive reason it worked was just that the inner loop did move the next max into place just like selection sort, but with extra swaps along the way.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by aristophenes on Tuesday August 22, 2023 @10:05AM (#37222898)
You should edit the code in your original comment, someone is bound to copy paste the code somewhere…
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Tuesday August 22, 2023 @04:40PM (#37228216)
it's only editable for two hours, for better or worse
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by mort96 on Monday August 21, 2023 @07:45AM (#37208182)
I would trust myself more to implement bubble sort than to implement insertion sort. Not that I couldn't implement insertion sort, I've done it before, but if I was in a context where I had to implement a quick and dirty ad-hoc sorting algorithm which I thought would only ever have to sort a few items, I would probably go with bubble sort.

If I suspected at all that the algorithms would have to sort a decent number of items, I wouldn't consider using an O(n^2) sort at all and would take the time to find a good implementation of (or implement) one of the O(n log(n)) algorithms.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @07:47AM (#37208196)
my subjective experience writing the above comment as documented in https://news.ycombinator.com/item?id=37206998 may be a relevant data point; note that the insertion-sort code is subtly buggy, and the bubble-sort code isn't
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by arthur2e5 on Monday August 21, 2023 @07:53AM (#37208239)
Personally I find insertion easier to reason about once you internalized the idea of a memmove.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by mort96 on Monday August 21, 2023 @08:20AM (#37208473)
To me, it seems like bubble sort is almost inherently easier to reason about.

One iteration of bubble sort is: find two elements in the wrong order and swap them.

One iteration of insertion sort is: find an element out of order, then find the location in the array where it should've been, then move all the items between those two slots one slot ahead, then insert the out-of-order element into the now free slot where it belongs.

Admittedly, insertion sort is pretty intuitive, since it reflects more or less how a human would instinctively try to sort a list; take an out-of-order element and move it to where it belongs. But when translated to code, I think it's very hard to beat "find two items in the wrong order and swap them".

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by hasmanean on Monday August 21, 2023 @01:24PM (#37212615)
A lot of people look at sorting algorithms with the mental model of a 1970s era PDP-8. They analyze scalar instructions as if they are being executed sequentially.

Once you admit superscalar execution (multiple loadstore pipes), out of order execution and caches into the picture ( as well as the possibility of almost sorted arrays as input) the picture is never as simple.

That said, I’m curious whether insertion sort is categorically better than bubble sort. I thought they might have been equivalent for the almost sorted case. I’ve heard both sides argued on this thread.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by masklinn on Monday August 21, 2023 @04:24PM (#37214878)
Per the wiki:

> Adaptive, i.e., efficient for data sets that are already substantially sorted: the time complexity is O(kn) when each element in the input is no more than k places away from its sorted position

In fact it’s often a sub-sort of hybrid sorts, like timsort:

> If a run is smaller than this minimum run size, insertion sort is used to add more elements to the run until the minimum run size is reached.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Tuesday August 22, 2023 @12:40AM (#37218769)
i think that adaptive time complexity bound holds for both bubble sort with early exit and insertion sort
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @10:36PM (#37217954)
the vast majority of computers still aren't superscalar, much less ooo; for every i7 there are 100 cortex-m0+s, which don't even have caches. gpus aren't superscalar or ooo either, just heavily multithreaded, simt, and simd

even if insertion sort reliably beats bubble sort on your ssd ftl chip and your wristwatch, though, it seems like there are cases on modern high-performance hardware where insertion sort is worse than bubble sort (cf. https://blog.reverberate.org/2020/05/29/hoares-rebuttal-bubb...) which is very surprising to me

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by scythe on Monday August 21, 2023 @12:08PM (#37211507)
Pratt–Shell is only mildly more complex than insertion sort and gives a good worst-case performance O(n log(n)^2). It may have a place sometimes.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by eru on Monday August 21, 2023 @12:14PM (#37211589)
If you find yourself having to re-implement a sorting algorithm ad-hoc, you are probably using the wrong language. (Especially these days.)
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kstrauser on Monday August 21, 2023 @02:21PM (#37213370)
...or you're implementing a kernel and don't have full access to a libc.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by eru on Monday August 21, 2023 @02:36PM (#37213576)
Who says you have to use libc?

Eg Rust has no-std crates that you can use even if you can't use the standard library.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by mort96 on Monday August 21, 2023 @03:50PM (#37214447)
What language should they have used instead of C?

And given that C's stdlib has a quicksort function, how would using a different language have helped?

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by eru on Monday August 21, 2023 @03:52PM (#37214467)
Back then C might have been the best bet.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @10:30PM (#37217908)
i think it's pretty common for a specialized reimplementation of a standard library type or function to outperform it by an order of magnitude or so in some particular case. chris wellons gave an excellent example of this with hashing in golang in https://nullprogram.com/blog/2023/06/26/

commonly (as in wellons's post about the two-sum problem) there's a variation on the standard algorithm that can help significantly, but which the standard library function doesn't have an option for

also i think the cost of reimplementing simple 'algorithms from the book' like insertion sort or even quicksort is pretty low; as you saw in my comment above, insertion sort is six lines of code and only moderately bug-prone. we aren't talking about fibonacci heaps or red-black trees or fm-indexes or rader's algorithm or something. the cost is low enough that it's easy to justify in a lot of cases

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by donkeybeer on Monday August 21, 2023 @12:18PM (#37211655)
I trust myself most to implement selection sort, its the most intuitive to me: just keep finding the next smallest element in the array and place it in its position.

I can never remember the loop bounds of bubble sort, always have to look it up.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Gibbon1 on Monday August 21, 2023 @01:50PM (#37212948)
I just remember something from basic math. Exponential curve < linear for small values.

That said a lot of time I have small arrays of objects. Instead of keeping them sorted I just grind through them to find the next largest value. That tends to be hard to get wrong.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by Thiez on Monday August 21, 2023 @05:35PM (#37215668)
Exponential can be better than linear for small n depending on your constant factors, but it's never a given. E.g. `2n` < `10^n + 5` for all n.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by janc_ on Monday August 21, 2023 @07:55AM (#37208260)
When this code was written there was no "amd64" though, so you would have to compare them on the original/typical hardware from then?
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kqr on Monday August 21, 2023 @11:41AM (#37211062)
> there is never a good reason to use bubble sort

I used to believe this but then a friend pointed out a real use case for bubble sort: when you have an array that is always mostly sorted, and real-time performance is more important than perfectly correct ordering. Then running one pass of bubble sort each cycle around the main loop is somewhat satisfyingly ideal.

One pass of insertion sort would be too expensive, and bubble sort is guaranteed to make incremental progress each pass.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by ramses0 on Monday August 21, 2023 @02:38PM (#37213597)
I remember a website that "raced" different sorting algorithms visually but I don't remember which website, or which oddball algorithm that stood out to me as being especially good for "continuous partial ordering".

Most sorts are designed to "really sort something", however I'm very interested in eg: ranking preferences of movies, and in cases like that there may never be "the one true ordering" ... however the mechanism for getting things "closer to sorted" is incredibly close to the mechanism you mentioned: multiple passes, and continual, incremental progress.

My imaginary GUI for interactive sorting in this manner is something like starting with a few "A vs. B" of a generally accepted "top 10/100 vs generic v pretty bad", and then morph to a "drag this new movie in between a few other movies either above, between, or below"

There are sorting algorithms for computers (eg: compare + swap), but fewer sorting algorithms for humans (eg: bucket sort / postman's sort - https://en.wikipedia.org/wiki/Bucket_sort#Postman's_sort ) which can take advantage of "not just compare and swap" to get things "close to correct" quicker.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @08:48PM (#37217200)
maybe you could use a multi-pivot quicksort or an insertion sort where you drag and drop each new item into any position in an already-sorted subset
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Tuesday August 22, 2023 @01:13PM (#37225743)
(upon further investigation that's what the cited "bucket sort" is actually)
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by spiderxxxx on Tuesday August 22, 2023 @02:41AM (#37219444)
Have you read Judea Pearl's paper on Theoretical Bounds on the Complexity of Inexact Computations? It's an old paper from 1976. The abstract is as follows:

Abstract-This paper considers the reduction in algorithmic complexity that can be achieved by permitting approximate answers to computational problems. It is shown that Shannon’s rate-distortion function could, under quite general conditions, provide lower bounds on the mean complexity of inexact computations. As practical examples of this approach, we show that partial sorting of N items, insisting on matching any non zero fraction of the terms with their correct successors, requires 0 (N log N) comparisons. On the other hand, partial sorting in linear time is feasible (and necessary) if one permits any finite fraction of pairs to remain out of order. It is also shown that any error tolerance below 50 percent can neither reduce the state complexity of binary N-sequences from the zero-error value of O(N) nor reduce the combinational complexity of N-variable Boolean functions from the zero-error level of 0(2N/N).

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by ramses0 on Thursday August 24, 2023 @01:50PM (#37252257)
Never in a million years, but that's exactly the angle I'm approaching it at. I'll look it up, but it intuitively says similar to what I'm thinking. "Linear-time Sort-ish..." and I guess the "extra" work is performing the comparison for the new item to insert and validating the comparison (implicitly) by confirming the order of the "extra" items you're compared against.

When humans are tasked with the comparison, it doesn't have to be strictly pair-wise and instead can devolve (kindof) into the various kinds of "sorting networks" that minimize the cmp-swap given a limited subset of the list.

Thanks for the reference!

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @08:36PM (#37217120)
good point, i never thought of that
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by eru on Monday August 21, 2023 @12:08PM (#37211508)
I guess the bigger problem is using a language like C that's almost incapable of providing useful libraries. So everyone is re-implementing everything from scratch all the time.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by yehaaa on Monday August 21, 2023 @01:26PM (#37212641)
qsort is part of the ISO C90 standard though.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by emmelaich on Monday August 21, 2023 @01:28PM (#37212668)
Why didn't they just use qsort, which is in libc?
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by masklinn on Monday August 21, 2023 @04:29PM (#37214943)
It’s kernel code do no libc?
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by emmelaich on Tuesday August 22, 2023 @08:59PM (#37230612)
Yeh obviously. I mean copy the source.

There _could_ be arguments against some sorts, e.g. less predictable memory or performance. But qsort is pretty well behaved.

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by erk__ on Monday August 21, 2023 @02:33PM (#37213531)
For reference the original code was a bit more complicated than just sorting integers which may also have been a reason for the choice.

        /*
         * Perform a bubble sort of the system initialization objects by
         * their subsystem (primary key) and order (secondary key).
         *
         * Since some things care about execution order, this is the
         * operation which ensures continued function.
         */
        for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) {
                for( xipp = sipp + 1; *xipp; xipp++) {
                        if( (*sipp)->subsystem < (*xipp)->subsystem ||
                            ( (*sipp)->subsystem == (*xipp)->subsystem &&
                              (*sipp)->order < (*xipp)->order))
                                continue;       /* skip*/
                        save = *sipp;
                        *sipp = *xipp;
                        *xipp = save;
                }
        }

https://github.com/freebsd/freebsd-src/blob/2b14f991e64ebe31...
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @08:39PM (#37217143)
this is actually selection sort; the comment is wrong
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by erk__ on Tuesday August 22, 2023 @01:38PM (#37226079)
That is a pretty interesting observation, I don't think I would have spotted that, especially given everyone have been saying it was bubblesort.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Tuesday August 22, 2023 @04:39PM (#37228204)
i probably wouldn't have spotted it without trying to figure out which variant of bubblesort it was: counting up? counting down? does it adjust the inner loop size? early exit?

selection sort has the potential advantage for things that are larger than your key that it can avoid copying the entire item, just doing a single swap at the end of the inner loop, but it's not implemented that way here. that would have looked like this

    size_t m = 0;
    register unsigned int subsystem = (*sipp)->subsystem;
    register unsigned int order = (*sipp)->order;
    for( xipp = sipp + 1; *xipp; xipp++) {
        register unsigned int newsubsystem = (*xipp)->subsystem;
        register unsigned int neworder = (*xipp)->order;
        if( subsystem < newsubsystem ||
            (subsystem == newsubsystem && order < neworder))
                  continue;       /* skip*/
        m = xipp - sipp;
        subsystem = newsubsystem;
        order = neworder;  /* enjoy the sorting */
    }

    save = sipp[0];
    sipp[0] = sipp[m];
    sipp[m] = save;
on the other hand if you were going to put effort into optimizing this you probably would have used mergesort or something
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by dkbrk on Monday August 21, 2023 @07:58PM (#37216880)
> there is never a good reason to use bubble sort

Not true. Bubble sort is excellent for sorting very small arrays.

See "Hoare’s Rebuttal and Bubble Sort’s Comeback (2020)" under "Fallback for sorting short arrays" and the performance results presented therein [0]. Discussion [1].

[0]: https://blog.reverberate.org/2020/05/29/hoares-rebuttal-bubb...

[1]: https://news.ycombinator.com/item?id=23363165

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Monday August 21, 2023 @08:55PM (#37217250)
remarkable, thank you

all of the bubble sorts i tried compiling in this thread ended up being compiled to code with either conditional branches or (on arm thumb-2) a couple of conditionalized stores. but conditional stores don't require a pipeline flush, and it is of course perfectly correct that insertion sort depends on its inner loop having an unpredictable branch to get better performance on almost-sorted data, which bubble sort does not

Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by kragen on Friday August 25, 2023 @06:41PM (#37267920)
after thinking about it some more, i was skeptical that this really implements bubble sort, but after trying it, it does

python version of the inner loop

    max_ = arr[0]
    for j in range(1, i):
        y = arr[j]
        arr[j - 1] = min(max_, y)
        max_ = max(max_, y)

    arr[i - 1] = max_
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by basementcat on Monday August 21, 2023 @09:29PM (#37217498)
If you find yourself sorting small arrays, may I suggest a sorting network? https://en.m.wikipedia.org/wiki/Sorting_network
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by michaelcampbell on Tuesday August 22, 2023 @08:52AM (#37221999)
One of the truths I've come across over my years is that almost without fail whenever code is mentioned, someone will come across to show how it could be done better. I haven't seen it in this thread, yet, but generally there will be someone who will maximize how badly it could also be done, usually using Java and invoking "Enterprise coding" memes.
Re:FreeBSD replaces bubblesort with mergesort on SYSINTs, re... by adam_oxla on Monday August 21, 2023 @07:44AM (#37208175)
It is surprising how popular is using O(N^2) algorithms that are simple in implementation even in extremely popular libraries. E. g. ICU search method: https://github.com/unicode-org/icu/blob/a7a2fdbcf257fa22c7a2... ICU is used by Python, Windows or OpenOffice.