Many people seem to run into this error quite often.
From the logs that I've seens, the main cause seems to be the updates we're doing in the blockticking - the more block types we actually process, the more blockchanges there are to be sent to the clients. With a viewdistance of 9 (default), there could be as many as 361 packets to be sent per tick (1/20 sec). That means that in a mere 5 ticks the packet queue is almost full. If the client's TCP stack lags behind more than 1/8 second, they are bound to be disconnected due to the "packet queue full" error.
Also the bandwidth used is increasing. Each BlockChange packet is 12 bytes, each MultiBlockChange is at least 19 bytes. That could easily add up to 80 KiB/sec just for the blockchanges.
We need to find a better way of handling this.
(to be continued)
One solution comes to my mind that could be easy enough to implement: Delay the blockchanges sending for chunks that are far from the players. For example, if the distance to the player is less than 48 blocks, send each blockchange. If it's between 48 and 128 blocks, send blockchanges only every 4 ticks. If it's further, send blockchanges every 16 ticks.
That means that single-block changes won't be sent that often, they will get queued and combined into multiblock change packets that have a much better "blocks per network byte" ratio. Those multiblock packets will grow, too, but only 4 bytes per block changed, unlike 12 bytes for a single-block change packet.
Instead of doing "every 4 ticks" or "every 16 ticks", we could even do things as "at least 4 changes", "at least 16 changes", but we'd still need to cap the max delay to, say, 20 ticks, so that the blockchanges eventually do get to the players.
From the logs that I've seens, the main cause seems to be the updates we're doing in the blockticking - the more block types we actually process, the more blockchanges there are to be sent to the clients. With a viewdistance of 9 (default), there could be as many as 361 packets to be sent per tick (1/20 sec). That means that in a mere 5 ticks the packet queue is almost full. If the client's TCP stack lags behind more than 1/8 second, they are bound to be disconnected due to the "packet queue full" error.
Also the bandwidth used is increasing. Each BlockChange packet is 12 bytes, each MultiBlockChange is at least 19 bytes. That could easily add up to 80 KiB/sec just for the blockchanges.
We need to find a better way of handling this.
(to be continued)
One solution comes to my mind that could be easy enough to implement: Delay the blockchanges sending for chunks that are far from the players. For example, if the distance to the player is less than 48 blocks, send each blockchange. If it's between 48 and 128 blocks, send blockchanges only every 4 ticks. If it's further, send blockchanges every 16 ticks.
That means that single-block changes won't be sent that often, they will get queued and combined into multiblock change packets that have a much better "blocks per network byte" ratio. Those multiblock packets will grow, too, but only 4 bytes per block changed, unlike 12 bytes for a single-block change packet.
Instead of doing "every 4 ticks" or "every 16 ticks", we could even do things as "at least 4 changes", "at least 16 changes", but we'd still need to cap the max delay to, say, 20 ticks, so that the blockchanges eventually do get to the players.