Skip to content

Commit

Permalink
edit action insertion benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
disconcision committed Nov 14, 2024
1 parent 05a890e commit edd3154
Show file tree
Hide file tree
Showing 5 changed files with 249 additions and 80 deletions.
7 changes: 7 additions & 0 deletions src/core/editor/Zipper.re
Original file line number Diff line number Diff line change
Expand Up @@ -303,3 +303,10 @@ let selection_str = (cur: Cursor.Base.t('tok)): option(string) =>
|> String.concat("")
|> Option.some
};

let to_string = (z: t): string => {
zip(z)
|> Cell.flatten
|> List.map((x: Token.t) => x.text)
|> String.concat("");
};
135 changes: 135 additions & 0 deletions src/web/Benchmark.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
open Tylr_core;

/* given base program string, figure out how many copies to concatenate
to get a program of the provided number of lines, do that concat, and then trim to the exact line count.
*/
let get_program_string_of_length = (program_str, num_lines: int): string => {
let base_lines = program_str |> String.split_on_char('\n');
let base_num_lines = base_lines |> List.length;
let num_copies = num_lines / base_num_lines;
let remainder = num_lines mod base_num_lines + 1;
let program = String.concat("\n", List.init(num_copies, _ => program_str));
let program =
program
++ String.concat("\n", fst(Stds.Lists.split_n(base_lines, remainder)));
program;
};

let benchmark = progam_str =>
Util.TimeUtil.get_time(() => progam_str |> Store.parse |> ignore);

let time_per_line = (lines: int, time: int): float => {
float_of_int(time) /. float_of_int(lines);
};

let benchmark_parsing = () => {
let program_str = Data.longlong;
print_endline(
"BENCHMARK: parsing (prefix of) complete program with no internal obligations",
);
let num_tokens = Labeler.label(program_str) |> List.length;
let num_chars = program_str |> String.length;
let num_lines = program_str |> String.split_on_char('\n') |> List.length;
print_endline(
"BENCHMARK: base program consists of "
++ string_of_int(num_lines)
++ " lines, "
++ string_of_int(num_chars)
++ " chars, and "
++ string_of_int(num_tokens)
++ " tokens",
);
print_endline(
"BENCHMARK: Average tokens per line: "
++ string_of_float(float_of_int(num_tokens) /. float_of_int(num_lines)),
);
print_endline(
"BENCHMARK: Average chars per line: "
++ string_of_float(float_of_int(num_chars) /. float_of_int(num_lines)),
);
let a = benchmark(program_str);
print_endline("BENCHMARK: warmup parse: " ++ string_of_int(a) ++ "ms");
let b = benchmark(program_str);
print_endline(
"BENCHMARK: same parse after warmup: " ++ string_of_int(b) ++ "ms",
);
for (i in 1 to 20) {
let num_lines = 30 * i;
let program_str = get_program_string_of_length(program_str, num_lines);
let c = benchmark(program_str);
print_endline(
"ITERATION "
++ string_of_int(i)
++ " :"
++ string_of_int(num_lines)
++ " lines. parsed in "
++ string_of_int(c)
++ "ms",
);
// print_endline(
// "time per line: "
// ++ string_of_float(time_per_line(num_lines, c))
// ++ "ms",
// );
};
};

let cursor_depth = (z: Zipper.t) => {
let cell = Zipper.zip(~save_cursor=true, z);
switch (cell.marks.cursor) {
| Some(Point(cursor)) => cursor.path |> List.length
| _ => failwith("benchmark: no cursor")
};
};

let benchmark_hole_fills = () => {
let program_str = Data.holey;
let reps_per_action = 200;
let zipper_action = Modify.insert("X");

print_endline("BENCHMARK: filling hole edits at different depths");
let a = benchmark(program_str);
print_endline("BENCHMARK: warmup parse: " ++ string_of_int(a) ++ "ms");
let b = benchmark(program_str);
print_endline(
"BENCHMARK: same parse after warmup: " ++ string_of_int(b) ++ "ms",
);
let z =
List.fold_left(
(z_acc, _x) => {
// perform insertion action repeatedly
let t =
Util.TimeUtil.get_time(() => {
for (_ in 1 to reps_per_action) {
let _ = zipper_action(z_acc);
();
}
});
print_endline(
"depth: "
++ string_of_int(cursor_depth(z_acc))
++ ", "
++ "time for "
++ string_of_int(reps_per_action)
++ " insertions:"
++ string_of_int(t)
++ "ms",
);
// fill hole and return zipper with caret moved to previous hole
let z2 = Modify.insert("X", z_acc);
switch (Tab.perform(L, z2)) {
| None => z2
| Some(z3) => z3
};
},
// starts at bottom of holey program
Store.parse(program_str),
List.init(20, _ => ()),
);
();
print_endline("program after actions:");
print_endline(z |> Zipper.to_string);
};

//benchmark_parsing();
benchmark_hole_fills();
101 changes: 101 additions & 0 deletions src/web/Data.re
Original file line number Diff line number Diff line change
Expand Up @@ -482,3 +482,104 @@ let r = dist(center, p) in
circle(center, r) in
|};

let holey = {|let x = + 1 in
let y = 2 in
let x = 1 + 1 in
let y = 2 * 1 + 3 < 56 * + 345442 in
type Emoji = Smile + Frown + Smirk in
type Cell = Empty + Stamped(Emoji) in
type Model = ([[ ]], Emoji) in
type Action =
StampEmoji(Int, Int)
+ ClearCell(Int, Int)
+ SelectEmoji(Emoji)
in
let init: Model = (
[[None, None, None],
[None, None, None],
[None, None, ]],
Smile)
in
let update_grid: (Int, Int, Cell, [[Cell]]) -> [[Cell]] =
fun (row, col, cell, grid) ->
update_nth(row, update_nth(col, cell, List.nth(row, grid)), grid)
in
let update: (Model, Action) -> Model =
fun ((cells, selected), action) ->
case action
| StampEmoji(row, col) =>
(update_grid(row, , Stamped(Smile), cells), selected)
| ClearCell(row, col) =>
(update_grid(row, col, Empty, cells), selected)
| SelectEmoji( ) => (cells, new)
end
in
type Point = (Int, Int) in
type Rect = (Point, Int, Int) in
type Circ = (Point, Int) in
type Shape = R(Rect) + C(Circ) in
let contains = fun ( , p: Point) ->
let (x, y) = p in
case s
| R(((x_min, y_min), x_len, y_len)) =>
<= x && x <= x_min + x_len
&& y_min <= y && y <= y_min +
| C((center, r)) => dist(center, p) <= r
end
in
type Point = (Int, Int) in
type Rect = (Point, Int, Int) in
let contains = fun (r: Rect, p: Point) ->
let (x, y) = p in
let ((x_min, y_min), x_len, y_len) = r in
x_min <= x && x <= x_min + x_len
&& y_min <= y && y <= y_min + y_len
in
let blah = shapes
|> filter(fun shape -> area(shape) < 50)
|> map(dilate(5))
|> map(rotate( / 4))
|> map(translate(6, 7)) in
let blah = shapes
|> map(rotate(pi / 4))
|> map(translate(, 7))
|> filter(fun shape -> area( ) < 50)
|> map(dilate(5)) in
let f = fun (square, p1, p2) ->
let =
fun center ->
if square then
let (x, y) = center in
rect(x - 2, y - 2, 4, )
else
let r = 4 in
circle(center, )
in
[mark(p1), line(p1, p2), mark(p2)] in
let f = fun (p1, p2) ->
let mark =
fun center ->
let r = 4 in
circle(center, )
in
[mark(p1), line(p1, p2), mark(p2)] in
let dist =
fun (p1, p2) ->
let (x1, ) = p1 in
let (x2, y2) = p2 in
sqrt(pow(x1 - x2, 2) + pow(y1 - y2, ))
in
let f = fun (center, p) ->
let r = dist(center, p) in
circle( , r) in
|};
80 changes: 1 addition & 79 deletions src/web/Store.re
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ let save_syntax_key: int => string =
let save_syntax = (save_idx: int, z: Zipper.t) =>
LocalStorage.set(save_syntax_key(save_idx), z |> serialize);

let tasks = []; //Data.longlong,
let tasks = [Data.holey]; //Data.longlong,
//Data.epzz,
// Data.epz0,
// Data.epz1,
Expand Down Expand Up @@ -67,81 +67,3 @@ let load_syntax: int => Zipper.t =
| None => load_default_syntax(save_idx)
| Some(str) => deserialize(str)
};

//let unparse: Zipper.t => string = z => z |> Zipper.zip |> Cell.tokens;

/* given base program string Data.longlong, figure out how many copies to concatenate
to get a program of the provided number of lines, do that concat, and then trim to the exact line count.
*/
let get_program_string_of_length = (program_str, num_lines: int): string => {
let base_lines = program_str |> String.split_on_char('\n');
let base_num_lines = base_lines |> List.length;
let num_copies = num_lines / base_num_lines;
let remainder = num_lines mod base_num_lines + 1;
let program = String.concat("\n", List.init(num_copies, _ => program_str));
let program =
program
++ String.concat("\n", fst(Stds.Lists.split_n(base_lines, remainder)));
program;
};

let benchmark = progam_str =>
Util.TimeUtil.get_time(() => progam_str |> parse |> ignore);

let time_per_line = (lines: int, time: int): float => {
float_of_int(time) /. float_of_int(lines);
};

let suite = () => {
let program_str = Data.longlong;
print_endline(
"BENCHMARK: parsing (prefix of) complete program with no internal obligations",
);
let num_tokens = Labeler.label(program_str) |> List.length;
let num_chars = program_str |> String.length;
let num_lines = program_str |> String.split_on_char('\n') |> List.length;
print_endline(
"BENCHMARK: base program consists of "
++ string_of_int(num_lines)
++ " lines, "
++ string_of_int(num_chars)
++ " chars, and "
++ string_of_int(num_tokens)
++ " tokens",
);
print_endline(
"BENCHMARK: Average tokens per line: "
++ string_of_float(float_of_int(num_tokens) /. float_of_int(num_lines)),
);
print_endline(
"BENCHMARK: Average chars per line: "
++ string_of_float(float_of_int(num_chars) /. float_of_int(num_lines)),
);
let a = benchmark(program_str);
print_endline("BENCHMARK: warmup parse: " ++ string_of_int(a) ++ "ms");
let b = benchmark(program_str);
print_endline(
"BENCHMARK: same parse after warmup: " ++ string_of_int(b) ++ "ms",
);
for (i in 1 to 20) {
let num_lines = 30 * i;
let program_str = get_program_string_of_length(program_str, num_lines);
let c = benchmark(program_str);
print_endline(
"ITERATION "
++ string_of_int(i)
++ " :"
++ string_of_int(num_lines)
++ " lines. parsed in "
++ string_of_int(c)
++ "ms",
);
// print_endline(
// "time per line: "
// ++ string_of_float(time_per_line(num_lines, c))
// ++ "ms",
// );
};
};

suite();
6 changes: 5 additions & 1 deletion src/web/update/Update.re
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,11 @@ let apply =
// | SetLogoFont(logo_font_metrics) =>
// Ok({...model, logo_font_metrics})
| PerformAction(a) =>
switch (Edit.perform(a, model.zipper)) {
switch (
Util.TimeUtil.measure_time("Edit.perform", true, () =>
Edit.perform(a, model.zipper)
)
) {
| None => Error(FailedToPerform)
| Some(z) =>
Ok({...model, zipper: z, history: History.do_(a, z, model.history)})
Expand Down

0 comments on commit edd3154

Please sign in to comment.