ptest/
main.rs

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            //let _ = nh.remove("/data/big");
280            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            /*
319            println!("okay, rewriting and syncing");
320            let start = Instant::now();
321            let mut base = obj.base_mut();
322            base.fill(24);
323            println!("{}ms. syncing...", start.elapsed().as_millis());
324            let start = Instant::now();
325            obj.sync().unwrap();
326            println!("=> {}ms", start.elapsed().as_millis());
327            */
328        }
329        SubCommand::Rdb => {
330            println!("in progress");
331        } /*
332          SubCommand::Rdb => {
333              println!("rocksdb test");
334              let start = std::time::Instant::now();
335              let db = rocksdb::DB::open_default("db").unwrap();
336              println!("rocksdb test: put");
337              db.put("test", "value").unwrap();
338              let val = db.get("test").unwrap().unwrap();
339              let val = String::from_utf8(val).unwrap();
340              println!("rocksdb test: get: {}", val);
341              let end = std::time::Instant::now();
342              println!("done!: {:?}", end - start);
343          }
344          */
345    }
346
347    /*
348    let vo = if let Ok(node) = nh.get("/data/ptest-obj-foo", GetFlags::empty()) {
349        println!("reopened: {:?}", node.id);
350        open_vector_object::<Foo>(node.id).unwrap()
351    } else {
352        let vo = create_vector_object().unwrap();
353        println!("new: {:?}", vo.object().id());
354        nh.put("/data/ptest-obj-foo", vo.object().id()).unwrap();
355        vo
356    };
357    for e in &vo {
358        println!("current contents: {:?}", e);
359    }
360    let len = vo.iter().count();
361    println!("pushing items");
362    let start = std::time::Instant::now();
363    let alloc = ArenaObject::new(ObjectBuilder::default().persist()).unwrap();
364    for i in 0..3 {
365        //println!("pushing: {}", i);
366        //vo.push(i).unwrap();
367        vo.push_ctor(|tx| {
368            let foo = Foo {
369                local_data: i + len as u32,
370                data: InvBox::new_in(&tx, i, alloc.allocator()).unwrap(),
371            };
372
373            tx.write(foo)
374        })
375        .unwrap();
376    }
377    let end = std::time::Instant::now();
378    println!("done!: {:?}", end - start);
379    /*
380    for e in &vo {
381        println!("current contents: {:?}", e);
382    }
383    */
384    */
385}