mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-06 06:38:20 +00:00
runtime align_forward procs as source of truth
This commit is contained in:
@@ -97,15 +97,6 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint)
|
||||
|
||||
@(require_results)
|
||||
arena_alloc :: proc(arena: ^Arena, size, alignment: uint, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
||||
align_forward_uint :: proc "contextless" (ptr, align: uint) -> uint {
|
||||
p := ptr
|
||||
modulo := p & (align-1)
|
||||
if modulo != 0 {
|
||||
p += align - modulo
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
assert(alignment & (alignment-1) == 0, "non-power of two alignment", loc)
|
||||
|
||||
size := size
|
||||
|
||||
@@ -29,6 +29,30 @@ byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byt
|
||||
return ([^]byte)(data)[:max(len, 0)]
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
align_forward_uint :: #force_inline proc "odin" (ptr, align: uint) -> uint {
|
||||
assert(is_power_of_two_uint(align))
|
||||
return (ptr + align-1) & ~(align-1)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
align_forward_int :: #force_inline proc "odin" (ptr, align: int) -> int {
|
||||
assert(is_power_of_two_int(align))
|
||||
return int(align_forward_uint(uint(ptr), uint(align)))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
align_forward_uintptr :: #force_inline proc "odin" (ptr, align: uintptr) -> uintptr {
|
||||
return uintptr(align_forward_uint(uint(ptr), uint(align)))
|
||||
}
|
||||
|
||||
align_forward :: proc {
|
||||
align_forward_int,
|
||||
align_forward_uint,
|
||||
align_forward_uintptr,
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_power_of_two_int :: #force_inline proc "contextless" (x: int) -> bool {
|
||||
if x <= 0 {
|
||||
return false
|
||||
@@ -36,51 +60,17 @@ is_power_of_two_int :: #force_inline proc "contextless" (x: int) -> bool {
|
||||
return (x & (x-1)) == 0
|
||||
}
|
||||
|
||||
align_forward_int :: #force_inline proc "odin" (ptr, align: int) -> int {
|
||||
assert(is_power_of_two_int(align))
|
||||
|
||||
p := ptr
|
||||
modulo := p & (align-1)
|
||||
if modulo != 0 {
|
||||
p += align - modulo
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_power_of_two_uint :: #force_inline proc "contextless" (x: uint) -> bool {
|
||||
if x <= 0 {
|
||||
if x == 0 {
|
||||
return false
|
||||
}
|
||||
return (x & (x-1)) == 0
|
||||
}
|
||||
|
||||
align_forward_uint :: #force_inline proc "odin" (ptr, align: uint) -> uint {
|
||||
assert(is_power_of_two_uint(align))
|
||||
|
||||
p := ptr
|
||||
modulo := p & (align-1)
|
||||
if modulo != 0 {
|
||||
p += align - modulo
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
is_power_of_two_uintptr :: #force_inline proc "contextless" (x: uintptr) -> bool {
|
||||
if x <= 0 {
|
||||
return false
|
||||
}
|
||||
return (x & (x-1)) == 0
|
||||
}
|
||||
|
||||
align_forward_uintptr :: #force_inline proc "odin" (ptr, align: uintptr) -> uintptr {
|
||||
assert(is_power_of_two_uintptr(align))
|
||||
|
||||
p := ptr
|
||||
modulo := p & (align-1)
|
||||
if modulo != 0 {
|
||||
p += align - modulo
|
||||
}
|
||||
return p
|
||||
return is_power_of_two_uint(uint(x))
|
||||
}
|
||||
|
||||
is_power_of_two :: proc {
|
||||
@@ -89,12 +79,6 @@ is_power_of_two :: proc {
|
||||
is_power_of_two_uintptr,
|
||||
}
|
||||
|
||||
align_forward :: proc {
|
||||
align_forward_int,
|
||||
align_forward_uint,
|
||||
align_forward_uintptr,
|
||||
}
|
||||
|
||||
mem_zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
|
||||
if data == nil {
|
||||
return nil
|
||||
|
||||
69
bench.odin
Normal file
69
bench.odin
Normal file
@@ -0,0 +1,69 @@
|
||||
package bench
|
||||
|
||||
import "core:slice"
|
||||
import "core:math/rand"
|
||||
import "core:time"
|
||||
import "core:fmt"
|
||||
|
||||
T :: u64
|
||||
|
||||
benchmark_sort :: proc(num: int) -> f64 {
|
||||
data := make([]T, num)
|
||||
defer delete(data)
|
||||
for &x in data {
|
||||
x = T(rand.uint64())
|
||||
}
|
||||
|
||||
start := time.tick_now()
|
||||
|
||||
slice.sort(data)
|
||||
|
||||
return time.duration_milliseconds(time.tick_since(start))
|
||||
}
|
||||
|
||||
benchmark_sort_with_indices :: proc(num: int) -> f64 {
|
||||
data := make([]T, num)
|
||||
defer delete(data)
|
||||
for &x in data {
|
||||
x = T(rand.uint64())
|
||||
}
|
||||
|
||||
start := time.tick_now()
|
||||
|
||||
// Important: includes 'sort_from_permutation_indices'
|
||||
indices := slice.sort_with_indices(data)
|
||||
|
||||
return time.duration_milliseconds(time.tick_since(start))
|
||||
}
|
||||
|
||||
benchmark_proc :: proc(num: int, bench: proc(int) -> f64, expr := #caller_expression(bench)) {
|
||||
|
||||
ITERS :: 10
|
||||
min_dur := max(f64)
|
||||
max_dur := min(f64)
|
||||
sum_dur: f64
|
||||
for i in 0..<ITERS {
|
||||
dur := bench(num)
|
||||
min_dur = min(min_dur, dur)
|
||||
max_dur = max(max_dur, dur)
|
||||
sum_dur += dur
|
||||
}
|
||||
|
||||
// fmt.printfln("[%s] num: %i, avg ms: %.5f, min: %.5f, max: %.5f", expr, num, sum_dur / ITERS, min_dur, max_dur)
|
||||
fmt.printfln("%i, %.5f, %.5f, %.5f", num, sum_dur / ITERS, min_dur, max_dur)
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
fmt.println("Running...")
|
||||
benchmark_proc(1000, benchmark_sort)
|
||||
|
||||
|
||||
fmt.printfln("\nnum, avg, min, max")
|
||||
for i in 1..=1000 {
|
||||
benchmark_proc(1000 * i, benchmark_sort)
|
||||
}
|
||||
// for i in 1..=uint(16) {
|
||||
// benchmark_proc(1 << i, benchmark_sort_with_indices)
|
||||
// }
|
||||
fmt.println("Done")
|
||||
}
|
||||
@@ -467,13 +467,7 @@ Check whether a number is a power of two.
|
||||
This procedure checks whether a given pointer-sized unsigned integer contains
|
||||
a power-of-two value.
|
||||
*/
|
||||
@(require_results)
|
||||
is_power_of_two :: proc "contextless" (x: uintptr) -> bool {
|
||||
if x <= 0 {
|
||||
return false
|
||||
}
|
||||
return (x & (x-1)) == 0
|
||||
}
|
||||
is_power_of_two :: runtime.is_power_of_two_uintptr
|
||||
|
||||
/*
|
||||
Check if a pointer is aligned.
|
||||
@@ -497,11 +491,7 @@ bytes, `ptr` is returned.
|
||||
|
||||
The specified alignment must be a power of 2.
|
||||
*/
|
||||
@(require_results)
|
||||
align_forward_uintptr :: proc(ptr, align: uintptr) -> uintptr {
|
||||
assert(is_power_of_two(align))
|
||||
return (ptr + align-1) & ~(align-1)
|
||||
}
|
||||
align_forward_uintptr :: runtime.align_forward_uintptr
|
||||
|
||||
/*
|
||||
Align pointer forward.
|
||||
@@ -526,10 +516,7 @@ bytes, `ptr` is returned.
|
||||
|
||||
The specified alignment must be a power of 2.
|
||||
*/
|
||||
@(require_results)
|
||||
align_forward_int :: proc(ptr, align: int) -> int {
|
||||
return int(align_forward_uintptr(uintptr(ptr), uintptr(align)))
|
||||
}
|
||||
align_forward_int :: runtime.align_forward_int
|
||||
|
||||
/*
|
||||
Align uint forward.
|
||||
@@ -540,10 +527,7 @@ bytes, `ptr` is returned.
|
||||
|
||||
The specified alignment must be a power of 2.
|
||||
*/
|
||||
@(require_results)
|
||||
align_forward_uint :: proc(ptr, align: uint) -> uint {
|
||||
return uint(align_forward_uintptr(uintptr(ptr), uintptr(align)))
|
||||
}
|
||||
align_forward_uint :: runtime.align_forward_uint
|
||||
|
||||
/*
|
||||
Align uintptr backwards.
|
||||
|
||||
Reference in New Issue
Block a user