mirror of
https://github.com/sbrow/thor.git
synced 2026-08-26 11:23:32 -04:00
225 lines
5.2 KiB
Odin
225 lines
5.2 KiB
Odin
package bench
|
|
|
|
import "../mustache"
|
|
import "core:fmt"
|
|
import "core:mem"
|
|
import "core:os"
|
|
import "core:strconv"
|
|
import "core:time"
|
|
|
|
Tag :: struct {
|
|
name: string,
|
|
slug: string,
|
|
}
|
|
|
|
Nav_Item :: struct {
|
|
url: string,
|
|
label: string,
|
|
}
|
|
|
|
Post :: struct {
|
|
title: string,
|
|
url: string,
|
|
date: string,
|
|
year: string,
|
|
excerpt: string,
|
|
author: string,
|
|
tags: [dynamic]Tag,
|
|
}
|
|
|
|
Comment :: struct {
|
|
author: string,
|
|
date: string,
|
|
body: string,
|
|
}
|
|
|
|
Page_Data :: struct {
|
|
title: string,
|
|
now: string,
|
|
posts: [dynamic]Post,
|
|
comments: [dynamic]Comment,
|
|
nav_items: [dynamic]Nav_Item,
|
|
}
|
|
|
|
TEMPLATE_DIR :: #directory
|
|
|
|
main :: proc() {
|
|
iterations := 250
|
|
dump_path := ""
|
|
|
|
i := 1
|
|
for i < len(os.args) {
|
|
if os.args[i] == "--dump" && i + 1 < len(os.args) {
|
|
dump_path = os.args[i + 1]
|
|
i += 2
|
|
} else {
|
|
n, ok := strconv.parse_int(os.args[i])
|
|
if ok && n > 0 {
|
|
iterations = n
|
|
}
|
|
i += 1
|
|
}
|
|
}
|
|
|
|
data_arena: mem.Dynamic_Arena
|
|
mem.dynamic_arena_init(&data_arena)
|
|
defer mem.dynamic_arena_destroy(&data_arena)
|
|
|
|
temp_arena: mem.Dynamic_Arena
|
|
mem.dynamic_arena_init(&temp_arena)
|
|
defer mem.dynamic_arena_destroy(&temp_arena)
|
|
|
|
context.allocator = mem.dynamic_arena_allocator(&data_arena)
|
|
context.temp_allocator = mem.dynamic_arena_allocator(&temp_arena)
|
|
|
|
base := parse_file("base.html")
|
|
page := parse_file("page.html")
|
|
defer mustache.delete_template(&base)
|
|
defer mustache.delete_template(&page)
|
|
|
|
partials := make(map[string]mustache.Template)
|
|
partials["base"] = base
|
|
partials["post"] = parse_file("partials/post.html")
|
|
partials["comment"] = parse_file("partials/comment.html")
|
|
defer mustache.delete_partials(partials)
|
|
|
|
data := generate_data()
|
|
|
|
if dump_path != "" {
|
|
result, err := mustache.render(page, data, partials, allocator = context.temp_allocator)
|
|
if err != nil {
|
|
b := mustache.body(err)
|
|
fmt.eprintln("render error:", b.msg)
|
|
os.exit(1)
|
|
}
|
|
werr := os.write_entire_file_from_string(dump_path, result)
|
|
if werr != nil {
|
|
fmt.eprintln("failed to write", dump_path, ":", werr)
|
|
os.exit(1)
|
|
}
|
|
fmt.println("wrote", len(result), "bytes to", dump_path)
|
|
return
|
|
}
|
|
|
|
for _ in 0 ..< 3 {
|
|
_, _ = mustache.render(page, data, partials, allocator = context.temp_allocator)
|
|
mem.dynamic_arena_free_all(&temp_arena)
|
|
}
|
|
|
|
start := time.now()
|
|
for _ in 0 ..< iterations {
|
|
_, _ = mustache.render(page, data, partials, allocator = context.temp_allocator)
|
|
mem.dynamic_arena_free_all(&temp_arena)
|
|
}
|
|
elapsed := time.since(start)
|
|
|
|
seconds := time.duration_seconds(elapsed)
|
|
per_render_ms := seconds * 1000 / f64(iterations)
|
|
|
|
fmt.printfln(
|
|
"iterations=%d total=%.3fs per_render=%.3fms",
|
|
iterations,
|
|
seconds,
|
|
per_render_ms,
|
|
)
|
|
}
|
|
|
|
parse_file :: proc(name: string) -> mustache.Template {
|
|
path := fmt.aprintf("%s/templates/%s", TEMPLATE_DIR, name)
|
|
data, err := os.read_entire_file_from_path(path, context.allocator)
|
|
if err != nil {
|
|
fmt.eprintln("failed to read", path, ":", err)
|
|
os.exit(1)
|
|
}
|
|
source := string(data)
|
|
tmpl, perr := mustache.parse(source, path)
|
|
if perr != nil {
|
|
b := mustache.body(perr)
|
|
fmt.eprintln("parse error in", path, ":", b.msg)
|
|
os.exit(1)
|
|
}
|
|
return tmpl
|
|
}
|
|
|
|
generate_data :: proc() -> Page_Data {
|
|
years := []string {
|
|
"2025",
|
|
"2024",
|
|
"2023",
|
|
"2022",
|
|
"2021",
|
|
"2020",
|
|
"2019",
|
|
"2018",
|
|
"2017",
|
|
"2016",
|
|
}
|
|
|
|
posts := make([dynamic]Post, 0, 500)
|
|
for year in years {
|
|
for i in 0 ..< 50 {
|
|
tags := make([dynamic]Tag, 0, 3)
|
|
append(
|
|
&tags,
|
|
Tag{name = fmt.aprintf("%s-notes", year), slug = fmt.aprintf("%s-notes", year)},
|
|
)
|
|
append(&tags, Tag{name = "writing", slug = "writing"})
|
|
append(&tags, Tag{name = "archive", slug = "archive"})
|
|
|
|
month := (i % 12) + 1
|
|
day := (i % 28) + 1
|
|
|
|
author := ""
|
|
if i % 3 != 0 {
|
|
author = fmt.aprintf("Author %d", i % 5)
|
|
}
|
|
|
|
append(
|
|
&posts,
|
|
Post {
|
|
title = fmt.aprintf("Post %d from %s", i, year),
|
|
url = fmt.aprintf("/%s/post-%d", year, i),
|
|
date = fmt.aprintf("%s-%02d-%02dT10:00:00Z", year, month, day),
|
|
year = year,
|
|
excerpt = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
author = author,
|
|
tags = tags,
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
comments := make([dynamic]Comment, 0, 100)
|
|
for i in 0 ..< 100 {
|
|
year := years[i % len(years)]
|
|
month := (i % 12) + 1
|
|
day := (i % 28) + 1
|
|
append(
|
|
&comments,
|
|
Comment {
|
|
author = fmt.aprintf("Commenter %d", i),
|
|
date = fmt.aprintf("%s-%02d-%02dT12:00:00Z", year, month, day),
|
|
body = fmt.aprintf("Great post! This is comment number %d.", i),
|
|
},
|
|
)
|
|
}
|
|
|
|
nav_items := make([dynamic]Nav_Item, 0, 8)
|
|
append(&nav_items, Nav_Item{url = "/", label = "Home"})
|
|
append(&nav_items, Nav_Item{url = "/archive", label = "Archive"})
|
|
append(&nav_items, Nav_Item{url = "/about", label = "About"})
|
|
append(&nav_items, Nav_Item{url = "/tags", label = "Tags"})
|
|
append(&nav_items, Nav_Item{url = "/feed.xml", label = "RSS"})
|
|
append(&nav_items, Nav_Item{url = "https://github.com/example", label = "GitHub"})
|
|
append(&nav_items, Nav_Item{url = "https://twitter.com/example", label = "Twitter"})
|
|
append(&nav_items, Nav_Item{url = "mailto:nobody@example.com", label = "Email"})
|
|
|
|
return Page_Data {
|
|
title = "Post Archive",
|
|
now = "2025-07-21T12:00:00Z",
|
|
posts = posts,
|
|
comments = comments,
|
|
nav_items = nav_items,
|
|
}
|
|
}
|