# nimble build -d:release=fast -d:danger
#[
result:
real 0.0000021457672119140625s cpu 0.0000007000000000000712s 14999999850000000
real 3.0177180767059326s cpu 3.017706s 14999999850000000
real 0.478442907333374s cpu 0.4784478999999999s 14999999850000000
]#
import std/times
import std/monotimes
import std/strformat
type
Point = ref object
x, y, z: int64 = 0
type
Obj1 = ref object
point: Point
type
Obj0 = ref object
o: Obj1
template `time`*(body: typed): auto =
block:
let
t0 = epochTime()
t1 = cpuTime()
body
(epochTime()-t0, cpuTime()-t1)
proc main() =
let n = 100_000_000
var obj = Obj0(o: Obj1(point: Point()))
var x, y, z: int64 = 0
var (real, cpu) = time:
for i in 0 ..< n:
x += i
y += i
z += i
x += i
y += i
z += i
x += i
y += i
z += i
echo(fmt"real {real}s cpu {cpu}s {x}")
(real, cpu) = time:
for i in 0 ..< n:
obj.o.point.x += i
obj.o.point.y += i
obj.o.point.z += i
obj.o.point.x += i
obj.o.point.y += i
obj.o.point.z += i
obj.o.point.x += i
obj.o.point.y += i
obj.o.point.z += i
echo(fmt"real {real}s cpu {cpu}s {obj.o.point.x}")
obj = Obj0(o: Obj1(point: Point()))
(real, cpu) = time:
for i in 0 ..< n:
let p = obj.o.point
p.x += i
p.y += i
p.z += i
p.x += i
p.y += i
p.z += i
p.x += i
p.y += i
p.z += i
echo(fmt"real {real}s cpu {cpu}s {obj.o.point.x}")
when isMainModule:
main()
// cargo build -r
/*
result:
1.61µs 600ns 14999999850000000
652ns 400ns 14999999850000000
292ns 200ns 14999999850000000
*/
use cpu_time::ProcessTime;
use std::time::SystemTime;
struct Point {
x: i64,
y: i64,
z: i64,
}
struct Obj1 {
point: Point,
}
struct Obj0 {
o: Obj1,
}
fn main() {
let n = 100_000_000;
let mut x: i64 = 0;
let mut y: i64 = 0;
let mut z: i64 = 0;
let mut s = SystemTime::now();
let mut p = ProcessTime::now();
for i in 0..n {
x += i;
y += i;
z += i;
x += i;
y += i;
z += i;
x += i;
y += i;
z += i;
}
println!("{:?} {:?} {:?}", s.elapsed().unwrap(), p.elapsed(), x);
let mut obj = Obj0 {
o: Obj1 {
point: Point { x: 0, y: 0, z: 0 },
},
};
s = SystemTime::now();
p = ProcessTime::now();
for i in 0..n {
obj.o.point.x += i;
obj.o.point.y += i;
obj.o.point.z += i;
obj.o.point.x += i;
obj.o.point.y += i;
obj.o.point.z += i;
obj.o.point.x += i;
obj.o.point.y += i;
obj.o.point.z += i;
}
println!(
"{:?} {:?} {:?}",
s.elapsed().unwrap(),
p.elapsed(),
obj.o.point.x
);
obj = Obj0 {
o: Obj1 {
point: Point { x: 0, y: 0, z: 0 },
},
};
s = SystemTime::now();
p = ProcessTime::now();
for i in 0..n {
let p = &mut obj.o.point;
p.x += i;
p.y += i;
p.z += i;
p.x += i;
p.y += i;
p.z += i;
p.x += i;
p.y += i;
p.z += i;
}
println!(
"{:?} {:?} {:?}",
s.elapsed().unwrap(),
p.elapsed(),
obj.o.point.x
);
}
Thank you very much for your answer. I sincerely apologize - I did indeed overlook this point. To be honest, I had considered it before, but I didn't realize there would be such a significant performance gap between the two approaches. After removing the ref keyword, the speed difference compared to Rust became negligible.
real 0.0000021457672119140625s cpu 0.0000008000000000000194s 14999999850000000
real 0.0000007152557373046875s cpu 0.0000005000000000000664s 14999999850000000
real 0.0000002384185791015625s cpu 0.0000002999999999999531s 14999999850000000