Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
examples: V orm still fast? (#15330)
- Loading branch information
Showing
6 changed files
with
403 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
*.js | ||
*.exe | ||
*.db |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
FROM thevlang/vlang:alpine-dev | ||
|
||
WORKDIR /app | ||
|
||
COPY . . | ||
|
||
RUN v up && v -prod main.v |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# To run app | ||
Dockerfile | ||
[docker build]=> Docker image | ||
[docker run]=> Docker container | ||
|
||
`sudo docker build -t <name> .` | ||
|
||
`sudo docker run --name <container name> --interactive --tty --publish 3001:3001 <name>` | ||
|
||
`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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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{}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
// } |
Oops, something went wrong.