I found another in-place approach which also does a higher-base version described here: https://arxiv.org/pdf/2302.03317, with an open source implementation: https://crates.io/crates/rip_shuffle. Might want to compare it with your version.
It's substantially the same algorithm so any differences would just be down to implementation details. Other than multi-threading which BQN doesn't do. The usage is also a little different as BQN generates shuffled integers directly; generating the integers is 100ms of the 850ms for rip_shuffle but I'm not sure whether it makes sense to subtract that or not.