I have been using in parallel both Linux and FreeBSD on my computers for around 3 decades, because each has advantages over the other in certain circumstances.Until around 2004, I looked at Linux more like a toy in comparison with FreeBSD, because the latter had much better reliability and performance.
However, in the early years after 2000 Linux has evolved and it gained more and more advantages over FreeBSD, mainly caused by a much greater number of programmers that contributed to Linux.
The first that affected me personally was that gradually Linux added support for a much greater number of peripheral devices.
Unfortunately, after the launch of Windows 95 all vendors of PC peripheral devices have stopped providing technical documentation for their products, replacing that with Windows drivers (or in rare cases, e.g. for network interfaces, they might provide drivers for a few other operating systems).
This means that for non-Windows OSes someone has to reverse engineer the device drivers. In the better cases, there are some standardized peripheral interfaces, like USB, ATA, SCSI etc., but that is not good enough for using a given peripheral device, because most of these have always been full of undocumented bugs and they work on Windows only because the Windows device drivers contain workarounds for the undocumented bugs.
This means that the Linux kernel includes a huge database of quirks with the bugs of various peripheral devices that exist on the market.
Eventually the BSDs were also forced to include such bug databases, but theirs were and still are much smaller than those of Linux, because they have less users, so less people who might encounter the buggy devices, investigate the cause and report it.
For example, I had some Athlon CPUs that I used with motherboards bought in 2001, which had VIA chipsets. In 2000/2001, the VIA chipsets had a horrible bug that caused data corruption on hard disks. There was a workaround to serialize some of the ATA commands, to avoid their concurrent execution that resulted in data corruption. Of course, VIA kept secret the existence of the bug, so who knows how many people have lost precious data because of this.
When I first bought a motherboard with a variant of the buggy chipset, for a Pentium III CPU, by chance I discovered very early the data corruption on Windows, and I returned the MB. I bought another MB with the same chipset from another MB vendor (Soltek), and I blacklisted the first MB vendor (Soyo), after not seeing data corruption on the new MB.
I was very wrong because the MB vendor had no responsibility in this, only VIA was guilty. The bug disappeared on the second MB because meanwhile VIA had updated its Windows driver. So they caused lost sales to the first MB vendor, by their secrecy.
Sometime later, I decided for a MB with Athlon to be my first desktop PC that was not configured for dual-booting with Windows, so I wanted to install on it only a *BSD or Linux.
However, neither FreeBSD nor NetBSD nor OpenBSD worked on it, all had the data corruption problem. But Linux worked fine, so I installed Linux and since then I used only Linux for PCs, restricting FreeBSD for certain kinds of servers.
Only later I discovered the reason why Linux worked, unlike the BSDs, which was because it was aware of the bug existing in the VIA chips and it included the same workaround as the Windows drivers.
I believe that my experience was typical of the positive feedback loop that enhanced the market share of Linux, more users resulted in good support for more hardware devices, which enabled the adoption of Linux by more users, and so on.
Then the major blow that hit the BSDs was the launch of Pentium 4 with SMT in 2003, followed by the dual-core AMD CPUs in 2005.
On a single-thread CPU, FreeBSD 4.x had a much better performance than the contemporaneous Linux, for networking and storage operations.
But the design of the *BSD kernels was incompatible with multiple threads and the rewriting of the *BSD kernels to work with multi-core and/or multi-threaded CPUs took several years, while Linux had already been ported to SMP architectures and it took immediately advantage of the new fast CPUs.
During the first decade of this century Linux took a great leap in performance beyond the BSDs, and they never caught up completely with it after that.
Beyond the fact that it worked well with many threads, Linux introduced during those years many improvements over the traditional UNIX-derived features.
The most original was the use for synchronization of compare-and-wait-for-mutation, a.k.a. futex (2002), which was the correct solution for a problem discussed by Dijkstra 40 years earlier, but for which Dijkstra had proposed a wrong solution, i.e. semaphores, a solution that caused inefficient implementations of IPC for decades (Dijkstra had criticized the use of event flags for synchronization, because of a possible race condition, which was avoided by the commutativity of the increment/decrement operations on semaphores, but compare-and-wait avoids the race, without using superfluous auxiliary variables, like semaphores, but using only a variable that is already needed when implementing things like a message queue, a ticket lock, a CLH lock etc.).
Other Linux improvements of that time were epoll (2003) as a poor man's equivalent of FreeBSD's kqueue/kevent (2000), libaio for asynchronous storage I/O (FreeBSD had used since 2000 an extended version of the POSIX AIO, adding "aio_waitcomplete"; libaio is better than the standard POSIX AIO), timerfd (2008) for waitable timers (FreeBSD had EVFILT_TIMER since 2000) and various means for doing zero-copy I/O, like O_DIRECT (2001) from IRIX, sendfile64 (2001), splice (2006) and related syscalls.
Of the BSDs, FreeBSD has the largest installed base, so it also has more developers and for the architectures that it supports (which are less than those supported by NetBSD and OpenBSD) it normally has the best performance among BSDs, as more optimization effort has been directed to it.
Before 2019, I would have said that for a server environment there was approximate feature parity between FreeBSD and Linux. But then Linux was greatly improved by the addition of io_uring, which finally provides the right way to do asynchronous I/O on Linux, where before this every available method was inferior in some respects to methods available on other operating systems 50 or even 60 years ago.
Now io_uring allows the implementation of high-performance I/O on Linux with much lower overhead than on any other UNIX-derived OS. Like previously with "futex" => "WaitOnAddress", the Microsoft developers remained able to recognize a good thing when they see it, so now Windows has also added functions like CreateIoRing (ioringapi.h).
While since io_uring I would always choose Linux for developing a server application where maximum performance is essential, I continue to use FreeBSD on some servers, where maximum reliability and maximum simplicity in management are more important.
I have FreeBSD servers that have been used 24/7 for more than 20 years, with reboots normally spaced at no less than a year, which were needed only for hardware upgrades or kernel upgrades. In the default configuration, or only with very minimal changes that can be done in a single configuration file, the BSDs are much more security-hardened than the default configurations of most Linux distributions. If you take your time to carefully audit and adjust all configuration options, you can reach equivalent security regardless of the operating system.
I have used occasionally NetBSD and OpenBSD, but not on general-purpose servers or PCs, which are better supported by Linux or FreeBSD. Especially NetBSD is easy to port to various embedded computers (which is of course an explicit goal for it).