Improve interactive file-saving performance

* src/fileio.c (init_fileio):
No longer any need to set write-region-inhibit-fsync here.
(syms_of_fileio): Default write-region-inhibit-fsync to t (Bug#60474).
This commit is contained in:
Paul Eggert 2023-01-02 10:00:41 -08:00
parent c209802f7b
commit 2ee6012b3f
4 changed files with 44 additions and 37 deletions

View file

@ -801,22 +801,21 @@ in these cases, customize the variable
@vindex write-region-inhibit-fsync
Normally, when a program writes a file, the operating system briefly
caches the file's data in main memory before committing the data to
disk. This can greatly improve performance; for example, when running
on laptops, it can avoid a disk spin-up each time a file is written.
However, it risks data loss if the operating system crashes before
committing the cache to disk.
secondary storage. Although this can greatly improve performance, it
risks data loss if the system loses power before committing the cache,
and on some platforms other processes might not immediately notice the
file's change.
To lessen this risk, Emacs can invoke the @code{fsync} system call
after saving a file. Using @code{fsync} does not eliminate the risk
of data loss, partly because many systems do not implement
of data loss or slow notification, partly because many systems do not support
@code{fsync} properly, and partly because Emacs's file-saving
procedure typically relies also on directory updates that might not
survive a crash even if @code{fsync} works properly.
The @code{write-region-inhibit-fsync} variable controls whether
Emacs invokes @code{fsync} after saving a file. The variable's
default value is @code{nil} when Emacs is interactive, and @code{t}
when Emacs runs in batch mode (@pxref{Initial Options, Batch Mode}).
default value is @code{t}.
Emacs never uses @code{fsync} when writing auto-save files, as these
files might lose data anyway.

View file

@ -692,11 +692,9 @@ files that the user does not need to know about.
@defvar write-region-inhibit-fsync
If this variable's value is @code{nil}, @code{write-region} uses the
@code{fsync} system call after writing a file. Although this slows
Emacs down, it lessens the risk of data loss after power failure. If
the value is @code{t}, Emacs does not use @code{fsync}. The default
value is @code{nil} when Emacs is interactive, and @code{t} when Emacs
runs in batch mode. @xref{Files and Storage}.
@code{fsync} system call after writing a file. If the value is
@code{t}, Emacs does not use @code{fsync}. The default value is
@code{t}. @xref{Files and Storage}.
@end defvar
@defmac with-temp-file file body@dots{}
@ -2038,17 +2036,28 @@ data already stored elsewhere on secondary storage until one file or
the other is later modified; this will lose both files if the only
copy on secondary storage is lost due to media failure. Second, the
operating system might not write data to secondary storage
immediately, which will lose the data if power is lost.
immediately, which will lose the data if power is lost
or if there is a media failure.
@findex write-region
Although both sorts of failures can largely be avoided by a suitably
configured file system, such systems are typically more expensive or
less efficient. In more-typical systems, to survive media failure you
configured system, such systems are typically more expensive or
less efficient. In lower-end systems, to survive media failure you
can copy the file to a different device, and to survive a power
failure you can use the @code{write-region} function with the
failure (or be immediately notified of a media failure) you can use
the @code{write-region} function with the
@code{write-region-inhibit-fsync} variable set to @code{nil}.
Although this variable is ordinarily @code{t} because that can
significantly improve performance, it may make sense to temporarily
bind it to @code{nil} if using Emacs to implement database-like
transactions that survive power failure on lower-end systems.
@xref{Writing to Files}.
On some platforms when Emacs changes a file other processes might not
be notified of the change immediately. Setting
@code{write-region-inhibit-fsync} to @code{nil} may improve
notification speed in this case, though there are no guarantees.
@node File Names
@section File Names
@cindex file names

View file

@ -41,6 +41,10 @@ compositing manager, Emacs will now redisplay such a frame even though
'frame-visible-' returns nil or 'icon' for it. This can happen, for
example, as part of preview for iconified frames.
+++
** 'write-region-inhibit-fsync' now defaults to t in interactive mode,
as it has in batch mode since Emacs 24.
* Editing Changes in Emacs 30.1

View file

@ -6334,24 +6334,6 @@ init_fileio (void)
umask (realmask);
valid_timestamp_file_system = 0;
/* fsync can be a significant performance hit. Often it doesn't
suffice to make the file-save operation survive a crash. For
batch scripts, which are typically part of larger shell commands
that don't fsync other files, its effect on performance can be
significant so its utility is particularly questionable.
Hence, for now by default fsync is used only when interactive.
For more on why fsync often fails to work on today's hardware, see:
Zheng M et al. Understanding the robustness of SSDs under power fault.
11th USENIX Conf. on File and Storage Technologies, 2013 (FAST '13), 271-84
https://www.usenix.org/system/files/conference/fast13/fast13-final80.pdf
For more on why fsync does not suffice even if it works properly, see:
Roche X. Necessary step(s) to synchronize filename operations on disk.
Austin Group Defect 672, 2013-03-19
https://austingroupbugs.net/view.php?id=672 */
write_region_inhibit_fsync = noninteractive;
}
void
@ -6609,9 +6591,22 @@ file is usually more useful if it contains the deleted text. */);
DEFVAR_BOOL ("write-region-inhibit-fsync", write_region_inhibit_fsync,
doc: /* Non-nil means don't call fsync in `write-region'.
This variable affects calls to `write-region' as well as save commands.
Setting this to nil may avoid data loss if the system loses power or
the operating system crashes. By default, it is non-nil in batch mode. */);
write_region_inhibit_fsync = 0; /* See also `init_fileio' above. */
By default, it is non-nil.
Although setting this to nil may avoid data loss if the system loses power,
it can be a significant performance hit in the usual case, and it doesn't
necessarily cause file-save operations to actually survive a crash. */);
/* For more on why fsync often fails to work on today's hardware, see:
Zheng M et al. Understanding the robustness of SSDs under power fault.
11th USENIX Conf. on File and Storage Technologies, 2013 (FAST '13), 271-84
https://www.usenix.org/system/files/conference/fast13/fast13-final80.pdf
For more on why fsync does not suffice even if it works properly, see:
Roche X. Necessary step(s) to synchronize filename operations on disk.
Austin Group Defect 672, 2013-03-19
https://austingroupbugs.net/view.php?id=672 */
write_region_inhibit_fsync = true;
DEFVAR_BOOL ("delete-by-moving-to-trash", delete_by_moving_to_trash,
doc: /* Specifies whether to use the system's trash can.