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(true);
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(true);
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 f = sgtest::bar(sgtest::Foo { x: 42 });
196    println!("==> foo: {:?}", f);
197
198    let mut nh = naming::dynamic_naming_factory().unwrap();
199    match cli.sub {
200        SubCommand::Hw => {
201            let top = hwlocality::topology::Topology::new().unwrap();
202            println!("{:#?}", top);
203            let cpus = top.complete_cpuset();
204            println!("==> {:?}", cpus);
205        }
206        SubCommand::New => match cli.ty {
207            VecTy::U32 => {
208                let _ = nh.remove("/data/ptest-obj-u32");
209                let vo = create_vector_object::<u32>().unwrap();
210                println!("new: {:?}", vo.object().id());
211                nh.put("/data/ptest-obj-u32", vo.object().id()).unwrap();
212            }
213            VecTy::Foo => {
214                let _ = nh.remove("/data/ptest-obj-foo");
215                let _ = nh.remove("/data/ptest-arena");
216                let vo = create_vector_object::<u32>().unwrap();
217                println!("new: {:?}", vo.object().id());
218                nh.put("/data/ptest-obj-foo", vo.object().id()).unwrap();
219
220                let vo = create_arena().unwrap();
221                println!("new arena: {:?}", vo.object().id());
222                nh.put("/data/ptest-arena", vo.object().id()).unwrap();
223            }
224        },
225        SubCommand::Push => match cli.ty {
226            VecTy::U32 => {
227                let vo = open_or_create_vector_object::<u32>("u32").unwrap();
228                let start = std::time::Instant::now();
229                do_push(vo);
230                let end = std::time::Instant::now();
231                println!("done!: {:?}", end - start);
232            }
233            VecTy::Foo => {
234                let vo = open_or_create_vector_object::<Foo>("foo").unwrap();
235                let arena = open_or_create_arena().unwrap();
236                let start = std::time::Instant::now();
237                do_push_foo(vo, arena);
238                let end = std::time::Instant::now();
239                println!("done!: {:?}", end - start);
240            }
241        },
242        SubCommand::Append => {
243            let vo = open_or_create_vector_object::<u32>("u32").unwrap();
244            let start = std::time::Instant::now();
245            match cli.ty {
246                VecTy::U32 => do_append(vo),
247                VecTy::Foo => {
248                    let vo = open_or_create_vector_object::<Foo>("foo").unwrap();
249                    let arena = open_or_create_arena().unwrap();
250                    do_append_foo(vo, arena)
251                }
252            }
253            let end = std::time::Instant::now();
254            println!("done!: {:?}", end - start);
255        }
256        SubCommand::Read => match cli.ty {
257            VecTy::U32 => {
258                let vo = open_or_create_vector_object::<u32>("u32").unwrap();
259                let start = std::time::Instant::now();
260                do_read(vo);
261                let end = std::time::Instant::now();
262                println!("done!: {:?}", end - start);
263            }
264            VecTy::Foo => {
265                let vo = open_or_create_vector_object::<Foo>("foo").unwrap();
266                let start = std::time::Instant::now();
267                do_read(vo);
268                let end = std::time::Instant::now();
269                println!("done!: {:?}", end - start);
270            }
271        },
272        SubCommand::Preload => {
273            let start = std::time::Instant::now();
274            let id = nh.get("/ext/rst", GetFlags::empty()).unwrap().id;
275            sys_object_ctrl(id, twizzler_abi::syscall::ObjectControlCmd::Preload).unwrap();
276            let end = std::time::Instant::now();
277            println!("done!: {:?}", end - start);
278        }
279        SubCommand::Big => {
280            const LEN: usize = 1024 * 1024 * 100;
281
282            //let _ = nh.remove("/data/big");
283            if let Ok(n) = nh.get("/data/big", GetFlags::empty()) {
284                let obj = Object::<u8>::map(n.id, MapFlags::READ).unwrap();
285                let obj = unsafe { obj.cast::<[u8; LEN]>() };
286                let base = obj.base_ptr::<u8>();
287                let slice = unsafe { core::slice::from_raw_parts(base, LEN) };
288                let sum = slice.iter().fold(0u32, |acc, x| acc + *x as u32);
289                println!("SUM for {} IS: {}", obj.id(), sum);
290                let mut b = 0u16;
291                for (i, s) in slice.iter().enumerate() {
292                    b += 1;
293                    if *s != (b - 1) as u8 {
294                        println!("wrong at {}: expect: {}, got: {}", i, (b - 1) as u8, *s);
295                    }
296                }
297                return;
298            }
299
300            let obj = ObjectBuilder::default().persist(true).build(0u8).unwrap();
301            let obj = unsafe { obj.cast::<[u8; LEN]>() };
302            let mut obj = unsafe { obj.as_mut().unwrap() };
303            println!("filling...");
304            let start = Instant::now();
305            let mut base = obj.base_mut();
306            let mut b = 0u16;
307            base.fill_with(|| {
308                b += 1;
309                (b - 1) as u8
310            });
311
312            let sum = base.iter().fold(0u32, |acc, x| acc + *x as u32);
313            println!("SUM WAS: {} for {}", sum, obj.id());
314            println!("{}ms. syncing...", start.elapsed().as_millis());
315            let start = Instant::now();
316            obj.sync().unwrap();
317            println!("=> {}ms", start.elapsed().as_millis());
318            let _ = nh.remove("/data/big");
319            nh.put("/data/big", obj.id()).unwrap();
320
321            /*
322            println!("okay, rewriting and syncing");
323            let start = Instant::now();
324            let mut base = obj.base_mut();
325            base.fill(24);
326            println!("{}ms. syncing...", start.elapsed().as_millis());
327            let start = Instant::now();
328            obj.sync().unwrap();
329            println!("=> {}ms", start.elapsed().as_millis());
330            */
331        }
332        SubCommand::Rdb => {
333            println!("in progress");
334        } /*
335          SubCommand::Rdb => {
336              println!("rocksdb test");
337              let start = std::time::Instant::now();
338              let db = rocksdb::DB::open_default("db").unwrap();
339              println!("rocksdb test: put");
340              db.put("test", "value").unwrap();
341              let val = db.get("test").unwrap().unwrap();
342              let val = String::from_utf8(val).unwrap();
343              println!("rocksdb test: get: {}", val);
344              let end = std::time::Instant::now();
345              println!("done!: {:?}", end - start);
346          }
347          */
348    }
349
350    /*
351    let vo = if let Ok(node) = nh.get("/data/ptest-obj-foo", GetFlags::empty()) {
352        println!("reopened: {:?}", node.id);
353        open_vector_object::<Foo>(node.id).unwrap()
354    } else {
355        let vo = create_vector_object().unwrap();
356        println!("new: {:?}", vo.object().id());
357        nh.put("/data/ptest-obj-foo", vo.object().id()).unwrap();
358        vo
359    };
360    for e in &vo {
361        println!("current contents: {:?}", e);
362    }
363    let len = vo.iter().count();
364    println!("pushing items");
365    let start = std::time::Instant::now();
366    let alloc = ArenaObject::new(ObjectBuilder::default().persist(true)).unwrap();
367    for i in 0..3 {
368        //println!("pushing: {}", i);
369        //vo.push(i).unwrap();
370        vo.push_ctor(|tx| {
371            let foo = Foo {
372                local_data: i + len as u32,
373                data: InvBox::new_in(&tx, i, alloc.allocator()).unwrap(),
374            };
375
376            tx.write(foo)
377        })
378        .unwrap();
379    }
380    let end = std::time::Instant::now();
381    println!("done!: {:?}", end - start);
382    /*
383    for e in &vo {
384        println!("current contents: {:?}", e);
385    }
386    */
387    */
388}