mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-27 19:52:49 +00:00
Speed up cold diffs and wrapped text measurement (#4676)
* perf(app): optimize wrapped measurements and checkpoint native layout experiment Compute full grapheme geometry only for final wrap fragments. Preserve shaped-text search behavior while bounding additive wrap probes. Keep the Android background layout experiment isolated from the normal diff renderer; native renderer integration and iOS bindings remain unfinished. * perf(server): reduce cold diff generation work Keep active diff reads owned across invalidation and wait for the initial watcher inventory before cold generation. Batch patch and blob reads while preserving per-file size isolation, bounded output, and daemon responsiveness. Avoid constructing fallback tokens when full-file highlighting already covers both sides. * test(server): exercise oversized highlighted diff rejection The single-line fixture now bypasses highlighting under the long-line guard, so it no longer reaches the structured payload limit. Use short dense lines to keep testing oversized rejection and continued socket usability. * fix(server): queue fresh diffs for forced reads A forced request following a repository mutation must not reuse an older active build. Invalidate that result and coalesce waiting callers onto one subsequent build. Give the cache a named object input and completed-value type. * test(server): share deferred diff loader setup * test(server): name completed diff cache setup * refactor(server): use aliases for new diff imports * fix(server): keep shipped diff imports resolvable by Node The TypeScript build preserves path aliases without a runtime resolver. Restore relative imports for shipped code and declarations, and correct the server import guideline that prompted the regression.
This commit is contained in:
@@ -8,7 +8,7 @@ import {
|
||||
} from "@/utils/diff-layout";
|
||||
import { compactHighlightTokens } from "@/utils/diff-rendering";
|
||||
import { getInlineReviewThreadState, getSplitInlineReviewThreadState } from "@/review/geometry";
|
||||
import { advancesFor } from "./text-measurement";
|
||||
import { advancesFor, requiresShaping } from "./text-measurement";
|
||||
import type {
|
||||
BuildDiffDocumentModelInput,
|
||||
DiffCell,
|
||||
@@ -571,14 +571,31 @@ export function measureFragments(input: {
|
||||
return [createFragment(graphemes, 0, graphemes.length, 0, input.lineHeight, input.measureText)];
|
||||
}
|
||||
const fragments: DiffFragment[] = [];
|
||||
const displayGraphemes = graphemes.map((grapheme) => grapheme.text);
|
||||
const measureWidth =
|
||||
input.measureText.measureWidth?.bind(input.measureText) ??
|
||||
((slice: readonly string[]) => advancesFor(input.measureText)(slice).at(-1) ?? 0);
|
||||
// Joining/ligatures can make a longer prefix narrower. Preserve the existing
|
||||
// search order for those runs; changing the probes can change their breaks.
|
||||
const canBoundSearch = !requiresShaping(input.text);
|
||||
let graphemeIndex = 0;
|
||||
while (graphemeIndex < graphemes.length) {
|
||||
let low = graphemeIndex + 1;
|
||||
let high = graphemes.length;
|
||||
// A small first probe finishes short lines in one query. Grow it only when
|
||||
// it fits, so narrow wrapping never repeatedly measures a huge line's tail.
|
||||
let high = canBoundSearch ? Math.min(graphemes.length, graphemeIndex + 64) : graphemes.length;
|
||||
let fitting = low;
|
||||
if (canBoundSearch) {
|
||||
while (measureWidth(displayGraphemes.slice(graphemeIndex, high)) <= input.availableWidth) {
|
||||
fitting = high;
|
||||
low = high + 1;
|
||||
if (high === graphemes.length) break;
|
||||
high = Math.min(graphemes.length, graphemeIndex + (high - graphemeIndex) * 2);
|
||||
}
|
||||
}
|
||||
while (low <= high) {
|
||||
const middle = (low + high) >>> 1;
|
||||
const width = measureGraphemeSlice(graphemes, graphemeIndex, middle, input.measureText).width;
|
||||
const width = measureWidth(displayGraphemes.slice(graphemeIndex, middle));
|
||||
if (width <= input.availableWidth || middle === graphemeIndex + 1) {
|
||||
fitting = middle;
|
||||
low = middle + 1;
|
||||
|
||||
Reference in New Issue
Block a user