Le lun. 7 déc. 2020 à 17:22, David Mertz <me...@gnosis.cx> a écrit :
> Are there any filesystems that can actually record a meaningful ns 
> modification time?  I find discussions claiming this:
>
> EXT4: millisecond precision

EXT4 and BTRFS have a resolution of 1 nanosecond.

> XFS and EXT3: second precision

XFS is going to support a resolution of 1 nanosecond in the incoming
Linux kernel 5.10:
https://www.phoronix.com/scan.php?page=news_item&px=XFS-Linux-5.10

> NTFS: 100ns precision
> APFS: 1 ns precision
>
> But also notes that the precision is likely to exceed the accuracy by many 
> times on real systems.

On my Fedora 33 with Linux 5.9 and Python 3.9, time.time_ns() has an
effective resolution around 71 nanoseconds (smallest difference which
can be measured in user space):
-----------------
import time

t0 = time.time_ns()
endtime = t0 + 5 * 1000_000_000

previous = t0
res = None
while True:
    t1, t2 = (time.time_ns(), time.time_ns())
    if t1 >= endtime:
        break
    dt = t2 - t1
    if not dt:
        dt = t1 - previous
    if not dt:
        continue
    if res is None or dt < res:
        res = dt
    previous = t2

print(f"time.time_ns() resolution: {res} nanoseconds")
-----------------

*Reading* the system clock in Python (as nanoseconds) already takes
around 50 nanoseconds!

$ python3 -m pyperf timeit -s 'import time; func=time.time_ns'
--duplicate=1024 'func()'
Mean +- std dev: 49.8 ns +- 1.2 ns

The IEEE-754 floating point number format is a weird beast. A number
"resolution" depends on its value. IMO this article well explains
that:
https://fabiensanglard.net/floating_point_visually_explained/

Python float resolution (using Unix epoch, 1970-01-01 at 00:00):

* 1970-01-01 00:00 (0 seconds) => res = 4.9e-315 ns
* 1970-01-02 00:00 (1 day) => res = 0.01 ns
* 1970-01-01 00:00 (31 days) => res = 0.5 ns
* 1970-04-09 00:00 (98 days) => res = 1.9 ns
* 2020-12-07 00:00 (18,603 days) => res = 238.4 ns <=== TODAY

Note: Windows uses 1601-01-01 Epoch for its FILETIME timestamp, but
hopefully os.stat() shifts the value to the Unix Epoch (otherwise, the
resolution would be way worse on Windows!).

The resolution got worse than 1 nanosecond since April 9th, 1970.
Today a timestamp using the Unix epoch has a resolution worse than 238
ns.

See PEP 564 which added "_ns" functions to the time module to Python
3.7, like time.time_ns():
https://www.python.org/dev/peps/pep-0564/

>>> import datetime, match
>>> epoch=datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc)
>>> t=epoch; ts=t.timestamp(); (t, ts, math.ulp(ts)*1e9)
(datetime.datetime(1970, 1, 1, 0, 0, tzinfo=datetime.timezone.utc),
0.0, 4.94065646e-315)
>>> t=epoch+datetime.timedelta(days=1); ts=t.timestamp(); (t, ts, 
>>> math.ulp(ts)*1e9)
(datetime.datetime(1970, 1, 2, 0, 0, tzinfo=datetime.timezone.utc),
86400.0, 0.014551915228366852)
>>> t=epoch+datetime.timedelta(days=31); ts=t.timestamp(); (t, ts, 
>>> math.ulp(ts)*1e9)
(datetime.datetime(1970, 2, 1, 0, 0, tzinfo=datetime.timezone.utc),
2678400.0, 0.46566128730773926)
>>> t=epoch+datetime.timedelta(days=98); ts=t.timestamp(); (t, ts, 
>>> math.ulp(ts)*1e9)
(datetime.datetime(1970, 4, 9, 0, 0, tzinfo=datetime.timezone.utc),
8467200.0, 1.862645149230957)
>>> t=datetime.datetime(2020, 12, 7, tzinfo=datetime.timezone.utc); 
>>> ts=t.timestamp(); (t, ts, math.ulp(ts)*1e9)
(datetime.datetime(2020, 12, 7, 0, 0, tzinfo=datetime.timezone.utc),
1607299200.0, 238.4185791015625)


Conclusion: store timestamp as an integer number of nanoseconds, not
as a float ;-)

Victor
-- 
Night gathers, and now my watch begins. It shall not end until my death.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/FBK7FEG57VHWC73SZ3LZW47AFONSTTUZ/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to