I use simple smoothing function in Simcoin's time sync to adjust node's time difference:

`time_diff = (time_diff * 7 + new_diff) / 8;`

It provides nice integration, which smooths any sudden changes.

It also has a dead zone if you calculate it using integers:

This should help with filtering small random variations.

A faster equivalent of the above code is:

`time_diff = ((time_diff << 3) - time_diff + new_diff) >> 3;`

To my surprise, when I switched to it the standard deviation of time between nodes dropped from about 10 ms to less than 1! An order of magnitude improvement!

What the...? How is this possible?!

Let's investigate.

====

The first thing I noticed is that the dead zone is not symmetrical:

Oops. But since both formulas give exactly the same results for positive numbers, this can't be it.

Let's look at negative numbers:

Aha. These formulas stop being completely equivalent for negative numbers:

`(-1000 * 7 - 999) / 8 = -999`

(-1000 * 7 - 999) >> 3 = -1000

But the difference is 1, how can this create such a dramatic effect? Let's dig deeper.

Plotting both functions side by side shows that when the value drops, the original function (red) has a dead zone, but the new one (yellow) does not:

What if the value grows? Then the picture flips:

Now the original doesn't have the dead zone and the new one does. So switching to the new function flips the asymmetric dead zone for negative numbers. So what?

Turns out this aligns dead zones for positive and negative numbers. This means that nodes above network time will not move in one direction on slight changes, and the nodes below network time will not move

*in the same direction!* This creates a resistance wall, to which the value "sticks", greatly reducing variation.

Indeed, adding a simple explicit dead zone:

`if(abs(time_diff - new_diff) < 8) return;`

Produces the same result.

A simple tweak to make the dead zone symmetrical improves things further:

`time_diff = (time_diff * 7 + new_diff + 4) >> 3;`

Note, that this tweak doesn't work in case of integer division! For that you also need to clear the lowest 3 bits before dividing:

`time_diff = (time_diff * 7 + new_diff + 4) & ~7) / 8;`

Then both will be identical again.

====

The time sync algorithm is full of such surprises, where tiny, seemingly insignificant details have a big impact.