Similar to https://github.com/dotnet/corefx/issues/26024 but for write
This blocks using msbuild incremental build. Especially when using MemoryMappedFile, LastWriteTime will not be set automatically
```c#
using System;
using System.IO;
namespace testLastAccess
{
class Program
{
static void Main(string[] args)
{
File.WriteAllText("file_reference", "");
File.WriteAllText("file_change_lastaccess", "");
File.SetLastAccessTimeUtc("file_change_lastaccess", DateTime.UtcNow);
Console.WriteLine(File.GetLastWriteTimeUtc("file_reference").Ticks + " file_reference");
Console.WriteLine(File.GetLastWriteTimeUtc("file_change_lastaccess").Ticks + " file_change_lastaccess");
}
}
}
on Ubuntu
wul@willauzrelinux3:~/test/testSetFileLastAccessTime$ dotnet run
636681614066249674 file_reference
636681614060000000 file_change_lastaccess
file_change_lastaccess has SetLastAccessTimeUtc after file_reference is created. But end up easier than file_reference. And clearly, the ticks are rounded.
on Windows it is correct
位 dotnet run
636681613739905306 file_reference
636681613739915309 file_change_lastaccess
```
@Anipik could you please take a look when you free up?
yep I will take a look at it sometime next week :)
I'll set the milestone to 2.1.x for now.
Ugh, I see the comment shows the problem -- when fixing, please help check that we don't have anywhere else in CoreFX/CoreCLR that does not set milliseconds. For a start we should not use utime anywhere we can use utimensat or utimes.
c#
private void SetAccessWriteTimes(string path, long? accessTime, long? writeTime)
{
// force a refresh so that we have an up-to-date times for values not being overwritten
_fileStatusInitialized = -1;
EnsureStatInitialized(path);
Interop.Sys.UTimBuf buf;
// we use utime() not utimensat() so we drop the subsecond part
buf.AcTime = accessTime ?? _fileStatus.ATime;
buf.ModTime = writeTime ?? _fileStatus.MTime;
Interop.CheckIo(Interop.Sys.UTime(path, ref buf), path, InitiallyDirectory);
_fileStatusInitialized = -1;
}
It looks like this impact large project solution builds. Currently Ubuntu takes 2 times of time to build incrementally than Windows
yeah it will be an improvement. I will post the numbers when I put the PR to fix this
I am able to make it work using utimes
@wli3 can you confirm that following is the required output ?
Discovering: System.IO.FileSystem.Tests
Discovered: System.IO.FileSystem.Tests
Starting: System.IO.FileSystem.Tests
636686696383220724 file_reference
636686696383221610 file_change_lastaccess
@Anipik yes, this looks good
@danmosemsft its fixed in master, do we want it to go for release branch
Thanks @anipik you're the file timestamp expert now. Yes, please add the template to this issue, create the port PR, and send mail to the usual alias per the procedure in my email and while back.
Thanks :) I will do that
Currently, when we set the LastAccessTime or LastModifiedTime of the files on Unix, the millisecond/micrososecond/nanosecond attribute of the timestamp of the file is always set to zero.
The customers will be able to set Last Access Time or Last Modified Time in Unix to nanosecond granularity.
Incremental build is faster by 2% on unix systems.
Not a Regression
Low risk because this change is already in master.
We are now using utimensat function to set the timestamp, if the utimensat is not available on the machine we are falling back to utimes
Approved for 2.1.5.
Hold your checkin until further notice about branch availability.
Updated the template with performance numbers
Fixed in 3.0 in PR dotnet/corefx#31522 (setting milestone accordingly & closing).
Note: The 2.1.x port was rejected - see PR dotnet/corefx#31569.
Most helpful comment
Approved for 2.1.5.
Hold your checkin until further notice about branch availability.