1use std::{
2 fmt::{Debug, Display},
3 time::Instant,
4};
5
6use clap::Parser;
7use miette::{IntoDiagnostic, Result};
8use naming::GetFlags;
9use tracing::Level;
10use twizzler::{
11 Invariant,
12 alloc::{
13 arena::{ArenaAllocator, ArenaObject},
14 invbox::InvBox,
15 },
16 collections::vec::{VecObject, VecObjectAlloc},
17 marker::Invariant,
18 object::{MapFlags, ObjID, Object, ObjectBuilder, RawObject},
19};
20use twizzler_abi::syscall::sys_object_ctrl;
21use twizzler_rt_abi::{error::TwzError, object::ObjectHandle};
22
23#[allow(dead_code)]
24#[derive(Invariant)]
25struct Foo {
26 data: InvBox<u32, ArenaAllocator>,
27 local_data: u32,
28}
29
30impl Debug for Foo {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 f.debug_struct("Foo")
33 .field("local_data", &self.local_data)
34 .field("data (ptr)", &self.data.global())
35 .field("data (val)", &*self.data.resolve())
36 .finish()
37 }
38}
39
40impl Display for Foo {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 write!(
43 f,
44 "Foo ({:p}): local {}, ptr: {:x} :: ",
45 self,
46 &self.local_data,
47 &self.data.as_ptr().raw(),
48 )?;
49 write!(f, "{}", &*self.data.resolve())
50 }
51}
52
53fn create_arena() -> Result<ArenaObject> {
54 let obj = ObjectBuilder::default().persist();
55 ArenaObject::new(obj).into_diagnostic()
56}
57
58fn open_arena(id: ObjID) -> Result<ArenaObject> {
59 ArenaObject::from_objid(id).into_diagnostic()
60}
61
62fn create_vector_object<T: Debug + Invariant>() -> Result<VecObject<T, VecObjectAlloc>> {
63 let obj = ObjectBuilder::default().persist();
64 VecObject::<T, VecObjectAlloc>::new(obj).into_diagnostic()
65}
66
67fn open_vector_object<T: Debug + Invariant>(id: ObjID) -> Result<VecObject<T, VecObjectAlloc>> {
68 Ok(VecObject::from(
69 Object::map(id, MapFlags::PERSIST | MapFlags::READ | MapFlags::WRITE).into_diagnostic()?,
70 ))
71}
72
73#[derive(clap::Parser, Clone, Copy, Debug)]
74struct Cli {
75 sub: SubCommand,
76 #[clap(default_value = "u32")]
77 ty: VecTy,
78}
79
80#[derive(clap::ValueEnum, clap::Parser, Clone, Copy, Debug)]
81enum VecTy {
82 U32,
83 Foo,
84}
85
86#[derive(clap::ValueEnum, clap::Subcommand, Clone, Copy, Debug)]
87enum SubCommand {
88 New,
89 Push,
90 Append,
91 Read,
92 Hw,
93 Rdb,
94 Preload,
95 Big,
96}
97
98fn open_or_create_arena() -> Result<ArenaObject> {
99 let mut nh = naming::dynamic_naming_factory().unwrap();
100 let name = format!("/data/ptest-arena");
101 let vo = if let Ok(node) = nh.get(&name, GetFlags::empty()) {
102 println!("reopened-arena: {:?}", node.id);
103 open_arena(node.id)
104 } else {
105 let vo = create_arena()?;
106 println!("new-arena: {:?}", vo.object().id());
107 let _ = nh.remove(&name);
108 nh.put(&name, vo.object().id()).into_diagnostic()?;
109 Ok(vo)
110 };
111 vo
112}
113fn open_or_create_vector_object<T: Debug + Invariant>(
114 name: &str,
115) -> Result<VecObject<T, VecObjectAlloc>> {
116 let mut nh = naming::dynamic_naming_factory().unwrap();
117 let name = format!("/data/ptest-obj-{}", name);
118 let vo = if let Ok(node) = nh.get(&name, GetFlags::empty()) {
119 println!("reopened: {:?}", node.id);
120 open_vector_object::<T>(node.id)
121 } else {
122 let vo = create_vector_object::<T>()?;
123 println!("new: {:?}", vo.object().id());
124 let _ = nh.remove(&name);
125 nh.put(&name, vo.object().id()).into_diagnostic()?;
126 Ok(vo)
127 };
128 vo
129}
130
131impl Foo {
132 fn new_in(
133 place: impl AsRef<ObjectHandle>,
134 val: u32,
135 alloc: ArenaAllocator,
136 ) -> Result<Self, TwzError> {
137 Ok(Self {
138 data: InvBox::new_in(place, val, alloc)?,
139 local_data: val,
140 })
141 }
142}
143
144fn do_push_foo(mut vo: VecObject<Foo, VecObjectAlloc>, arena: ArenaObject) {
145 let val = vo.len() as u32;
146 vo.push_ctor(|r| {
147 let foo = Foo::new_in(&r, val, arena.allocator())?;
148 Ok(r.write(foo))
149 })
150 .unwrap();
151}
152
153fn do_append_foo(mut vo: VecObject<Foo, VecObjectAlloc>, arena: ArenaObject) {
154 for i in 0..8 {
155 tracing::info!("PUSH {}", i);
156 vo.push_ctor(|r| {
157 let foo = Foo::new_in(&r, i, arena.allocator())?;
158 Ok(r.write(foo))
159 })
160 .unwrap();
161 tracing::info!("DONE: {}", i);
162 }
163}
164
165fn do_push(vo: VecObject<u32, VecObjectAlloc>) {
166 let mut vo = vo;
167 vo.push(vo.len() as u32).unwrap();
168}
169
170fn do_append(vo: VecObject<u32, VecObjectAlloc>) {
171 let mut vo = vo;
172 for i in 0..100 {
173 vo.push(i).unwrap();
174 }
175}
176
177fn do_read<T: Debug + Invariant + Display>(vo: VecObject<T, VecObjectAlloc>) {
178 for i in vo.iter().enumerate() {
179 println!("entry {}: {}", i.0, i.1);
180 }
181}
182
183#[link(name = "c")]
184unsafe extern "C" {}
185fn main() {
186 tracing::subscriber::set_global_default(
187 tracing_subscriber::FmtSubscriber::builder()
188 .with_max_level(Level::INFO)
189 .finish(),
190 )
191 .unwrap();
192 let cli = Cli::parse();
193 println!("==> {:?}", cli);
194
195 let mut nh = naming::dynamic_naming_factory().unwrap();
196 match cli.sub {
197 SubCommand::Hw => {
198 let top = hwlocality::topology::Topology::new().unwrap();
199 println!("{:#?}", top);
200 let cpus = top.complete_cpuset();
201 println!("==> {:?}", cpus);
202 }
203 SubCommand::New => match cli.ty {
204 VecTy::U32 => {
205 let _ = nh.remove("/data/ptest-obj-u32");
206 let vo = create_vector_object::<u32>().unwrap();
207 println!("new: {:?}", vo.object().id());
208 nh.put("/data/ptest-obj-u32", vo.object().id()).unwrap();
209 }
210 VecTy::Foo => {
211 let _ = nh.remove("/data/ptest-obj-foo");
212 let _ = nh.remove("/data/ptest-arena");
213 let vo = create_vector_object::<u32>().unwrap();
214 println!("new: {:?}", vo.object().id());
215 nh.put("/data/ptest-obj-foo", vo.object().id()).unwrap();
216
217 let vo = create_arena().unwrap();
218 println!("new arena: {:?}", vo.object().id());
219 nh.put("/data/ptest-arena", vo.object().id()).unwrap();
220 }
221 },
222 SubCommand::Push => match cli.ty {
223 VecTy::U32 => {
224 let vo = open_or_create_vector_object::<u32>("u32").unwrap();
225 let start = std::time::Instant::now();
226 do_push(vo);
227 let end = std::time::Instant::now();
228 println!("done!: {:?}", end - start);
229 }
230 VecTy::Foo => {
231 let vo = open_or_create_vector_object::<Foo>("foo").unwrap();
232 let arena = open_or_create_arena().unwrap();
233 let start = std::time::Instant::now();
234 do_push_foo(vo, arena);
235 let end = std::time::Instant::now();
236 println!("done!: {:?}", end - start);
237 }
238 },
239 SubCommand::Append => {
240 let vo = open_or_create_vector_object::<u32>("u32").unwrap();
241 let start = std::time::Instant::now();
242 match cli.ty {
243 VecTy::U32 => do_append(vo),
244 VecTy::Foo => {
245 let vo = open_or_create_vector_object::<Foo>("foo").unwrap();
246 let arena = open_or_create_arena().unwrap();
247 do_append_foo(vo, arena)
248 }
249 }
250 let end = std::time::Instant::now();
251 println!("done!: {:?}", end - start);
252 }
253 SubCommand::Read => match cli.ty {
254 VecTy::U32 => {
255 let vo = open_or_create_vector_object::<u32>("u32").unwrap();
256 let start = std::time::Instant::now();
257 do_read(vo);
258 let end = std::time::Instant::now();
259 println!("done!: {:?}", end - start);
260 }
261 VecTy::Foo => {
262 let vo = open_or_create_vector_object::<Foo>("foo").unwrap();
263 let start = std::time::Instant::now();
264 do_read(vo);
265 let end = std::time::Instant::now();
266 println!("done!: {:?}", end - start);
267 }
268 },
269 SubCommand::Preload => {
270 let start = std::time::Instant::now();
271 let id = nh.get("/ext/rst", GetFlags::empty()).unwrap().id;
272 sys_object_ctrl(id, twizzler_abi::syscall::ObjectControlCmd::Preload).unwrap();
273 let end = std::time::Instant::now();
274 println!("done!: {:?}", end - start);
275 }
276 SubCommand::Big => {
277 const LEN: usize = 1024 * 1024 * 100;
278
279 if let Ok(n) = nh.get("/data/big", GetFlags::empty()) {
281 let obj = Object::<u8>::map(n.id, MapFlags::READ).unwrap();
282 let obj = unsafe { obj.cast::<[u8; LEN]>() };
283 let base = obj.base_ptr::<u8>();
284 let slice = unsafe { core::slice::from_raw_parts(base, LEN) };
285 let sum = slice.iter().fold(0u32, |acc, x| acc + *x as u32);
286 println!("SUM for {} IS: {}", obj.id(), sum);
287 let mut b = 0u16;
288 for (i, s) in slice.iter().enumerate() {
289 b += 1;
290 if *s != (b - 1) as u8 {
291 println!("wrong at {}: expect: {}, got: {}", i, (b - 1) as u8, *s);
292 }
293 }
294 return;
295 }
296
297 let obj = ObjectBuilder::default().persist().build(0u8).unwrap();
298 let obj = unsafe { obj.cast::<[u8; LEN]>() };
299 let mut obj = unsafe { obj.as_mut().unwrap() };
300 println!("filling...");
301 let start = Instant::now();
302 let mut base = obj.base_mut();
303 let mut b = 0u16;
304 base.fill_with(|| {
305 b += 1;
306 (b - 1) as u8
307 });
308
309 let sum = base.iter().fold(0u32, |acc, x| acc + *x as u32);
310 println!("SUM WAS: {} for {}", sum, obj.id());
311 println!("{}ms. syncing...", start.elapsed().as_millis());
312 let start = Instant::now();
313 obj.sync().unwrap();
314 println!("=> {}ms", start.elapsed().as_millis());
315 let _ = nh.remove("/data/big");
316 nh.put("/data/big", obj.id()).unwrap();
317
318 }
329 SubCommand::Rdb => {
330 println!("in progress");
331 } }
346
347 }