Comments (8)
Please create a PR and I‘ll take a look at it.
from js-framework-benchmark.
Faster than vanillajs can be only vanillajs.
Jokes aside, there is an issue in this very case as well as in general, it is related not with measurements but with the simplicity of this very benchmark. So, here is either an over-optimization or a deviation from the expected implementation (aka cheating) in your toy framework which tricks the benchmark.
With that being said, those figures are easily achieved with a simple css
rule, like this one:
table tr:nth-child(n+11) { display: none; }
@krausest I guess this "issue" is a evidence that some kind of checking for elements visibility should be implemented to improve the reliability of the benchmark.
from js-framework-benchmark.
Faster than vanillajs can be only vanillajs. Jokes aside, there is an issue in this very case as well as in general, it is related not with measurements but with the simplicity of this very benchmark. So, here is either an over-optimization or a deviation from the expected implementation (aka cheating) in your toy framework which tricks the benchmark. With that being said, those figures are easily achieved with a simple
css
rule, like this one:table tr:nth-child(n+11) { display: none; }@krausest I guess this "issue" is a evidence that some kind of checking for elements visibility should be implemented to improve the reliability of the benchmark.
Thank you for replying. I am happy to collaborate in order to track down the exact cause. My implementation is pretty much a mix of an immediate mode gui with elm-like message passing. I'm hooking the dom events with messages that then get handled asynchronously (updating the app state), and then running old_builder.rebuild(new_builder) - comparing old changes with the new changes and applying the diff. Framework was not written with cheating of any benchmark in mind. To be honest, I haven't done any optimizations at this point as I focused on the api and only ran the benchmark out of curiosity.
TLDR: I'm not a troll :P
from js-framework-benchmark.
use std::sync::atomic::{AtomicUsize, Ordering};
use futures_util::StreamExt;
use korvin::core::{
element_builder::{AsElementBuilder, ElementBuilder},
flavors::elm_like::Communicator,
Runtime,
};
use rand::{seq::SliceRandom, thread_rng};
use web_sys::MouseEvent;
static ADJECTIVES: &[&str] = &[
"pretty",
"large",
"big",
"small",
"tall",
"short",
"long",
"handsome",
"plain",
"quaint",
"clean",
"elegant",
"easy",
"angry",
"crazy",
"helpful",
"mushy",
"odd",
"unsightly",
"adorable",
"important",
"inexpensive",
"cheap",
"expensive",
"fancy",
];
static COLOURS: &[&str] = &[
"red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black",
"orange",
];
static NOUNS: &[&str] = &[
"table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger",
"pizza", "mouse", "keyboard",
];
fn button<F: FnOnce(ElementBuilder) -> ElementBuilder>(
id: &str,
text: &str,
button: F,
) -> ElementBuilder {
"div".attribute("class", "col-sm-6 smallpad").child(button(
"button"
.attribute("id", id)
.attribute("class", "btn btn-primary btn-block")
.attribute("type", "button")
.text(text),
))
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct RowData {
id: usize,
label: String,
}
static ID_COUNTER: AtomicUsize = AtomicUsize::new(1);
fn build_data(count: usize) -> Vec<RowData> {
let mut thread_rng = thread_rng();
let mut data = Vec::new();
data.reserve_exact(count);
for _i in 0..count {
let adjective = ADJECTIVES.choose(&mut thread_rng).unwrap();
let colour = COLOURS.choose(&mut thread_rng).unwrap();
let noun = NOUNS.choose(&mut thread_rng).unwrap();
let capacity = adjective.len() + colour.len() + noun.len() + 2;
let mut label = String::with_capacity(capacity);
label.push_str(adjective);
label.push(' ');
label.push_str(colour);
label.push(' ');
label.push_str(noun);
data.push(RowData {
id: ID_COUNTER.fetch_add(1, Ordering::Relaxed),
label,
});
}
data
}
#[derive(Default)]
struct App {
data: Vec<RowData>,
selected: Option<usize>,
}
impl App {
fn handle(&mut self, message: AppMessage) {
match message {
AppMessage::Create1000Rows => self.data = build_data(1000),
AppMessage::Create10000Rows => self.data = build_data(10000),
AppMessage::Append1000Rows => self.data.append(&mut build_data(1000)),
AppMessage::UpdateEvery10thRow => self
.data
.iter_mut()
.step_by(10)
.for_each(|row| row.label.push_str(" !!!")),
AppMessage::Clear => {
self.selected = None;
self.data.clear();
}
AppMessage::SwapRows => {
if self.data.len() > 998 {
self.data.swap(1, 998)
}
}
AppMessage::SetSelected(id) => self.selected = Some(id),
AppMessage::Remove(id) => self.data.retain(|row| row.id != id),
}
}
}
#[derive(Clone, Copy, Hash)]
enum AppMessage {
Create1000Rows,
Create10000Rows,
Append1000Rows,
UpdateEvery10thRow,
Clear,
SwapRows,
SetSelected(usize),
Remove(usize),
}
fn app(communicator: Communicator<AppMessage>, App { data, selected }: &App) -> ElementBuilder {
let div = |class: &str| "div".attribute("class", class);
let mousedown_send = move |message| move |_: MouseEvent| communicator.send(message);
let element_mousedown_send = |element: ElementBuilder, message| {
element.event(message, "mousedown", mousedown_send(message))
};
let message_button =
|id, text, message| button(id, text, |button| element_mousedown_send(button, message));
let jumbotron = div("jumbotron")
.child(div("col-md-6").child("h1".text("Korvin")))
.child(div("col-md-6"))
.child(
div("row")
.child(message_button(
"run",
"Create 1,000 rows",
AppMessage::Create1000Rows,
))
.child(message_button(
"runlots",
"Create 10,000 rows",
AppMessage::Create10000Rows,
))
.child(message_button(
"add",
"Append 1,000 rows",
AppMessage::Append1000Rows,
))
.child(message_button(
"update",
"Update every 10th row",
AppMessage::UpdateEvery10thRow,
))
.child(message_button("clear", "Clear", AppMessage::Clear))
.child(message_button(
"swaprows",
"Swap Rows",
AppMessage::SwapRows,
)),
);
let table = "table"
.attribute("class", "table table-hover table-striped test-data")
.child("tbody".children(data.iter().map(|RowData { id, label }| {
let mut tr = "tr".into_builder();
if selected
.as_ref()
.map(|selected| selected.eq(id))
.unwrap_or_default()
{
tr = tr.attribute("class", "danger");
}
let td = |class: &str| "td".attribute("class", class);
let row = {
td("col-md-4").child(element_mousedown_send(
"a".text(label.as_str()),
AppMessage::SetSelected(*id),
))
};
tr.child(td("col-md-1").text(id.to_string().as_str()))
.child(row)
.child(
td("col-md-1").child(element_mousedown_send(
"a".child(
"span"
.attribute("class", "glyphicon glyphicon-remove")
.attribute("aria-hidden", "true"),
),
AppMessage::Remove(*id),
)),
)
.child(td("col-md-6"))
})));
div("container").child(jumbotron).child(table).child(
"span"
.attribute("class", "preloadicon glyphicon glyphicon-remove")
.attribute("aria-hidden", "true"),
)
}
fn main() {
console_error_panic_hook::set_once();
let main = web_sys::window()
.and_then(|w| w.document())
.map(|d| d.query_selector("#main").unwrap().unwrap())
.unwrap();
wasm_bindgen_futures::spawn_local(async move {
let mut runtime = Runtime::new(main);
let (mut rx, communicator) = Communicator::create();
let mut state = App::default();
runtime
.dom_executor
.rebuild(app(communicator, &state).build())
.unwrap();
while let Some(message) = rx.next().await {
state.handle(message);
runtime
.dom_executor
.rebuild(app(communicator, &state).build())
.unwrap()
}
});
}
here is the code for reference
from js-framework-benchmark.
TLDR: I'm not a troll :P
Don't get me wrong, people love challenges and some frameworks in this benchmark can be tracked down to have been built just to fulfill the purpose of "fastest framework".
Anyway, I see this is a Rust implementation and the few Rust frameworks here doesn't show such a breakthrough in performance. Again, as I said, I personally don't think this is a measurement issue, as the measurements here are pretty straightforward and have been battle-tested on very different kind of implementations. Thus my only assumption is that there is something wrong within your framework/implementation, but I cannot confirm this only by looking at the code you provided. Maybe you can just submit a PR with this non-keyed framework, for a better visibility for all concerned?
from js-framework-benchmark.
sorry for the delay, but as I said it's a toy project and I needed to clean it up, also korvin is a much more serious name than bimber (kind of polish alcoholic drink). In case you need help with building everything from source ping me on discord: niedzwiedzw
from js-framework-benchmark.
repo with library source code:
https://github.com/Niedzwiedzw/korvin
from js-framework-benchmark.
we have figured out the reason of measurement corruption
turns out the implementation needs to use "click" event, as using "mousedown" will offset the measurement by the browser lag. closing :)
from js-framework-benchmark.
Related Issues (20)
- 90 percentile calculation make comparisons across browser versions impossible. HOT 4
- The weight is killing innovations in `JS` frameworks HOT 28
- Remove lighthouse metrics? HOT 10
- Tracing misses sometimes the click event HOT 3
- isKeyed test appears to be wrong for qwik HOT 4
- Please add jQuery if just for completion HOT 2
- .NET 8 Released HOT 1
- archive petite-vue
- sprae should be flagged #1139 HOT 2
- doohtml should be flagged #801 HOT 2
- Number of warm-up runs should not be the same every time HOT 3
- The test "total kilobyte weight" might not cover assets cached by service worker HOT 2
- Suggestion: transpose + sort + group table HOT 2
- Results of locally tested frameworks (libraries e.t.c.) are sometimes at the end of the table HOT 1
- hydro-js is broken HOT 1
- Suggestion: calculation for transferred sizes HOT 6
- add htmx and astro for the benchmark ? HOT 3
- Add "Fresh" web framework. HOT 1
- Check #1139 flag HOT 6
- Suggestion: Improvement for Vanillajs-1 implementation HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from js-framework-benchmark.