This commit is contained in:
Rizky 2024-02-20 15:03:09 +07:00
parent b9a877911e
commit 86ef473710
8 changed files with 120 additions and 70 deletions

File diff suppressed because one or more lines are too long

View File

@ -11,7 +11,7 @@ import { SyncConnection } from "../type";
import { parseJs } from "../editor/parser/parse-js";
import { snapshot } from "../entity/snapshot";
import { validate } from "uuid";
import { gzipAsync } from "utils/diff";
import { gzipAsync } from "utils/diff/diff";
const decoder = new TextDecoder();
const timeout = {

View File

@ -3,7 +3,7 @@ import { SAction } from "../actions";
import { docs } from "../entity/docs";
import { gunzipAsync } from "../entity/zlib";
import { SyncConnection } from "../type";
import { gzipAsync } from "utils/diff";
import { gzipAsync } from "utils/diff/diff";
const history = {} as Record<string, string>;

View File

@ -170,7 +170,7 @@ export const EDGlobal = {
page: {
history: {
id: "",
show: false
show: false,
},
root_id: "root",
cur: EmptyPage,
@ -231,6 +231,7 @@ export const EDGlobal = {
open: {} as Record<string, string[]>,
},
popup: {
file: { enabled: false },
code: {
init: false,
open: false,
@ -273,7 +274,7 @@ export const EDGlobal = {
comp: {
preview_id: "",
open: null as null | ((comp_id: string) => void | Promise<void>),
import: false
import: false,
},
comp_group: null as null | {
mouse_event: React.MouseEvent<HTMLElement, MouseEvent>;

View File

@ -1,56 +0,0 @@
import { describe } from "bun:test";
import { readAsync } from "fs-jetpack";
import { Diff, gunzipAsync } from "./diff";
import { Packr } from "msgpackr";
const MAX_HISTORY = 10;
const packr = new Packr({});
describe("simple diff", async () => {
const server = await Diff.server<any>(await readAsync("tsconfig.json"));
const patch = await server.getPatch("new");
console.log("init", hmn(patch.length));
const client = await Diff.client<string>(patch);
console.log("\npatch1");
await server.update("rako12");
const patch1 = await server.getPatch(client.ts);
await client.applyPatch(patch1);
console.log(
hmn(patch1.length),
`|| client: ${hmn((await client.data).length)}`
);
console.log("\npatch2");
const bin = await readAsync("data/prod/main.js", "utf8");
await server.update(bin);
const patch2 = await server.getPatch(client.ts);
await client.applyPatch(patch2);
console.log(
hmn(patch2.length),
`|| client: ${hmn((await client.data).length)}`
);
console.log("\npatch3");
const ubin = "mantappu" + bin?.substring(0,100000);
await server.update(ubin);
const patch3 = await server.getPatch(client.ts);
await client.applyPatch(patch3);
console.log(
hmn(patch3.length),
`|| client: ${hmn((await client.data).length)}`
);
});
function hmn(bytes: number): string {
const sizes = ["bytes", "KB", "MB", "GB", "TB"];
if (bytes === 0) return "0 bytes";
const i = Math.floor(Math.log(bytes) / Math.log(1024));
const size = i === 0 ? bytes : (bytes / Math.pow(1024, i)).toFixed(2);
return `${size} ${sizes[i]}`;
}

View File

@ -0,0 +1,84 @@
import { describe } from "bun:test";
import { readAsync } from "fs-jetpack";
import { Diff, gunzipAsync } from "./diff";
import { Packr } from "msgpackr";
const MAX_HISTORY = 10;
const packr = new Packr({});
describe("simple diff", async () => {
const json = await readAsync("data/1MB.json", "json") as any[];
const server = await Diff.server<any>(json);
const patch = await server.getPatch("new");
console.log("init");
const client = await Diff.client<string>(patch);
console.log(
hmn(patch.length),
`|| client: ${hmn(JSON.stringify(await client.data).length)}`
);
console.log("\npatch1");
json.shift();
json.shift();
json.shift();
await server.update(json);
const patch1 = await server.getPatch(client.ts);
await client.applyPatch(patch1);
console.log(
hmn(patch1.length),
`|| client: ${hmn(JSON.stringify(await client.data).length)}`
);
// console.log("\npatch15");
// await server.update({ moka: { rako: "1231" } });
// const patch15 = await server.getPatch(client.ts);
// await client.applyPatch(patch15);
// console.log(
// hmn(patch15.length),
// `|| client: ${JSON.stringify(await client.data)}`
// );
// console.log("\npatch2");
// const bin = await readAsync("data/prod/main.js", "utf8");
// await server.update(bin);
// const patch2 = await server.getPatch(client.ts);
// await client.applyPatch(patch2);
// console.log(
// hmn(patch2.length),
// `|| client: ${hmn((await client.data).length)}`
// );
// if (bin) {
// console.log("\npatch2.5");
// await server.update(bin.substring(0, 10) + "1" + bin.substring(10));
// const patch25 = await server.getPatch(client.ts);
// await client.applyPatch(patch25);
// console.log(
// hmn(patch25.length),
// `|| client: ${hmn((await client.data).length)}`
// );
// }
// console.log("\npatch3");
// const ubin = "mantappu" + bin?.substring(0, 100000);
// await server.update(ubin);
// const patch3 = await server.getPatch(client.ts);
// await client.applyPatch(patch3);
// console.log(
// hmn(patch3.length),
// `|| client: ${hmn((await client.data).length)}`
// );
});
function hmn(bytes: number): string {
const sizes = ["bytes", "KB", "MB", "GB", "TB"];
if (bytes === 0) return "0 bytes";
const i = Math.floor(Math.log(bytes) / Math.log(1024));
const size = i === 0 ? bytes : (bytes / Math.pow(1024, i)).toFixed(2);
return `${size} ${sizes[i]}`;
}

View File

@ -1,9 +1,9 @@
import { applyPatch, calcPatch } from "./diff-internal";
import { Packr } from "msgpackr";
import { gunzip, gzip } from "zlib";
import { applyPatch, calcPatch } from "./lib/fast-myers-diff";
const MAX_HISTORY = 25; // max history item
const MAX_DIFF_TIMEOUT = 50; // in ms
const MAX_FMD_TIMEOUT = 100; // in ms
const packr = new Packr({});
@ -12,9 +12,14 @@ type PATCH_RESULT =
mode: "new";
ts: string;
data: number[];
}
| {
mode: "patch-fmd";
ts: string;
diff: any;
}
| {
mode: "patch";
mode: "patch-fd";
ts: string;
diff: any;
};
@ -74,12 +79,13 @@ export class Diff<T> {
return old_data[key1] === this._data[key2];
},
() => {
return performance.now() - now > MAX_DIFF_TIMEOUT;
return performance.now() - now > MAX_FMD_TIMEOUT;
}
),
];
if (performance.now() - now <= MAX_DIFF_TIMEOUT) {
if (performance.now() - now <= MAX_FMD_TIMEOUT) {
console.log(Math.round(performance.now() - now) + "ms");
done(
new Uint8Array(
packr.pack({ diff: result_diff, mode: "patch", ts: this.ts })
@ -100,6 +106,7 @@ export class Diff<T> {
async applyPatch(_patch: Uint8Array) {
const patch = packr.unpack(_patch) as PATCH_RESULT;
console.log(patch.mode, `size: ${hmn(_patch.length)}`);
if (patch.mode === "new") {
this.ts = patch.ts;
if (patch.data) this._data = patch.data;
@ -113,7 +120,7 @@ export class Diff<T> {
}
} else {
num_array.push(num);
}
}
}
this._data = num_array;
}
@ -156,3 +163,13 @@ export const gunzipAsync = (bin: Uint8Array) => {
});
});
};
function hmn(bytes: number): string {
const sizes = ["bytes", "KB", "MB", "GB", "TB"];
if (bytes === 0) return "0 bytes";
const i = Math.floor(Math.log(bytes) / Math.log(1024));
const size = i === 0 ? bytes : (bytes / Math.pow(1024, i)).toFixed(2);
return `${size} ${sizes[i]}`;
}

View File

@ -250,9 +250,13 @@ export function diff_core(
): IterableIterator<Vec4> {
const Z = (Math.min(N, M) + 1) * 2;
const L = N + M;
const b = new (L < 256 ? Uint8Array : L < 65536 ? Uint16Array : Uint32Array)(
2 * Z
);
let constructor: any = Float64Array;
if (L < 256) constructor = Uint8Array;
else if (L < 65536) constructor = Uint16Array;
else if (L < 4294967297) constructor = Uint32Array;
const b = new constructor(2 * Z);
return new DiffGen({
i,