bs can easily take many several times more blocks than bc can dish out, and bs is indexing them into relational tables while bc is just reading them directly into the socket from stored blocks on the disk. The disks are independent and fast, and all resource utilization is extremely low.
The limiting factors all pertain to how bc manages the network, and to a lesser degree how it loads the blocks from the file system into the socket. It uses only one thread for network I/O across all channels. Nevertheless there is extensive long-duration mutex locking across the entire network stack (despite just one network thread by design). There is no asynchrony at all, the network is sequential on one thread.
I set up 32 ports and connect to each manually from bs on performance-unmanaged connections. I tried up to 256, but 32 is far more capacity than bc can supply. It tops out somewhere around 18. The throughput is lower than over the Internet on the same machine. Which means bs can easily do more (and over 100+ connections vs. just 32), but the one bc thread is frequently stalled on page faults, critical sections, and polling. It's telling that this one thread never comes close to 100% utilization, as it spends so much time idling.
It's not something that can be fixed with config or more resources. The design is a single thread, and there 99+% of machine resources are unused. We spend a lot of time looking at IBD, but this is the other side of the coin. bs can sync fast because it can cobble together any number of slow peers to reach its bandwidth limitation. bc is limited not only by its utxo accumulator sequentially, but its sophomoric network design.
(edited)