mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
examples: js_dom_draw_bechmark_chart (#15518)
This commit is contained in:
parent
ca99a1d355
commit
21b2a9841a
@ -1,4 +1,15 @@
|
||||
# To run app
|
||||
## From root
|
||||
- run typescript project
|
||||
`npm i --prefix examples/js_dom_draw_bechmark_chart/typescript_vanilla_typeorm`
|
||||
`npm run start:dev --prefix examples/js_dom_draw_bechmark_chart/typescript_vanilla_typeorm`
|
||||
|
||||
- run v project
|
||||
`v run examples/js_dom_draw_bechmark_chart/v_vweb_orm `
|
||||
|
||||
- running v chart
|
||||
`cd examples/js_dom_draw_bechmark_chart/chart && v run .`
|
||||
|
||||
Dockerfile
|
||||
[docker build]=> Docker image
|
||||
[docker run]=> Docker container
|
||||
@ -13,12 +24,83 @@ A message like `[Vweb] Running app on http://localhost:3001/` should appear
|
||||
|
||||
`exit`
|
||||
|
||||
# To implement new bechmarks
|
||||
# To implement new bechmarks in v
|
||||
|
||||
In `examples/js_dom_draw_bechmark_chart/v_vweb_orm/src/main.v` path
|
||||
Create a route returning a `Response` struct like:
|
||||
|
||||
```v ignore
|
||||
['/sqlite-memory/:count']
|
||||
pub fn (mut app App) sqlite_memory(count int) vweb.Result {
|
||||
mut insert_stopwatchs := []int{}
|
||||
mut select_stopwatchs := []int{}
|
||||
mut update_stopwatchs := []int{}
|
||||
|
||||
mut sw := time.new_stopwatch()
|
||||
|
||||
mut db := sqlite.connect(':memory:') or { panic(err) }
|
||||
|
||||
sql db {
|
||||
create table Task
|
||||
}
|
||||
|
||||
task_model := Task{
|
||||
title: 'a'
|
||||
status: 'done'
|
||||
}
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
sw.start()
|
||||
sql db {
|
||||
insert task_model into Task
|
||||
}
|
||||
sw.stop()
|
||||
insert_stopwatchs << int(sw.end - sw.start)
|
||||
}
|
||||
|
||||
sql db {
|
||||
drop table Task
|
||||
}
|
||||
|
||||
response := Response{
|
||||
insert: insert_stopwatchs
|
||||
@select:select_stopwatchs
|
||||
update: update_stopwatchs
|
||||
}
|
||||
return app.json(response)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
In `examples/chart/services.v` path
|
||||
Create a service to request the benchmarks data by http
|
||||
Decode the info to `FrameworkBenchmarkResponse`
|
||||
```v ignore
|
||||
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
||||
url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
|
||||
res := http.get(url) or { panic(err) }
|
||||
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
|
||||
return framework_benchmark_response
|
||||
}
|
||||
```
|
||||
|
||||
In `examples/chart/main.v` path
|
||||
Create a service to request the benchmarks data by http
|
||||
Decode the info to `FrameworkBenchmarkResponse`
|
||||
```v ignore
|
||||
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
||||
url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
|
||||
res := http.get(url) or { panic(err) }
|
||||
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
|
||||
return framework_benchmark_response
|
||||
}
|
||||
```
|
||||
Then, update:
|
||||
`insert_framework_benchmark_times()`;
|
||||
`select_framework_benchmark_times()`;
|
||||
`update_framework_benchmark_times()`.
|
||||
with the new function
|
||||
|
||||
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
|
||||
|
98
examples/js_dom_draw_bechmark_chart/chart/README.md
Normal file
98
examples/js_dom_draw_bechmark_chart/chart/README.md
Normal file
@ -0,0 +1,98 @@
|
||||
# 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 in v
|
||||
|
||||
In `examples/js_dom_draw_bechmark_chart/v_vweb_orm/src/main.v` path
|
||||
Create a route returning a `Response` struct like:
|
||||
|
||||
```v ignore
|
||||
['/sqlite-memory/:count']
|
||||
pub fn (mut app App) sqlite_memory(count int) vweb.Result {
|
||||
mut insert_stopwatchs := []int{}
|
||||
mut select_stopwatchs := []int{}
|
||||
mut update_stopwatchs := []int{}
|
||||
|
||||
mut sw := time.new_stopwatch()
|
||||
|
||||
mut db := sqlite.connect(':memory:') or { panic(err) }
|
||||
|
||||
sql db {
|
||||
create table Task
|
||||
}
|
||||
|
||||
task_model := Task{
|
||||
title: 'a'
|
||||
status: 'done'
|
||||
}
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
sw.start()
|
||||
sql db {
|
||||
insert task_model into Task
|
||||
}
|
||||
sw.stop()
|
||||
insert_stopwatchs << int(sw.end - sw.start)
|
||||
}
|
||||
|
||||
sql db {
|
||||
drop table Task
|
||||
}
|
||||
|
||||
response := Response{
|
||||
insert: insert_stopwatchs
|
||||
@select:select_stopwatchs
|
||||
update: update_stopwatchs
|
||||
}
|
||||
return app.json(response)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
In `examples/chart/services.v` path
|
||||
Create a service to request the benchmarks data by http
|
||||
Decode the info to `FrameworkBenchmarkResponse`
|
||||
```v ignore
|
||||
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
||||
url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
|
||||
res := http.get(url) or { panic(err) }
|
||||
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
|
||||
return framework_benchmark_response
|
||||
}
|
||||
```
|
||||
|
||||
In `examples/chart/main.v` path
|
||||
Create a service to request the benchmarks data by http
|
||||
Decode the info to `FrameworkBenchmarkResponse`
|
||||
```v ignore
|
||||
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
||||
url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
|
||||
res := http.get(url) or { panic(err) }
|
||||
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
|
||||
return framework_benchmark_response
|
||||
}
|
||||
```
|
||||
Then, update:
|
||||
`insert_framework_benchmark_times()`;
|
||||
`select_framework_benchmark_times()`;
|
||||
`update_framework_benchmark_times()`.
|
||||
with the new function
|
||||
|
||||
|
||||
|
||||
# ROADMAP
|
||||
02/09/2022
|
||||
- [ ] select bench (easy)
|
||||
- [ ] vsql (easy)
|
129
examples/js_dom_draw_bechmark_chart/chart/draw.js.v
Normal file
129
examples/js_dom_draw_bechmark_chart/chart/draw.js.v
Normal file
@ -0,0 +1,129 @@
|
||||
module main
|
||||
|
||||
import js.dom
|
||||
|
||||
fn get_canvas(elem JS.HTMLElement) JS.HTMLCanvasElement {
|
||||
// error: `JS.HTMLElement` doesn't implement method `getContext` of interface `JS.HTMLCanvasElement`
|
||||
match elem {
|
||||
JS.HTMLCanvasElement {
|
||||
return elem
|
||||
}
|
||||
else {
|
||||
JS.console.log('Not canvas')
|
||||
return JS.HTMLCanvasElement{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
struct FrameworkPlatform {
|
||||
mut:
|
||||
v_sqlite_memory []int
|
||||
// v_sqlite_file []int
|
||||
typescript_sqlite_memory []int
|
||||
}
|
||||
|
||||
fn (mut state DrawState) draw_bench_chart(color string, time_array []int, max_time int) ? {
|
||||
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
|
||||
|
||||
mut canvas_elem := map[string]JS.HTMLElement{}
|
||||
mut canvas := map[string]JS.HTMLCanvasElement{}
|
||||
|
||||
canvas_elem['insert'] = document.getElementById('canvas_insert_id'.str)?
|
||||
JS.console.log('canvas_insert_id')
|
||||
|
||||
canvas_elem['select'] = document.getElementById('canvas_select_id'.str)?
|
||||
JS.console.log('canvas_select_id')
|
||||
|
||||
canvas_elem['update'] = document.getElementById('canvas_update_id'.str)?
|
||||
JS.console.log('canvas_update_id')
|
||||
|
||||
// for orm_stmt_kind in ["insert", "select", "update"]{
|
||||
for orm_stmt_kind in ['insert', 'select', 'update'] {
|
||||
// type HTMLElement
|
||||
|
||||
canvas[orm_stmt_kind] = get_canvas(canvas_elem[orm_stmt_kind])
|
||||
|
||||
ctx := canvas[orm_stmt_kind].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}
|
||||
|
||||
mut inserts_from_framework := canvas_elem[orm_stmt_kind].getAttribute('inserts_from_framework'.str)?
|
||||
|
||||
mut max_benchmark := canvas_elem[orm_stmt_kind].getAttribute('max_benchmark'.str)?
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
mut obj := FrameworkPlatform{}
|
||||
obj = JS.JSON.parse(tos(inserts_from_framework))
|
||||
|
||||
// Waiting for v implement for loop getting key and value of object in v.js
|
||||
mut attribute_int_values := []int{}
|
||||
|
||||
//* v framework
|
||||
for variable in obj.v_sqlite_memory {
|
||||
attribute_int_values << variable
|
||||
}
|
||||
|
||||
state.draw_bench_chart('gray', attribute_int_values, tos(max_benchmark).int())?
|
||||
attribute_int_values = []
|
||||
|
||||
//* typescript framework
|
||||
|
||||
for variable in obj.typescript_sqlite_memory {
|
||||
attribute_int_values << variable
|
||||
}
|
||||
|
||||
state.draw_bench_chart('red', attribute_int_values, tos(max_benchmark).int())?
|
||||
|
||||
attribute_int_values = []
|
||||
}
|
||||
}
|
BIN
examples/js_dom_draw_bechmark_chart/chart/favicon.ico
Normal file
BIN
examples/js_dom_draw_bechmark_chart/chart/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 303 KiB |
249
examples/js_dom_draw_bechmark_chart/chart/main.v
Normal file
249
examples/js_dom_draw_bechmark_chart/chart/main.v
Normal file
@ -0,0 +1,249 @@
|
||||
module main
|
||||
|
||||
import vweb
|
||||
import os
|
||||
import json
|
||||
import arrays
|
||||
import net.http
|
||||
import math
|
||||
import v.util.version
|
||||
|
||||
[table: 'benchmark']
|
||||
struct Task {
|
||||
mut:
|
||||
id u32 [primary; serial; sql: serial]
|
||||
title string
|
||||
status string
|
||||
}
|
||||
|
||||
struct FrameworkBenchmarkResponse {
|
||||
insert []int
|
||||
@select []int
|
||||
update []int
|
||||
}
|
||||
|
||||
struct FrameworkPlatform {
|
||||
mut:
|
||||
v_sqlite_memory []int
|
||||
// v_sqlite_file []int
|
||||
typescript_sqlite_memory []int
|
||||
}
|
||||
|
||||
fn (framework_platform FrameworkPlatform) to_map() map[string][]int {
|
||||
mut mapa := map[string][]int{}
|
||||
|
||||
mapa['v_sqlite_memory'] = framework_platform.v_sqlite_memory
|
||||
// mapa['v_sqlite_file'] = framework_platform.v_sqlite_file
|
||||
mapa['typescript_sqlite_memory'] = framework_platform.typescript_sqlite_memory
|
||||
return mapa
|
||||
}
|
||||
|
||||
const (
|
||||
http_port = 3001
|
||||
benchmark_loop_length = 20
|
||||
)
|
||||
|
||||
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 {
|
||||
v_version := version.full_v_version(true)
|
||||
orm_stmt_kinds := ['insert', 'select', 'update']
|
||||
|
||||
mut attribute_names := map[string][]string{}
|
||||
// Used to garante the chart proposionalite
|
||||
mut max_benchmark := map[string]int{}
|
||||
mut from_framework := map[string]string{}
|
||||
mut maxs := map[string][]int{}
|
||||
mut framework_platform := map[string]map[string][]int{}
|
||||
mut table := map[string]map[string]map[string]string{}
|
||||
|
||||
chart_colors := ['gray', 'red', 'orange', 'purple', 'red', 'orange', 'purple']
|
||||
for orm_stmt_kind in orm_stmt_kinds {
|
||||
match orm_stmt_kind {
|
||||
'insert' {
|
||||
framework_platform[orm_stmt_kind] = insert_framework_benchmark_times().to_map()
|
||||
}
|
||||
'select' {
|
||||
framework_platform[orm_stmt_kind] = select_framework_benchmark_times().to_map()
|
||||
}
|
||||
'update' {
|
||||
framework_platform[orm_stmt_kind] = update_framework_benchmark_times().to_map()
|
||||
}
|
||||
else {}
|
||||
}
|
||||
|
||||
for key, values in framework_platform[orm_stmt_kind] {
|
||||
attribute_names[orm_stmt_kind] << key
|
||||
maxs[orm_stmt_kind] << arrays.max(values)?
|
||||
}
|
||||
|
||||
max_benchmark[orm_stmt_kind] = arrays.max(maxs[orm_stmt_kind])?
|
||||
from_framework[orm_stmt_kind] = json.encode(framework_platform[orm_stmt_kind])
|
||||
table[orm_stmt_kind] = gen_table_info(attribute_names[orm_stmt_kind], framework_platform[orm_stmt_kind])
|
||||
}
|
||||
|
||||
return $vweb.html()
|
||||
}
|
||||
|
||||
fn insert_framework_benchmark_times() FrameworkPlatform {
|
||||
numbers := FrameworkPlatform{
|
||||
v_sqlite_memory: v_sqlite_memory()!.insert
|
||||
// v_sqlite_file: v_sqlite_file()!.insert
|
||||
typescript_sqlite_memory: typescript_sqlite_memory()!.insert
|
||||
}
|
||||
|
||||
return numbers
|
||||
}
|
||||
|
||||
fn select_framework_benchmark_times() FrameworkPlatform {
|
||||
numbers := FrameworkPlatform{
|
||||
v_sqlite_memory: v_sqlite_memory()!.@select
|
||||
// v_sqlite_file: v_sqlite_file()!.@select
|
||||
typescript_sqlite_memory: typescript_sqlite_memory()!.@select
|
||||
}
|
||||
|
||||
return numbers
|
||||
}
|
||||
|
||||
fn update_framework_benchmark_times() FrameworkPlatform {
|
||||
numbers := FrameworkPlatform{
|
||||
v_sqlite_memory: v_sqlite_memory()!.update
|
||||
// v_sqlite_file: v_sqlite_file()!.@select
|
||||
typescript_sqlite_memory: typescript_sqlite_memory()!.update
|
||||
}
|
||||
|
||||
return numbers
|
||||
}
|
||||
|
||||
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
||||
url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
|
||||
res := http.get(url) or { panic(err) }
|
||||
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
|
||||
return framework_benchmark_response
|
||||
}
|
||||
|
||||
fn v_sqlite_memory() ?FrameworkBenchmarkResponse {
|
||||
url := 'http://localhost:4000/sqlite-memory/$benchmark_loop_length'
|
||||
res := http.get(url) or { panic(err) }
|
||||
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
|
||||
return framework_benchmark_response
|
||||
}
|
||||
|
||||
fn v_sqlite_file() ?FrameworkBenchmarkResponse {
|
||||
// url := 'http://localhost:3000/sqlite-memory/$benchmark_loop_length'
|
||||
// res := http.get(url) or { panic(err) }
|
||||
// framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)?
|
||||
framework_benchmark_response := FrameworkBenchmarkResponse{
|
||||
insert: []
|
||||
@select: []
|
||||
update: []
|
||||
}
|
||||
return framework_benchmark_response
|
||||
}
|
||||
|
||||
fn gen_table_info(attribute_names []string, framework_platform map[string][]int) map[string]map[string]string {
|
||||
mut table := map[string]map[string]string{}
|
||||
|
||||
// nanoseconds
|
||||
mut max_times := map[string]int{}
|
||||
mut ten_perc_max_times := map[string]int{}
|
||||
mut min_times := map[string]int{}
|
||||
mut ten_perc_min_times := map[string]int{}
|
||||
|
||||
// bigger to calculate percent
|
||||
mut max := 0.0
|
||||
mut ten_perc_max := 0.0
|
||||
mut min := 0.0
|
||||
mut ten_perc_min := 0.0
|
||||
|
||||
// percentes
|
||||
mut max_fast := map[string]int{}
|
||||
mut ten_perc_max_fast := map[string]int{}
|
||||
mut min_fast := map[string]int{}
|
||||
mut ten_perc_min_fast := map[string]int{}
|
||||
|
||||
// nanoseconds
|
||||
for idx, name in attribute_names {
|
||||
// qtd. of values in 10 % of arrays
|
||||
ten_perc := int(framework_platform[name].len / 10)
|
||||
|
||||
// get 10% highter
|
||||
mut min_ten_array := framework_platform[name].clone()
|
||||
min_ten_array.sort()
|
||||
min_ten_array.trim(ten_perc)
|
||||
|
||||
// get 10% lower
|
||||
mut max_ten_array := framework_platform[name].clone()
|
||||
max_ten_array.sort(a > b)
|
||||
max_ten_array.trim(ten_perc)
|
||||
|
||||
// popule array with nanoseconds to which benchmark
|
||||
max_times[name] = arrays.max(framework_platform[name]) or { 0 } // int
|
||||
ten_perc_max_times[name] = arrays.sum(max_ten_array) or { 0 } / ten_perc // int
|
||||
min_times[name] = arrays.min(framework_platform[name]) or { 0 } // int
|
||||
ten_perc_min_times[name] = arrays.sum(min_ten_array) or { 0 } / ten_perc // int
|
||||
|
||||
// set bigger values
|
||||
if idx < 1 {
|
||||
max = f64(max_times[name])
|
||||
ten_perc_max = f64(ten_perc_max_times[name])
|
||||
min = f64(min_times[name])
|
||||
ten_perc_min = f64(ten_perc_min_times[name])
|
||||
} else {
|
||||
if max < f64(max_times[name]) {
|
||||
max = f64(max_times[name])
|
||||
}
|
||||
if ten_perc_max < f64(ten_perc_max_times[name]) {
|
||||
ten_perc_max = f64(ten_perc_max_times[name])
|
||||
}
|
||||
if min < f64(min_times[name]) {
|
||||
min = f64(min_times[name])
|
||||
}
|
||||
if ten_perc_min < f64(ten_perc_min_times[name]) {
|
||||
ten_perc_min = f64(ten_perc_min_times[name])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// percents
|
||||
for name in attribute_names {
|
||||
max_fast[name] = int(max / f64(max_times[name]))
|
||||
ten_perc_max_fast[name] = int(ten_perc_max / f64(ten_perc_max_times[name]))
|
||||
min_fast[name] = int(min / f64(min_times[name]))
|
||||
ten_perc_min_fast[name] = int(ten_perc_min / f64(ten_perc_min_times[name]))
|
||||
}
|
||||
|
||||
for name in attribute_names {
|
||||
table[name]['max.'] = '${math.round_sig(f64(max_times[name]) / 1000000, 2)} ms (${max_fast[name]}x faster)'
|
||||
table[name]['10% max.'] = '${math.round_sig(f64(ten_perc_max_times[name]) / 1000000,
|
||||
2)} ms (${ten_perc_max_fast[name]}x faster)'
|
||||
table[name]['min.'] = '${math.round_sig(f64(min_times[name]) / 1000000, 2)} ms (${min_fast[name]}x faster)'
|
||||
table[name]['10% min.'] = '${math.round_sig(f64(ten_perc_min_times[name]) / 1000000,
|
||||
2)} ms (${ten_perc_min_fast[name]}x faster)'
|
||||
}
|
||||
return table
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
<body class="main">
|
||||
<style>
|
||||
table,
|
||||
th,
|
||||
td {
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
|
||||
<title>Is V orm still fast? ${v_version}</title>
|
||||
<div style="display: flex; align-items: center">
|
||||
<h2
|
||||
style="
|
||||
font-family: Menlo, Monospace, 'Courier New';
|
||||
margin-left: 30px;
|
||||
margin-top: 30px;
|
||||
"
|
||||
>
|
||||
Is V orm still fast?
|
||||
</h2>
|
||||
|
||||
<img src="./../../../../favicon.ico" height="35px" />
|
||||
<h5 style="font-family: Menlo, Monospace, 'Courier New'; color: #3b7bbf">
|
||||
${v_version}
|
||||
</h5>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row; flex-wrap: wrap">
|
||||
@for orm_stmt_kind in orm_stmt_kinds
|
||||
<!-- <div style="display: flex; flex-direction: column; "> -->
|
||||
<div
|
||||
style="
|
||||
border-radius: 15px;
|
||||
padding: 15px;
|
||||
margin: 15px;
|
||||
box-shadow: 0px 2px 10px 1px grey;
|
||||
"
|
||||
>
|
||||
<div style="display: flex; flex-direction: column; max-width: 850px">
|
||||
<h2 style="font-family: Arial, Helvetica, sans-serif">
|
||||
${orm_stmt_kind} benchmark
|
||||
</h2>
|
||||
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
"
|
||||
>
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
height: 480;
|
||||
margin-right: 20px;
|
||||
background-image: linear-gradient(red, yellow, green, #3b7bbf);
|
||||
"
|
||||
>
|
||||
@for number in 0..11
|
||||
<div style="font-family: Arial, Helvetica, sans-serif">
|
||||
${int(number*(f64(max_benchmark[orm_stmt_kind])/10))} ns
|
||||
</div>
|
||||
@end
|
||||
</div>
|
||||
|
||||
<canvas
|
||||
id="canvas_${orm_stmt_kind}_id"
|
||||
inserts_from_framework="@{from_framework[orm_stmt_kind]}"
|
||||
max_benchmark="@{max_benchmark[orm_stmt_kind]}"
|
||||
style="border: 1px solid grey"
|
||||
width="720"
|
||||
height="480"
|
||||
></canvas>
|
||||
</div>
|
||||
<table style="margin-top: 10px">
|
||||
<tr>
|
||||
<th>Benchmark name</th>
|
||||
<th>max.</th>
|
||||
<th>10% max.</th>
|
||||
<th>min.</th>
|
||||
<th>10% min.</th>
|
||||
</tr>
|
||||
@for idx, name in attribute_names[orm_stmt_kind]
|
||||
<tr style="font-family:arial; color: ${chart_colors[idx]};">
|
||||
<td style="padding-right: 5px" id="benchmark_name" +idx>@name</td>
|
||||
<td style="padding-left: 5px; padding-right: 5px">
|
||||
@{table[orm_stmt_kind][name]["max."]}
|
||||
</td>
|
||||
<td style="padding-left: 5px; padding-right: 5px">
|
||||
@{table[orm_stmt_kind][name]["10% max."]}
|
||||
</td>
|
||||
<td style="padding-left: 5px; padding-right: 5px">
|
||||
@{table[orm_stmt_kind][name]["min."]}
|
||||
</td>
|
||||
<td style="padding-left: 5px; padding-right: 5px">
|
||||
@{table[orm_stmt_kind][name]["10% min."]}
|
||||
</td>
|
||||
</tr>
|
||||
@end
|
||||
</table>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
@end
|
||||
</div>
|
||||
<script type="text/javascript" src="draw.js"></script>
|
||||
</body>
|
@ -1,111 +0,0 @@
|
||||
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{})
|
||||
}
|
@ -1,217 +0,0 @@
|
||||
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
|
||||
// }
|
@ -1,38 +0,0 @@
|
||||
|
||||
<body class="main">
|
||||
<style>
|
||||
table, th, td {
|
||||
border:1px solid black;
|
||||
}
|
||||
</style>
|
||||
|
||||
<title>V orm still fast?</title>
|
||||
<input type="button" id="clearButton" value="Clear canvas">
|
||||
<div style="float: left; width: 100%;">
|
||||
<canvas style="border: 1px solid black;" width="100" height="480" id="canvas_left_bar_id"></canvas>
|
||||
<canvas sqlite_memory_insert_times=@sqlite_memory_insert_times sqlite_file_insert_times=@sqlite_file_insert_times style="border: 1px solid black;" width="720" height="480" id="canvas_insert_id"></canvas>
|
||||
</div>
|
||||
<script type="text/javascript" src="draw.js"></script>
|
||||
|
||||
<h2>Insert test</h2>
|
||||
|
||||
<table style="width:1080px">
|
||||
<tr>
|
||||
<th>Benchmark name</th>
|
||||
<th>max.</th>
|
||||
<th>10% max.</th>
|
||||
<th>min.</th>
|
||||
<th>10% min.</th>
|
||||
</tr>
|
||||
@for idx, name in attribute_names
|
||||
<tr style="font-family:arial; color: ${chart_colors[idx]};" >
|
||||
<td id="benchmark_name"+idx >@name</td>
|
||||
<td>@{max_times[idx]} ns (@{max_fast[idx]}%faster)</td>
|
||||
<td>@{ten_perc_max_times[idx]} ns (@{ten_perc_max_fast[idx]}%faster)</td>
|
||||
<td>@{min_times[idx]} ns (@{min_fast[idx]}%faster)</td>
|
||||
<td>@{ten_perc_min_times[idx]} ns (@{ten_perc_min_fast[idx]}%faster)</td>
|
||||
</tr>
|
||||
@end
|
||||
</table>
|
||||
<p>V orm still fast?</p>
|
||||
</body>
|
25
examples/js_dom_draw_bechmark_chart/typescript_vanilla_typeorm/.gitignore
vendored
Normal file
25
examples/js_dom_draw_bechmark_chart/typescript_vanilla_typeorm/.gitignore
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
*/node_modules/**/*
|
||||
/node_modules/**/*
|
||||
node_modules/**/*
|
||||
/node_modules/
|
||||
node_modules/
|
||||
node_modules
|
||||
|
||||
# Ignore built ts files
|
||||
*/dist/**/*
|
||||
/dist/**/*
|
||||
dist/**/*
|
||||
/dist/
|
||||
dist/
|
||||
dist
|
||||
|
||||
temp/*
|
||||
temp/
|
||||
*/temp/**/*
|
||||
|
||||
package-lock.json
|
||||
|
||||
# Not ignore built js or ts files
|
||||
!*.js
|
||||
!*.ts
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "js_dom_draw_chart_ts",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"start": "npm run build && node src/server.js",
|
||||
"start:dev": "./node_modules/nodemon/bin/nodemon.js -e ts --exec \"npm run start\"",
|
||||
"build": "tsc"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"nodemon": "^2.0.19",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"sqlite3": "^5.0.11",
|
||||
"typeorm": "^0.3.7",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.6.4"
|
||||
}
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
import { performance } from "perf_hooks";
|
||||
import { Entity, Column, PrimaryGeneratedColumn, DataSource } from "typeorm";
|
||||
|
||||
type Response = {
|
||||
insert: number[];
|
||||
select: number[];
|
||||
update: number[];
|
||||
};
|
||||
|
||||
@Entity("benchmark")
|
||||
export class Task {
|
||||
@PrimaryGeneratedColumn()
|
||||
id?: number;
|
||||
|
||||
@Column("text")
|
||||
title!: string;
|
||||
|
||||
@Column("text")
|
||||
status!: string;
|
||||
}
|
||||
|
||||
export const appDataSource = new DataSource({
|
||||
type: "sqlite",
|
||||
database: ":memory:",
|
||||
dropSchema: true,
|
||||
entities: [Task],
|
||||
synchronize: true, // create a new table
|
||||
logging: false,
|
||||
});
|
||||
|
||||
export async function sqlite_memory(count: Number): Promise<Response> {
|
||||
var insert_stopwatchs: number[] = [];
|
||||
let select_stopwatchs: number[] = [];
|
||||
let update_stopwatchs: number[] = [];
|
||||
|
||||
let sw = performance;
|
||||
|
||||
const taskRepository = appDataSource.getRepository(Task);
|
||||
|
||||
// inserts
|
||||
for (let index = 0; index < count; index++) {
|
||||
const task_model = new Task();
|
||||
task_model.title = "a";
|
||||
task_model.status = "done";
|
||||
|
||||
const start = sw.now();
|
||||
await taskRepository.save(task_model).then((value) => {
|
||||
const insert_stopwatch = (sw.now() - start) * 1000000;
|
||||
insert_stopwatchs.push(Math.floor(insert_stopwatch)); //nanoseconds
|
||||
});
|
||||
}
|
||||
|
||||
// selects
|
||||
for (let index = 0; index < count; index++) {
|
||||
const start = sw.now();
|
||||
await taskRepository.find().then((value) => {
|
||||
const select_stopwatch = (sw.now() - start) * 1000000;
|
||||
select_stopwatchs.push(Math.floor(select_stopwatch)); //nanoseconds
|
||||
});
|
||||
}
|
||||
|
||||
// updates
|
||||
for (let index = 0; index < count; index++) {
|
||||
const taskToUpdate = await taskRepository.findOneBy({ id: 1 });
|
||||
|
||||
taskToUpdate!.title = "b";
|
||||
taskToUpdate!.status = "finish";
|
||||
|
||||
const start = sw.now();
|
||||
await taskRepository.save(taskToUpdate!).then((value) => {
|
||||
const update_stopwatch = (sw.now() - start) * 1000000;
|
||||
update_stopwatchs.push(Math.floor(update_stopwatch)); //nanoseconds
|
||||
});
|
||||
}
|
||||
|
||||
// taskRepository.find().then((value) => {
|
||||
// console.log(`value: %j`, value);
|
||||
// });
|
||||
|
||||
let response: Response = {
|
||||
insert: insert_stopwatchs,
|
||||
select: select_stopwatchs,
|
||||
update: update_stopwatchs,
|
||||
};
|
||||
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
|
||||
// export function sqlite_file(count: Number): Response {
|
||||
// var insert_stopwatchs: number[] = [];
|
||||
// let select_stopwatchs: number[] = [];
|
||||
// let update_stopwatchs: number[] = [];
|
||||
|
||||
// for (let index = 0; index < count; index++) {
|
||||
// insert_stopwatchs.push(index);
|
||||
// }
|
||||
|
||||
// let response: Response = {
|
||||
// insert: insert_stopwatchs,
|
||||
// select: select_stopwatchs,
|
||||
// update: update_stopwatchs,
|
||||
// };
|
||||
|
||||
// return response;
|
||||
// }
|
||||
|
||||
// export function postgres(count: Number): Response {
|
||||
// var insert_stopwatchs: number[] = [];
|
||||
// let select_stopwatchs: number[] = [];
|
||||
// let update_stopwatchs: number[] = [];
|
||||
|
||||
// for (let index = 0; index < count; index++) {
|
||||
// insert_stopwatchs.push(index);
|
||||
// }
|
||||
|
||||
// let response: Response = {
|
||||
// insert: insert_stopwatchs,
|
||||
// select: select_stopwatchs,
|
||||
// update: update_stopwatchs,
|
||||
// };
|
||||
|
||||
// return response;
|
||||
// }
|
||||
|
||||
// export function mysql(count: Number): Response {
|
||||
// var insert_stopwatchs: number[] = [];
|
||||
// let select_stopwatchs: number[] = [];
|
||||
// let update_stopwatchs: number[] = [];
|
||||
|
||||
// for (let index = 0; index < count; index++) {
|
||||
// insert_stopwatchs.push(index);
|
||||
// }
|
||||
|
||||
// let response: Response = {
|
||||
// insert: insert_stopwatchs,
|
||||
// select: select_stopwatchs,
|
||||
// update: update_stopwatchs,
|
||||
// };
|
||||
|
||||
// return response;
|
||||
// }
|
@ -0,0 +1,90 @@
|
||||
const http = require("http");
|
||||
const fs = require("fs");
|
||||
var path = require("path");
|
||||
const { hello, sqlite_memory, appDataSource } = require("..");
|
||||
|
||||
const host = "localhost";
|
||||
const port = 3000;
|
||||
|
||||
// const hello = require("../index")
|
||||
|
||||
const reqListener = async (req, res) => {
|
||||
console.log(`[route] - (${req.method}) ${req.url}`);
|
||||
|
||||
var filePath = "." + req.url;
|
||||
// if (filePath == './') {
|
||||
// filePath = './index.html';
|
||||
// }
|
||||
|
||||
var extname = String(path.extname(filePath)).toLowerCase();
|
||||
var mimeTypes = {
|
||||
".html": "text/html",
|
||||
".js": "text/javascript",
|
||||
".css": "text/css",
|
||||
".json": "application/json",
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpg",
|
||||
".gif": "image/gif",
|
||||
".svg": "image/svg+xml",
|
||||
".wav": "audio/wav",
|
||||
".mp4": "video/mp4",
|
||||
".woff": "application/font-woff",
|
||||
".ttf": "application/font-ttf",
|
||||
".eot": "application/vnd.ms-fontobject",
|
||||
".otf": "application/font-otf",
|
||||
".wasm": "application/wasm",
|
||||
};
|
||||
|
||||
var contentType = mimeTypes[extname] || "application/octet-stream";
|
||||
|
||||
fs.readFile(filePath, function (error, content) {
|
||||
if (error) {
|
||||
if (error.code == "ENOENT") {
|
||||
fs.readFile("./404.html", function (error, content) {
|
||||
// res.writeHead(404, { "Content-Type": "text/html" });
|
||||
// res.end(content, "utf-8");
|
||||
});
|
||||
} else {
|
||||
res.writeHead(500);
|
||||
res.end(
|
||||
"Sorry, check with the site admin for error: " + error.code + " ..\n"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
res.writeHead(200, { "Content-Type": contentType });
|
||||
res.end(content, "utf-8");
|
||||
}
|
||||
});
|
||||
|
||||
// Routes
|
||||
if (req.url == "/" && req.method == "GET") {
|
||||
res.writeHead(200);
|
||||
res.end("adad");
|
||||
}
|
||||
|
||||
if (req.url == "/hello-world" && req.method == "GET") {
|
||||
res.writeHead(200);
|
||||
res.end("hello world");
|
||||
}
|
||||
|
||||
if (req.url.includes("/sqlite-memory/") && req.method == "GET") {
|
||||
var count = req.url.replace("/sqlite-memory/", "");
|
||||
|
||||
await sqlite_memory(count).then((response) => {
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify(response));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const server = http.createServer(reqListener);
|
||||
|
||||
appDataSource.initialize();
|
||||
console.log("Database working");
|
||||
|
||||
server.listen(port, host);
|
||||
console.log(`Server is running on http://${host}:${port}`);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
"lib": ["es2022"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
|
||||
/* Modules */
|
||||
//Specify what module code is generated.
|
||||
"module": "commonjs",
|
||||
|
||||
/* Emit */
|
||||
// Specify an output folder for all emitted files.
|
||||
"outDir": "./dist",
|
||||
// Disable emitting comments.
|
||||
"removeComments": true,
|
||||
|
||||
|
||||
/* Interop Constraints */
|
||||
// Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility.
|
||||
"esModuleInterop": true,
|
||||
// Ensure that casing is correct in imports.
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
|
||||
/* Type Checking */
|
||||
// Enable all strict type-checking options.
|
||||
"strict": true,
|
||||
|
||||
|
||||
// Completeness
|
||||
// Skip type checking all .d.ts files.
|
||||
"skipLibCheck": true },
|
||||
"include": ["src/**/*"]
|
||||
|
||||
}
|
131
examples/js_dom_draw_bechmark_chart/v_vweb_orm/src/main.v
Normal file
131
examples/js_dom_draw_bechmark_chart/v_vweb_orm/src/main.v
Normal file
@ -0,0 +1,131 @@
|
||||
module main
|
||||
|
||||
import vweb
|
||||
import time
|
||||
import sqlite
|
||||
|
||||
struct App {
|
||||
vweb.Context
|
||||
}
|
||||
|
||||
[table: 'benchmark']
|
||||
struct Task {
|
||||
mut:
|
||||
id u32 [primary; serial; sql: serial]
|
||||
title string
|
||||
status string
|
||||
}
|
||||
|
||||
struct Response {
|
||||
insert []int
|
||||
@select []int
|
||||
update []int
|
||||
}
|
||||
|
||||
fn main() {
|
||||
vweb.run_at(new_app(), vweb.RunParams{
|
||||
port: 4000
|
||||
}) or { panic(err) }
|
||||
}
|
||||
|
||||
fn new_app() &App {
|
||||
mut app := &App{}
|
||||
return app
|
||||
}
|
||||
|
||||
['/hello-world']
|
||||
pub fn (mut app App) hello_world() vweb.Result {
|
||||
return app.text('hello world')
|
||||
}
|
||||
|
||||
['/sqlite-memory/:count']
|
||||
pub fn (mut app App) sqlite_memory(count int) vweb.Result {
|
||||
mut insert_stopwatchs := []int{}
|
||||
mut select_stopwatchs := []int{}
|
||||
mut update_stopwatchs := []int{}
|
||||
|
||||
mut sw := time.new_stopwatch()
|
||||
|
||||
mut db := sqlite.connect(':memory:') or { panic(err) }
|
||||
|
||||
sql db {
|
||||
create table Task
|
||||
}
|
||||
|
||||
task_model := Task{
|
||||
title: 'a'
|
||||
status: 'done'
|
||||
}
|
||||
|
||||
// inserts
|
||||
for i := 0; i < count; i++ {
|
||||
sw.start()
|
||||
sql db {
|
||||
insert task_model into Task
|
||||
}
|
||||
sw.stop()
|
||||
insert_stopwatchs << int(sw.end - sw.start)
|
||||
}
|
||||
|
||||
// selects
|
||||
for i := 0; i < count; i++ {
|
||||
sw.start()
|
||||
result := sql db {
|
||||
select from Task
|
||||
}
|
||||
sw.stop()
|
||||
eprintln(result)
|
||||
select_stopwatchs << int(sw.end - sw.start)
|
||||
}
|
||||
|
||||
// updates
|
||||
for i := 0; i < count; i++ {
|
||||
sw.start()
|
||||
sql db {
|
||||
update Task set title = 'b', status = 'finish' where id == i
|
||||
}
|
||||
sw.stop()
|
||||
update_stopwatchs << int(sw.end - sw.start)
|
||||
}
|
||||
|
||||
sql db {
|
||||
drop table Task
|
||||
}
|
||||
|
||||
response := Response{
|
||||
insert: insert_stopwatchs
|
||||
@select: select_stopwatchs
|
||||
update: update_stopwatchs
|
||||
}
|
||||
return app.json(response)
|
||||
}
|
||||
|
||||
['/sqlite-file/:count']
|
||||
pub fn (mut app App) sqlite_file(count int) vweb.Result {
|
||||
response := Response{
|
||||
insert: []
|
||||
@select: []
|
||||
update: []
|
||||
}
|
||||
return app.json(response)
|
||||
}
|
||||
|
||||
['/postgres/:count']
|
||||
pub fn (mut app App) postgres(count int) vweb.Result {
|
||||
response := Response{
|
||||
insert: []
|
||||
@select: []
|
||||
update: []
|
||||
}
|
||||
return app.json(response)
|
||||
}
|
||||
|
||||
['/mysql/:count']
|
||||
pub fn (mut app App) mysql(count int) vweb.Result {
|
||||
response := Response{
|
||||
insert: []
|
||||
@select: []
|
||||
update: []
|
||||
}
|
||||
return app.json(response)
|
||||
}
|
Loading…
Reference in New Issue
Block a user