forked from jess/Acord
Fix excessive writing to disk by gating r/w behind in-mem hash checks first.
This commit is contained in:
parent
9c0a74c1ce
commit
035164a698
|
|
@ -32,6 +32,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuItemValidation {
|
||||||
/// eval overlay. By writing straight to disk, autosave can't disturb
|
/// eval overlay. By writing straight to disk, autosave can't disturb
|
||||||
/// what the user sees.
|
/// what the user sees.
|
||||||
private var autosaveTimer: Timer?
|
private var autosaveTimer: Timer?
|
||||||
|
/// Hash of the viewport text the last time autosave actually wrote to
|
||||||
|
/// disk. The 100ms timer compares against this and skips the write if
|
||||||
|
/// nothing has changed — without this gate, autosave rewrites the
|
||||||
|
/// entire file every tick (~500 KB/s sustained on a 50 KB doc, which
|
||||||
|
/// macOS flags as a disk-writes throttle event).
|
||||||
|
private var lastAutosavedHash: Int?
|
||||||
|
|
||||||
private var viewport: IcedViewportView? {
|
private var viewport: IcedViewportView? {
|
||||||
window?.contentView as? IcedViewportView
|
window?.contentView as? IcedViewportView
|
||||||
|
|
@ -719,7 +725,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSMenuItemValidation {
|
||||||
guard let w = window, let vp = w.contentView as? IcedViewportView else { return }
|
guard let w = window, let vp = w.contentView as? IcedViewportView else { return }
|
||||||
let text = vp.getText()
|
let text = vp.getText()
|
||||||
guard !AppState.isEffectivelyBlank(text) else { return }
|
guard !AppState.isEffectivelyBlank(text) else { return }
|
||||||
|
let hash = text.hashValue
|
||||||
|
if hash == lastAutosavedHash { return }
|
||||||
appState.writeAutosavedCopy(text: text)
|
appState.writeAutosavedCopy(text: text)
|
||||||
|
lastAutosavedHash = hash
|
||||||
}
|
}
|
||||||
|
|
||||||
private func observeDocumentTitle() {
|
private func observeDocumentTitle() {
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,29 @@ pub struct ViewportHandle {
|
||||||
pub needs_redraw: bool,
|
pub needs_redraw: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Install a panic hook that flushes a full backtrace to stderr before
|
||||||
|
/// the process aborts. Called once on first viewport_create. Without this
|
||||||
|
/// the host (Swift / winit) often eats the panic message and the user sees
|
||||||
|
/// only a silent SIGABRT with no `.ips` file.
|
||||||
|
fn install_panic_hook() {
|
||||||
|
use std::sync::Once;
|
||||||
|
static ONCE: Once = Once::new();
|
||||||
|
ONCE.call_once(|| {
|
||||||
|
let prior = std::panic::take_hook();
|
||||||
|
std::panic::set_hook(Box::new(move |info| {
|
||||||
|
use std::io::Write;
|
||||||
|
let mut err = std::io::stderr().lock();
|
||||||
|
let _ = writeln!(err, "===== ACORD RUST PANIC =====");
|
||||||
|
let _ = writeln!(err, "{}", info);
|
||||||
|
let bt = std::backtrace::Backtrace::force_capture();
|
||||||
|
let _ = writeln!(err, "{}", bt);
|
||||||
|
let _ = writeln!(err, "============================");
|
||||||
|
let _ = err.flush();
|
||||||
|
prior(info);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn viewport_create(
|
pub extern "C" fn viewport_create(
|
||||||
nsview: *mut c_void,
|
nsview: *mut c_void,
|
||||||
|
|
@ -55,6 +78,7 @@ pub extern "C" fn viewport_create(
|
||||||
height: f32,
|
height: f32,
|
||||||
scale: f32,
|
scale: f32,
|
||||||
) -> *mut ViewportHandle {
|
) -> *mut ViewportHandle {
|
||||||
|
install_panic_hook();
|
||||||
if nsview.is_null() {
|
if nsview.is_null() {
|
||||||
return std::ptr::null_mut();
|
return std::ptr::null_mut();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue