Given that the Ethernet MTU is 1,500 bytes, this causes the read response to be split across 41 packets, as you can see if you look at a wireshark capture of a file being downloaded by this code. If any one of those packets gets lost, the entire request and response needs to be retransmitted.
I found I got much better results using the same read size as the players themselves (2,048 bytes), and configuring the UDP RPC client to have a timeout of 250 milliseconds, with an exponential backoff. What is your timeout?
I will try to look into this and test my download speeds with different chunk sizes. I am currently using a timeout of one second, which is quite probably too much.
https://github.com/flesniak/python-prodj-link/blob/4be86a86a74f1e90604c2d0e0abe2d2c2b02a238/nfsclient.py#L20-L21
Given that the Ethernet MTU is 1,500 bytes, this causes the read response to be split across 41 packets, as you can see if you look at a wireshark capture of a file being downloaded by this code. If any one of those packets gets lost, the entire request and response needs to be retransmitted.
I found I got much better results using the same read size as the players themselves (2,048 bytes), and configuring the UDP RPC client to have a timeout of 250 milliseconds, with an exponential backoff. What is your timeout?