Compare commits

..

6 Commits

Author SHA1 Message Date
8b5ab06b67 Add more console.log 2023-09-20 18:18:35 -04:00
94b606d2d9 Cache the width/height with the engine manager 2023-09-20 17:33:37 -04:00
2a2cc44baa appease the format gods 2023-09-20 15:58:49 -04:00
2d31f5b0e0 Fix typing 2023-09-20 15:54:42 -04:00
bb12eec7f9 Use useRef to store the Engine
useRef is a React Hook that lets you reference a value that’s not needed
for rendering. The value is set to the initial value on startup, and
will hang on to 'current' for us. We can store the Engine in the ref,
and React will take care of persisting it for us.

Signed-off-by: Paul Tagliamonte <paul@kittycad.io>
2023-09-20 15:44:06 -04:00
b67c16cc9d Benchmark for KCL parser (#664)
* KCL benchmarks

* CI for benchmarks

* More specific name for benchmark

* Benchmark the right directory

* Format
2023-09-20 13:15:28 -05:00
11 changed files with 264 additions and 63 deletions

View File

@ -54,4 +54,4 @@ jobs:
- name: Run clippy
run: |
cd "${{ matrix.dir }}"
cargo clippy --all --tests -- -D warnings
cargo clippy --all --tests --benches -- -D warnings

37
.github/workflows/cargo-criterion.yml vendored Normal file
View File

@ -0,0 +1,37 @@
on:
push:
branches:
- main
paths:
- '**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-criterion.yml
pull_request:
paths:
- '**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-criterion.yml
workflow_dispatch:
permissions: read-all
name: cargo criterion
jobs:
cargocriterion:
name: cargo criterion
runs-on: ubuntu-latest-8-cores
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: |
cargo install cargo-criterion
- name: Rust Cache
uses: Swatinem/rust-cache@v2.6.1
- name: Benchmark kcl library
shell: bash
run: |-
cd src/wasm-lib/kcl; cargo criterion

2
.gitignore vendored
View File

@ -22,6 +22,8 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
src/wasm-lib/.idea
# rust
src/wasm-lib/target
src/wasm-lib/bindings

View File

@ -57,7 +57,7 @@
"zustand": "^4.1.4"
},
"scripts": {
"start": "BROWSER=none vite",
"start": "vite",
"build": "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && source \"$HOME/.cargo/env\" && curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -y && yarn build:wasm && vite build",
"build:local": "vite build",
"build:both": "vite build",
@ -65,7 +65,7 @@
"pretest": "yarn remove-importmeta",
"test": "vitest --mode development",
"test:nowatch": "vitest run --mode development",
"test:rust": "(cd src/wasm-lib && cargo test --all && cargo clippy --all --tests)",
"test:rust": "(cd src/wasm-lib && cargo test --all && cargo clippy --all --tests --benches)",
"test:cov": "vitest run --coverage --mode development",
"simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &",
"simpleserver": "yarn pretest && http-server ./public --cors -p 3000",

View File

@ -1,4 +1,4 @@
import { useLayoutEffect } from 'react'
import { useRef, useLayoutEffect } from 'react'
import { _executor } from '../lang/executor'
import { useStore } from '../useStore'
import { EngineCommandManager } from '../lang/std/engineConnection'
@ -28,6 +28,11 @@ export function useSetupEngineManager(
const quadWidth = Math.round(width / 4) * 4
const height = streamHeight ? streamHeight : 0
const quadHeight = Math.round(height / 4) * 4
const eng = useRef<{
engine: EngineCommandManager
width: number
height: number
} | null>(null)
useLayoutEffect(() => {
setStreamDimensions({
@ -35,19 +40,37 @@ export function useSetupEngineManager(
streamHeight: quadHeight,
})
if (!width || !height) return
const eng = new EngineCommandManager({
setMediaStream,
setIsStreamReady,
width: quadWidth,
height: quadHeight,
token,
})
setEngineCommandManager(eng)
eng.waitForReady.then(() => {
if (eng.current) {
// Before we go further, we're going to check to see if the
// width/height is the same as the last go-around. If it is, we
// can continue as normal, but if it's different, we should be
// clearing out the manager and going again.
let c = eng.current
if (width !== c.width || height !== c.height) {
eng.current = null
}
}
if (eng.current === null) {
eng.current = {
engine: new EngineCommandManager({
setMediaStream,
setIsStreamReady,
width: quadWidth,
height: quadHeight,
token,
}),
width: width,
height: height,
}
}
setEngineCommandManager(eng.current.engine)
eng.current.engine.waitForReady.then(() => {
executeCode()
})
return () => {
eng?.tearDown()
eng.current?.engine?.tearDown()
}
}, [quadWidth, quadHeight])
}

View File

@ -68,12 +68,12 @@ export class EngineConnection {
constructor({
url,
token,
onWebsocketOpen = () => {},
onNewTrack = () => {},
onEngineConnectionOpen = () => {},
onConnectionStarted = () => {},
onClose = () => {},
onDataChannelOpen = () => {},
onWebsocketOpen = () => { },
onNewTrack = () => { },
onEngineConnectionOpen = () => { },
onConnectionStarted = () => { },
onClose = () => { },
onDataChannelOpen = () => { },
}: {
url: string
token?: string
@ -364,8 +364,10 @@ export class EngineConnection {
// fix responsiveness for clients that had a weird network hiccup.
const connectionTimeoutMs = VITE_KC_CONNECTION_TIMEOUT_MS
console.log('setting timeout for connection')
setTimeout(() => {
if (this.isReady()) {
console.log('timeout fired but we were ready')
return
}
console.log('engine connection timeout on connection, retrying')
@ -531,8 +533,8 @@ export class EngineCommandManager {
outSequence = 1
inSequence = 1
engineConnection?: EngineConnection
waitForReady: Promise<void> = new Promise(() => {})
private resolveReady = () => {}
waitForReady: Promise<void> = new Promise(() => { })
private resolveReady = () => { }
subscriptions: {
[event: string]: {
@ -561,6 +563,7 @@ export class EngineCommandManager {
this.resolveReady = resolve
})
const url = `${VITE_KC_API_WS_MODELING_URL}?video_res_width=${width}&video_res_height=${height}`
console.log('new eng conn')
this.engineConnection = new EngineConnection({
url,
token,
@ -777,7 +780,6 @@ export class EngineCommandManager {
lastMessage = command.cmd.type
}
if (!this.engineConnection?.isReady()) {
console.log('socket not ready')
return Promise.resolve()
}
if (command.type !== 'modeling_cmd_req') return Promise.resolve()
@ -824,7 +826,6 @@ export class EngineCommandManager {
this.sourceRangeMap[id] = range
if (!this.engineConnection?.isReady()) {
console.log('socket not ready')
return Promise.resolve()
}
this.engineConnection?.send(command)
@ -842,7 +843,7 @@ export class EngineCommandManager {
command: Models['ModelingCmd_type'],
range?: SourceRange
) {
let resolve: (val: any) => void = () => {}
let resolve: (val: any) => void = () => { }
const promise = new Promise((_resolve, reject) => {
resolve = _resolve
})

130
src/wasm-lib/Cargo.lock generated
View File

@ -63,6 +63,12 @@ dependencies = [
"libc",
]
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
version = "0.5.0"
@ -337,6 +343,12 @@ dependencies = [
"serde",
]
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.0.83"
@ -374,6 +386,33 @@ dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "ciborium"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
[[package]]
name = "ciborium-ll"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"
dependencies = [
"ciborium-io",
"half 1.8.2",
]
[[package]]
name = "clang-sys"
version = "1.6.1"
@ -507,6 +546,42 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "criterion"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
dependencies = [
"anes",
"cast",
"ciborium",
"clap",
"criterion-plot",
"is-terminal",
"itertools 0.10.5",
"num-traits",
"once_cell",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
dependencies = [
"cast",
"itertools 0.10.5",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.8"
@ -716,7 +791,7 @@ checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8"
dependencies = [
"bit_field",
"flume",
"half",
"half 2.2.1",
"lebe",
"miniz_oxide",
"rayon-core",
@ -983,6 +1058,12 @@ dependencies = [
"tracing",
]
[[package]]
name = "half"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]]
name = "half"
version = "2.2.1"
@ -1287,6 +1368,7 @@ dependencies = [
"async-trait",
"bson",
"clap",
"criterion",
"dashmap",
"derive-docs",
"expectorate",
@ -1316,6 +1398,8 @@ dependencies = [
[[package]]
name = "kittycad"
version = "0.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9cf962b1e81a0b4eb923a727e761b40672cbacc7f5f0b75e13579d346352bc7"
dependencies = [
"anyhow",
"async-trait",
@ -1604,6 +1688,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d11de466f4a3006fe8a5e7ec84e93b79c70cb992ae0aa0eb631ad2df8abfe2"
[[package]]
name = "oorandom"
version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "openapitor"
version = "0.0.9"
@ -1837,6 +1927,34 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "plotters"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
[[package]]
name = "plotters-svg"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
dependencies = [
"plotters-backend",
]
[[package]]
name = "png"
version = "0.17.10"
@ -2851,6 +2969,16 @@ dependencies = [
"time-core",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "tinyvec"
version = "1.6.0"

View File

@ -11,8 +11,7 @@ crate-type = ["cdylib"]
bson = { version = "2.7.0", features = ["uuid-1", "chrono"] }
gloo-utils = "0.2.0"
kcl-lib = { path = "kcl" }
#kittycad = { version = "0.2.25", default-features = false, features = ["js"] }
kittycad = { git = "https://github.com/KittyCAD/kittycad.rs", branch = "achalmers/relative-path-segments" }
kittycad = { version = "0.2.25", default-features = false, features = ["js"] }
serde_json = "1.0.107"
uuid = { version = "1.4.1", features = ["v4", "js", "serde"] }
wasm-bindgen = "0.2.87"
@ -21,8 +20,7 @@ wasm-bindgen-futures = "0.4.37"
[dev-dependencies]
anyhow = "1"
image = "0.24.7"
#kittycad = "0.2.25"
kittycad = { git = "https://github.com/KittyCAD/kittycad.rs", branch = "achalmers/relative-path-segments" }
kittycad = "0.2.25"
pretty_assertions = "1.4.0"
reqwest = { version = "0.11.20", default-features = false }
tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros", "time"] }

View File

@ -14,7 +14,7 @@ clap = { version = "4.4.3", features = ["cargo", "derive", "env", "unicode"], op
dashmap = "5.5.3"
#derive-docs = { version = "0.1.4" }
derive-docs = { path = "../derive-docs" }
kittycad = { git = "https://github.com/KittyCAD/kittycad.rs", branch = "achalmers/relative-path-segments", default-features = false, features = ["js"] }
kittycad = { version = "0.2.25", default-features = false, features = ["js"] }
lazy_static = "1.4.0"
parse-display = "0.8.2"
regex = "1.7.1"
@ -50,7 +50,12 @@ panic = "abort"
debug = true
[dev-dependencies]
criterion = "0.5.1"
expectorate = "1.0.7"
itertools = "0.11.0"
pretty_assertions = "1.4.0"
tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros", "time"] }
[[bench]]
name = "compiler_benchmark"
harness = false

View File

@ -0,0 +1,27 @@
use criterion::{criterion_group, criterion_main, Criterion};
pub fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("parse + lex cube program", |b| b.iter(lex_and_parse_cube));
}
fn lex_and_parse_cube() {
let program = r#"
fn cube = (pos, scale) => {
const sg = startSketchAt(pos)
|> line([0, scale], %)
|> line([scale, 0], %)
|> line([0, -scale], %)
return sg
}
const b1 = cube([0,0], 10)
const pt1 = b1[0]
show(b1)"#;
let tokens = kcl_lib::tokeniser::lexer(program);
let parser = kcl_lib::parser::Parser::new(tokens);
parser.ast().unwrap();
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

View File

@ -67,7 +67,6 @@ fn inner_line_to(
y: to[1],
z: 0.0,
},
relative: false,
},
},
)?;
@ -202,7 +201,6 @@ fn inner_line(data: LineData, sketch_group: Box<SketchGroup>, args: &mut Args) -
LineData::Point(to) => *to,
};
let delta = inner_args;
let to = [from.x + inner_args[0], from.y + inner_args[1]];
let id = uuid::Uuid::new_v4();
@ -213,11 +211,10 @@ fn inner_line(data: LineData, sketch_group: Box<SketchGroup>, args: &mut Args) -
path: sketch_group.id,
segment: kittycad::types::PathSegment::Line {
end: Point3D {
x: delta[0],
y: delta[1],
x: to[0],
y: to[1],
z: 0.0,
},
relative: true
},
},
)?;
@ -352,17 +349,9 @@ fn inner_angled_line(
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
AngledLineData::AngleAndLength(angle_and_length) => (angle_and_length[0], angle_and_length[1]),
};
//double check me on this one - mike
let delta: [f64; 2] = [
length * f64::cos(angle.to_radians()),
length * f64::sin(angle.to_radians()),
];
let relative = true;
let to: [f64; 2] = [
from.x + delta[0],
from.y + delta[1],
from.x + length * f64::cos(angle.to_radians()),
from.y + length * f64::sin(angle.to_radians()),
];
let id = uuid::Uuid::new_v4();
@ -389,11 +378,10 @@ fn inner_angled_line(
path: sketch_group.id,
segment: kittycad::types::PathSegment::Line {
end: Point3D {
x: delta[0],
y: delta[1],
x: to[0],
y: to[1],
z: 0.0,
},
relative: relative,
},
},
)?;
@ -844,14 +832,9 @@ fn inner_arc(data: ArcData, sketch_group: Box<SketchGroup>, args: &mut Args) ->
angle_end: angle_end.degrees(),
center: center.into(),
radius,
relative: false,
},
},
)?;
// TODO: Dont do this (move path pen) - mike
// lets review what the needs are here and see if any existing arc endpoints can accomplish this
// Move the path pen to the end of the arc.
// Since that is where we want to draw the next path.
// TODO: the engine should automatically move the pen to the end of the arc.
@ -944,8 +927,6 @@ fn inner_bezier_curve(
BezierData::Points { to, control1, control2 } => (to, control1, control2),
};
let relative = true;
let delta = to;
let to = [from.x + to[0], from.y + to[1]];
let id = uuid::Uuid::new_v4();
@ -956,21 +937,20 @@ fn inner_bezier_curve(
path: sketch_group.id,
segment: kittycad::types::PathSegment::Bezier {
control1: Point3D {
x: control1[0],
y: control1[1],
x: from.x + control1[0],
y: from.y + control1[1],
z: 0.0,
},
control2: Point3D {
x: control2[0],
y: control2[1],
x: from.x + control2[0],
y: from.y + control2[1],
z: 0.0,
},
end: Point3D {
x: delta[0],
y: delta[1],
x: to[0],
y: to[1],
z: 0.0,
},
relative: relative
},
},
)?;