diff --git a/frameworks/V/veb/README.md b/frameworks/V/veb/README.md new file mode 100755 index 00000000000..467345c1431 --- /dev/null +++ b/frameworks/V/veb/README.md @@ -0,0 +1,35 @@ +# [veb](https://modules.vlang.io/veb.html) Benchmarking Test + +Veb is the default V language web framework. This test uses veb and V native ORM. + +### Test Type Implementation Source Code + +All tests in a 95 lines [main.v] and a html [template](fortunes.html) +### Database + +PostgresQL + +## Test URLs +### JSON + +http://localhost:8080/json + +### PLAINTEXT + +http://localhost:8080/plaintext + +### DB + +http://localhost:8080/db + +### QUERY + +http://localhost:8080/query?q= + +### UPDATE + +http://localhost:8080/update?queries= + +### FORTUNES + +http://localhost:8080/fortunes diff --git a/frameworks/V/veb/benchmark_config.json b/frameworks/V/veb/benchmark_config.json new file mode 100755 index 00000000000..e5ca19da42c --- /dev/null +++ b/frameworks/V/veb/benchmark_config.json @@ -0,0 +1,30 @@ +{ + "framework": "veb", + "tests": [ + { + "default": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "db_url": "/db", + "query_url": "/queries?q=", + "fortune_url": "/fortunes", + "update_url": "/update?q=", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "Postgres", + "framework": "veb", + "language": "V", + "flavor": "None", + "orm": "Micro", + "platform": "None", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "veb", + "notes": "", + "versus": "None" + } + } + ] +} diff --git a/frameworks/V/veb/config.toml b/frameworks/V/veb/config.toml new file mode 100644 index 00000000000..ea461db93e4 --- /dev/null +++ b/frameworks/V/veb/config.toml @@ -0,0 +1,19 @@ +[framework] +name = "veb" + +[main] +urls.plaintext = "/plaintext" +urls.json = "/json" +urls.db = "/db" +urls.query = "/queries?q=" +urls.update = "/update?q=" +urls.fortune = "/fortunes" +approach = "Realistic" +classification = "Fullstack" +database = "Postgres" +database_os = "Linux" +os = "Linux" +orm = "Micro" +platform = "None" +webserver = "None" +versus = "None" diff --git a/frameworks/V/veb/fortunes.html b/frameworks/V/veb/fortunes.html new file mode 100644 index 00000000000..51e1d42989a --- /dev/null +++ b/frameworks/V/veb/fortunes.html @@ -0,0 +1,12 @@ + + +Fortunes + + + +@for m in fortunes + +@end +
idmessage
@m.id@m.message
+ + \ No newline at end of file diff --git a/frameworks/V/veb/main.v b/frameworks/V/veb/main.v new file mode 100644 index 00000000000..1fa0b3e5d0f --- /dev/null +++ b/frameworks/V/veb/main.v @@ -0,0 +1,103 @@ +import veb +import time +import rand +import db.pg + +pub fn (app &App) plaintext(mut ctx Context) veb.Result { + s := 'Hello, World!' + return ctx.text(s) +} + +pub fn (app &App) json(mut ctx Context) veb.Result { + obj := {'message': 'Hello, World!'} + return ctx.json(obj) +} + +struct World { + id int @[primary; sql: serial] +mut: + randomnumber int +} + +pub fn (app &App) db(mut ctx Context) veb.Result { + r := rand.int_in_range(1, 10000) or { return ctx.text('rand error') } + mut world := sql app.db { + select from World where id == r + } or { return ctx.text('db error') } + return ctx.json(world.first()) +} + +pub fn (app &App) queries(mut ctx Context) veb.Result { + mut q := ctx.query['q'].int() + if q < 1 { q = 1 } else if q > 500 { q = 500 } + mut world := []World{} + for _ in 0..q { + r := rand.int_in_range(1, 10000) or { return ctx.text('rand error') } + world << sql app.db { + select from World where id == r + } or { return ctx.text('db error') } + } + return ctx.json(world) +} + +pub fn (app &App) update(mut ctx Context) veb.Result { + mut q := ctx.query['q'].int() + if q < 1 { q = 1 } else if q > 500 { q = 500 } + mut world := []World{} + for _ in 0..q { + r := rand.int_in_range(1, 10000) or { return ctx.text('rand error') } + world << sql app.db { + select from World where id == r + } or { return ctx.text('db error') } + world.last().randomnumber = rand.int_in_range(1, 10000) or { return ctx.text('rand error') } + sql app.db { + update World set randomnumber = world.last().randomnumber where id == world.last().id + } or { return ctx.text('db error') } + } + return ctx.json(world) +} + +struct Fortune { + id int @[primary; sql: serial] + message string +} + +pub fn (app &App) fortunes(mut ctx Context) veb.Result { + mut fortunes := sql app.db { + select from Fortune + } or { return ctx.text('db error') } + fortunes.insert(0, Fortune{id: 0, message: 'Additional fortune added at request time.'}) + fortunes.sort(a.message < b.message) + ctx.content_type = 'text/html; charset=utf-8' + return $veb.html() +} + +pub struct Context { + veb.Context +} + +pub struct App { + veb.Middleware[Context] +pub mut: + db pg.DB +} + +pub fn header(mut ctx Context) bool { + ctx.set_header(.date, time.now().as_utc().custom_format('ddd, DD MMM YYYY HH:MM:ss') + ' GMT') + ctx.set_header(.server, 'veb') + return true +} + +fn main() { + mut app := &App{ + db: pg.connect(pg.Config{ + host: 'tfb-database' + port: 5432 + user: 'benchmarkdbuser' + password: 'benchmarkdbpass' + dbname: 'hello_world' + }) ! + } + app.use(handler: header) + veb.run[App, Context](mut app, 8080) +} diff --git a/frameworks/V/veb/run.sh b/frameworks/V/veb/run.sh new file mode 100644 index 00000000000..5979570b9dc --- /dev/null +++ b/frameworks/V/veb/run.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +for i in $(seq 0 $(nproc)); do + taskset -c $i ./main & +done + +wait diff --git a/frameworks/V/veb/veb.dockerfile b/frameworks/V/veb/veb.dockerfile new file mode 100644 index 00000000000..d3313b4515e --- /dev/null +++ b/frameworks/V/veb/veb.dockerfile @@ -0,0 +1,9 @@ +FROM thevlang/vlang:debian-dev +RUN apt update && apt install -y libpq-dev + +WORKDIR /app +COPY ./main.v run.sh fortunes.html ./ +RUN v -prod -cflags '-std=gnu11 -Wall -O3 -march=native -mtune=native -flto' main.v + +EXPOSE 8080 +CMD sh run.sh