From ee9142a11353f78d73cafa674c91e9a90aaddd72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hitalo=20de=20Jesus=20do=20Ros=C3=A1rio=20Souza?= <63821277+enghitalo@users.noreply.github.com> Date: Sun, 7 Aug 2022 22:38:38 -0300 Subject: [PATCH] examples: V orm still fast? (#15330) --- .../js_dom_draw_bechmark_chart/.gitignore | 3 + .../js_dom_draw_bechmark_chart/Dockerfile | 7 + examples/js_dom_draw_bechmark_chart/README.md | 27 +++ examples/js_dom_draw_bechmark_chart/draw.js.v | 111 +++++++++ examples/js_dom_draw_bechmark_chart/main.v | 217 ++++++++++++++++++ .../templates/controller/get/all/task.html | 38 +++ 6 files changed, 403 insertions(+) create mode 100644 examples/js_dom_draw_bechmark_chart/.gitignore create mode 100644 examples/js_dom_draw_bechmark_chart/Dockerfile create mode 100644 examples/js_dom_draw_bechmark_chart/README.md create mode 100644 examples/js_dom_draw_bechmark_chart/draw.js.v create mode 100644 examples/js_dom_draw_bechmark_chart/main.v create mode 100644 examples/js_dom_draw_bechmark_chart/templates/controller/get/all/task.html diff --git a/examples/js_dom_draw_bechmark_chart/.gitignore b/examples/js_dom_draw_bechmark_chart/.gitignore new file mode 100644 index 0000000000..1a77262b14 --- /dev/null +++ b/examples/js_dom_draw_bechmark_chart/.gitignore @@ -0,0 +1,3 @@ +*.js +*.exe +*.db \ No newline at end of file diff --git a/examples/js_dom_draw_bechmark_chart/Dockerfile b/examples/js_dom_draw_bechmark_chart/Dockerfile new file mode 100644 index 0000000000..ea9b24d6ad --- /dev/null +++ b/examples/js_dom_draw_bechmark_chart/Dockerfile @@ -0,0 +1,7 @@ +FROM thevlang/vlang:alpine-dev + +WORKDIR /app + +COPY . . + +RUN v up && v -prod main.v \ No newline at end of file diff --git a/examples/js_dom_draw_bechmark_chart/README.md b/examples/js_dom_draw_bechmark_chart/README.md new file mode 100644 index 0000000000..f2ac2ca849 --- /dev/null +++ b/examples/js_dom_draw_bechmark_chart/README.md @@ -0,0 +1,27 @@ +# To run app +Dockerfile +[docker build]=> Docker image +[docker run]=> Docker container + +`sudo docker build -t .` + +`sudo docker run --name --interactive --tty --publish 3001:3001 ` + +`v run .` + +A message like `[Vweb] Running app on http://localhost:3001/` should appear + +`exit` + +# To implement new bechmarks + +create a function to bench in main.v like `fn any_function() []int {}` +that must factory return the array of time spended. +So set the attribute in canvas (with id "canvas_insert_id") +In draw.js.v put the attribute name inside of attribute_names array + + +# ROADMAP +02/09/2022 +- [ ] select bench (easy) +- [ ] vsql (easy) \ No newline at end of file diff --git a/examples/js_dom_draw_bechmark_chart/draw.js.v b/examples/js_dom_draw_bechmark_chart/draw.js.v new file mode 100644 index 0000000000..df67e8012f --- /dev/null +++ b/examples/js_dom_draw_bechmark_chart/draw.js.v @@ -0,0 +1,111 @@ +module main + +import js.dom + +fn get_canvas(elem JS.HTMLElement) JS.HTMLCanvasElement { + match elem { + JS.HTMLCanvasElement { + return elem + } + else { + panic('Not a canvas') + } + } +} + +fn draw_line(mut context JS.CanvasRenderingContext2D, x1 int, y1 int, x2 int, y2 int) { + context.beginPath() + context.strokeStyle = 'black'.str + context.lineWidth = JS.Number(1) + context.moveTo(0, 0) + context.lineTo(100, 100) + context.stroke() + context.closePath() +} + +struct DrawState { +mut: + context JS.CanvasRenderingContext2D + drawing bool + x f64 + y f64 +} + +fn (mut state DrawState) draw_bench_chart(color string, time_array []int, max_time int) ? { + println(time_array.len) + max_height := f64(480) + max_width := f64(720) + + state.drawing = true + state.x = f64(0) + state.y = f64(max_height) + state.context.strokeStyle = color.str + state.context.lineWidth = JS.Number(1) + + for i := 0; i <= time_array.len; i++ { + state.context.beginPath() + state.context.moveTo(state.x, state.y) + state.x = max_width / f64(time_array.len) * i + 1.0 + state.y = max_height - (max_height / f64(max_time) * f64(time_array[i])) + state.context.lineTo(state.x, state.y) + state.context.stroke() + state.context.closePath() + } + + state.drawing = false +} + +fn main() { + document := dom.document + + clear_btn := document.getElementById('clearButton'.str)? + + canvas_elem := document.getElementById('canvas_insert_id'.str)? + + canvas := get_canvas(canvas_elem) + ctx := canvas.getContext('2d'.str, js_undefined())? + context := match ctx { + JS.CanvasRenderingContext2D { + ctx + } + else { + panic('can not get 2d context') + } + } + mut state := DrawState{context, false, 0, 0} + + attribute_names := ['sqlite_memory_insert_times', 'sqlite_file_insert_times' /* + , + 'postgres_insert_times', 'mysql_insert_times' + */] + chart_colors := ['gray', 'black', 'red', 'orange', 'purple'] + + for idx, name in attribute_names { + // get values in JS.String values + mut attribute_js_values := canvas_elem.getAttribute(name.str) or { + println('Não pegou o attributo') + continue // if attribute not exist, jump. + } + if attribute_js_values.length < JS.Number(1) { + continue // if attribute value is empty, jump. + } + + // convert []JS.String in v []string + mut attribute_string_values := tos(attribute_js_values).replace('[', '').replace(']', + '').split(',') + + // convert []string in []int + mut attribute_int_values := []int{} + for variable in attribute_string_values { + attribute_int_values << variable.int() + } + // draw chart + state.draw_bench_chart(chart_colors[idx], attribute_int_values, 11204530) or { + println(err) + } + } + + clear_btn.addEventListener('click'.str, fn [mut state, canvas] (_ JS.Event) { + state.context.clearRect(0, 0, canvas.width, canvas.height) + }, JS.EventListenerOptions{}) +} diff --git a/examples/js_dom_draw_bechmark_chart/main.v b/examples/js_dom_draw_bechmark_chart/main.v new file mode 100644 index 0000000000..6c7b7086d5 --- /dev/null +++ b/examples/js_dom_draw_bechmark_chart/main.v @@ -0,0 +1,217 @@ +module main + +import vweb +import os +import sqlite +// import pg +// import mysql +import time +import arrays + +[table: 'benchmark'] +struct Task { +mut: + id u32 [primary; serial; sql: serial] + title string + status string +} + +const ( + http_port = 3001 + benchmark_loop_length = 10 +) + +struct App { + vweb.Context +} + +enum SqliteDbConnection { + sqlite_memory + sqlite_file +} + +fn main() { + vweb.run(new_app(), http_port) +} + +pub fn (mut app App) before_request() { + os.execute_or_panic('v -b js_browser draw.js.v ') +} + +fn new_app() &App { + mut app := &App{} + app.serve_static('/favicon.ico', 'favicon.ico') + app.serve_static('/draw.js', 'draw.js') + app.mount_static_folder_at(os.resource_abs_path('.'), '/') + return app +} + +['/'; get] +pub fn (mut app App) controller_get_all_task() vweb.Result { + // attribute_names := ['sqlite_memory_insert_times', 'sqlite_file_insert_times', + // 'postgres_insert_times', 'mysql_insert_times'] + attribute_names := ['sqlite_memory_insert_times', 'sqlite_file_insert_times'] + chart_colors := ['gray', 'black', 'red', 'orange', 'purple'] + mut insert_times := [][]int{} + + mut max_times := []int{} + mut ten_perc_max_times := []int{} + mut min_times := []int{} + mut ten_perc_min_times := []int{} + + mut max_fast := []int{} + mut ten_perc_max_fast := []int{} + mut min_fast := []int{} + mut ten_perc_min_fast := []int{} + + insert_times << factory_sqlite_memory_insert_benchmark(.sqlite_memory) + insert_times << factory_sqlite_memory_insert_benchmark(.sqlite_file) + // insert_times << factory_postgres_insert_benchmark() + // insert_times << factory_mysql_insert_benchmark() + + sqlite_memory_insert_times := insert_times[0].str().replace(' ', '') + sqlite_file_insert_times := insert_times[1].str().replace(' ', '') + // postgres_insert_times := insert_times[2].str().replace(' ', '') + // mysql_insert_times := insert_times[3].str().replace(' ', '') + + for i := 0; i < attribute_names.len; i++ { + println('insert_times[i]: ${insert_times[i]}') + ten_perc := int(insert_times[i].len / 10) + + mut min_ten_array := insert_times[i].clone() + min_ten_array.sort() + min_ten_array.trim(ten_perc) + + mut max_ten_array := insert_times[i].clone() + max_ten_array.sort(a > b) + max_ten_array.trim(ten_perc) + + max_times << arrays.max(insert_times[i]) or { 0 } + ten_perc_max_times << arrays.sum(max_ten_array) or { 0 } / ten_perc + min_times << arrays.min(insert_times[i]) or { 0 } + ten_perc_min_times << arrays.sum(min_ten_array) or { 0 } / ten_perc + } + + for i := 0; i < attribute_names.len; i++ { + max_fast << int(100 - (f64(max_times[i] * 100) / f64(arrays.max(max_times) or { + panic('deu ruim no max_fas') + }))) + ten_perc_max_fast << int(100 - (f64(ten_perc_max_times[i] * 100) / f64(arrays.max(ten_perc_max_times) or { + panic('deu ruim no max_fas') + }))) + min_fast << int(100 - (f64(min_times[i] * 100) / f64(arrays.max(min_times) or { + panic('deu ruim no max_fas') + }))) + ten_perc_min_fast << int(100 - (f64(ten_perc_min_times[i] * 100) / f64(arrays.max(ten_perc_min_times) or { + panic('deu ruim no max_fas') + }))) + } + + return $vweb.html() +} + +fn factory_sqlite_memory_insert_benchmark(db_connection SqliteDbConnection) []int { + mut result := []int{} + mut sw := time.new_stopwatch() + mut db := sqlite.connect(':memory:') or { panic(err) } + + if db_connection == .sqlite_file { + db.close() or { println('text: $err') } + db = sqlite.connect('salada.db') or { panic(err) } + } + + sql db { + create table Task + } + + task_model := Task{ + title: 'a' + status: 'done' + } + + for i := 0; i < benchmark_loop_length; i++ { + sw.start() + sql db { + insert task_model into Task + } + sw.stop() + result << int(sw.end - sw.start) + } + + sql db { + drop table Task + } + return result +} + +// fn factory_postgres_insert_benchmark() []int { +// mut result := []int{} +// mut sw := time.new_stopwatch() + +// mut db := pg.connect(pg.Config{ +// host: '127.0.0.1' +// port: 5432 +// user: 'hitalo' +// password: 'password' +// dbname: 'username' +// }) or { panic(err) } +// sql db { +// create table Task +// } + +// task_model := Task{ +// title: 'a' +// status: 'done' +// } + +// for i := 0; i < benchmark_loop_length; i++ { +// sw.start() +// sql db { +// insert task_model into Task +// } +// sw.stop() +// result << int(sw.end - sw.start) +// } + +// sql db { +// drop table Task +// } +// return result +// } + +// fn factory_mysql_insert_benchmark() []int { +// mut result := []int{} +// mut sw := time.new_stopwatch() + +// mut db := mysql.Connection{ +// host: '127.0.0.1' +// port: 3306 +// username: 'username' +// password: 'password' +// dbname: 'benchmark' +// } +// db.connect() or { println(err) } + +// sql db { +// create table Task +// } + +// task_model := Task{ +// title: 'a' +// status: 'done' +// } + +// for i := 0; i < benchmark_loop_length; i++ { +// sw.start() +// sql db { +// insert task_model into Task +// } +// sw.stop() +// result << int(sw.end - sw.start) +// } + +// sql db { +// drop table Task +// } +// return result +// } diff --git a/examples/js_dom_draw_bechmark_chart/templates/controller/get/all/task.html b/examples/js_dom_draw_bechmark_chart/templates/controller/get/all/task.html new file mode 100644 index 0000000000..33cafdca85 --- /dev/null +++ b/examples/js_dom_draw_bechmark_chart/templates/controller/get/all/task.html @@ -0,0 +1,38 @@ + + + + + V orm still fast? + +
+ + +
+ + +

Insert test

+ + + + + + + + + + @for idx, name in attribute_names + + + + + + + + @end +
Benchmark namemax.10% max.min.10% min.
@name@{max_times[idx]} ns (@{max_fast[idx]}%faster)@{ten_perc_max_times[idx]} ns (@{ten_perc_max_fast[idx]}%faster)@{min_times[idx]} ns (@{min_fast[idx]}%faster)@{ten_perc_min_times[idx]} ns (@{ten_perc_min_fast[idx]}%faster)
+

V orm still fast?

+ \ No newline at end of file