runtime/rpc: optimizations for list and arrays
Requires https://github.com/m-labs/artiq/pull/1510 This is the commit producing the result in the table.
This commit is contained in:
parent
71427f8ec8
commit
d474cf58a5
@ -2,6 +2,7 @@ use core::str;
|
||||
use core::future::Future;
|
||||
use cslice::{CSlice, CMutSlice};
|
||||
use log::trace;
|
||||
use byteorder::{NetworkEndian, ByteOrder};
|
||||
|
||||
use core_io::{Write, Error};
|
||||
use libboard_zynq::smoltcp;
|
||||
@ -76,14 +77,40 @@ async unsafe fn recv_value<F>(stream: &TcpStream, tag: Tag<'async_recursion>, da
|
||||
#[repr(C)]
|
||||
struct List { elements: *mut (), length: u32 };
|
||||
consume_value!(List, |ptr| {
|
||||
(*ptr).length = proto_async::read_i32(stream).await? as u32;
|
||||
|
||||
let length = proto_async::read_i32(stream).await? as usize;
|
||||
(*ptr).length = length as u32;
|
||||
let tag = it.clone().next().expect("truncated tag");
|
||||
(*ptr).elements = alloc(tag.size() * (*ptr).length as usize).await;
|
||||
let mut data = alloc(tag.size() * length as usize).await;
|
||||
|
||||
let mut data = (*ptr).elements;
|
||||
for _ in 0..(*ptr).length as usize {
|
||||
recv_value(stream, tag, &mut data, alloc).await?
|
||||
(*ptr).elements = data;
|
||||
match tag {
|
||||
Tag::Bool => {
|
||||
let ptr = align_ptr_mut::<u8>(data);
|
||||
let dest = core::slice::from_raw_parts_mut(ptr, length);
|
||||
proto_async::read_chunk(stream, dest).await?;
|
||||
},
|
||||
Tag::Int32 => {
|
||||
let ptr = align_ptr_mut::<u32>(data);
|
||||
// reading as raw bytes and do endianness conversion later
|
||||
let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 4);
|
||||
proto_async::read_chunk(stream, dest).await?;
|
||||
drop(dest);
|
||||
let dest = core::slice::from_raw_parts_mut(ptr, length);
|
||||
NetworkEndian::from_slice_u32(dest);
|
||||
},
|
||||
Tag::Int64 | Tag::Float64 => {
|
||||
let ptr = align_ptr_mut::<u64>(data);
|
||||
let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 8);
|
||||
proto_async::read_chunk(stream, dest).await?;
|
||||
drop(dest);
|
||||
let dest = core::slice::from_raw_parts_mut(ptr, length);
|
||||
NetworkEndian::from_slice_u64(dest);
|
||||
},
|
||||
_ => {
|
||||
for _ in 0..(*ptr).length as usize {
|
||||
recv_value(stream, tag, &mut data, alloc).await?
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
@ -100,9 +127,35 @@ async unsafe fn recv_value<F>(stream: &TcpStream, tag: Tag<'async_recursion>, da
|
||||
let elt_tag = it.clone().next().expect("truncated tag");
|
||||
*buffer = alloc(elt_tag.size() * total_len as usize).await;
|
||||
|
||||
let length = total_len as usize;
|
||||
let mut data = *buffer;
|
||||
for _ in 0..total_len {
|
||||
recv_value(stream, elt_tag, &mut data, alloc).await?
|
||||
match elt_tag {
|
||||
Tag::Bool => {
|
||||
let ptr = align_ptr_mut::<u8>(data);
|
||||
let dest = core::slice::from_raw_parts_mut(ptr, length);
|
||||
proto_async::read_chunk(stream, dest).await?;
|
||||
},
|
||||
Tag::Int32 => {
|
||||
let ptr = align_ptr_mut::<u32>(data);
|
||||
let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 4);
|
||||
proto_async::read_chunk(stream, dest).await?;
|
||||
drop(dest);
|
||||
let dest = core::slice::from_raw_parts_mut(ptr, length);
|
||||
NetworkEndian::from_slice_u32(dest);
|
||||
},
|
||||
Tag::Int64 | Tag::Float64 => {
|
||||
let ptr = align_ptr_mut::<u64>(data);
|
||||
let dest = core::slice::from_raw_parts_mut(ptr as *mut u8, length * 8);
|
||||
proto_async::read_chunk(stream, dest).await?;
|
||||
drop(dest);
|
||||
let dest = core::slice::from_raw_parts_mut(ptr, length);
|
||||
NetworkEndian::from_slice_u64(dest);
|
||||
},
|
||||
_ => {
|
||||
for _ in 0..length {
|
||||
recv_value(stream, elt_tag, &mut data, alloc).await?
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
@ -177,12 +230,47 @@ unsafe fn send_value<W>(writer: &mut W, tag: Tag, data: &mut *const ())
|
||||
#[repr(C)]
|
||||
struct List { elements: *const (), length: u32 };
|
||||
consume_value!(List, |ptr| {
|
||||
let length = (*ptr).length as isize;
|
||||
writer.write_u32((*ptr).length)?;
|
||||
let tag = it.clone().next().expect("truncated tag");
|
||||
let mut data = (*ptr).elements;
|
||||
for _ in 0..(*ptr).length as usize {
|
||||
send_value(writer, tag, &mut data)?;
|
||||
}
|
||||
writer.write_u8(tag.as_u8())?;
|
||||
match tag {
|
||||
Tag::Bool => {
|
||||
// we can pretend this is u8...
|
||||
let ptr1 = align_ptr::<u8>(data);
|
||||
let slice = core::slice::from_raw_parts(ptr1, length as usize);
|
||||
writer.write_all(slice)?;
|
||||
},
|
||||
Tag::Int32 => {
|
||||
let ptr1 = align_ptr::<i32>(data);
|
||||
let slice = core::slice::from_raw_parts(ptr1, length as usize);
|
||||
let mut v: alloc::vec::Vec<i32> = slice.to_vec();
|
||||
NetworkEndian::from_slice_i32(&mut v);
|
||||
let slice2 = core::slice::from_raw_parts(
|
||||
v.as_ptr() as usize as *const u8,
|
||||
length as usize * 4
|
||||
);
|
||||
writer.write_all(slice2)?;
|
||||
},
|
||||
Tag::Int64 | Tag::Float64 => {
|
||||
let ptr1 = align_ptr::<i64>(data);
|
||||
let slice = core::slice::from_raw_parts(ptr1, length as usize);
|
||||
let mut v: alloc::vec::Vec<i64> = slice.to_vec();
|
||||
NetworkEndian::from_slice_i64(&mut v);
|
||||
let slice2 = core::slice::from_raw_parts(
|
||||
v.as_ptr() as usize as *const u8,
|
||||
length as usize * 8
|
||||
);
|
||||
writer.write_all(slice2)?;
|
||||
},
|
||||
// non-primitive types, not sure if this would happen but we can handle it...
|
||||
_ => {
|
||||
for _ in 0..length {
|
||||
send_value(writer, tag, &mut data)?;
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@ -199,9 +287,43 @@ unsafe fn send_value<W>(writer: &mut W, tag: Tag, data: &mut *const ())
|
||||
})
|
||||
}
|
||||
let mut data = *buffer;
|
||||
for _ in 0..total_len as usize {
|
||||
send_value(writer, elt_tag, &mut data)?;
|
||||
}
|
||||
let length = total_len as isize;
|
||||
writer.write_u8(elt_tag.as_u8())?;
|
||||
match elt_tag {
|
||||
Tag::Bool => {
|
||||
let ptr1 = align_ptr::<u8>(data);
|
||||
let slice = core::slice::from_raw_parts(ptr1, length as usize);
|
||||
writer.write_all(slice)?;
|
||||
},
|
||||
Tag::Int32 => {
|
||||
let ptr1 = align_ptr::<i32>(data);
|
||||
let slice = core::slice::from_raw_parts(ptr1, length as usize);
|
||||
let mut v: alloc::vec::Vec<i32> = slice.to_vec();
|
||||
NetworkEndian::from_slice_i32(&mut v);
|
||||
let slice2 = core::slice::from_raw_parts(
|
||||
v.as_ptr() as usize as *const u8,
|
||||
length as usize * 4
|
||||
);
|
||||
writer.write_all(slice2)?;
|
||||
},
|
||||
Tag::Int64 | Tag::Float64 => {
|
||||
let ptr1 = align_ptr::<i64>(data);
|
||||
let slice = core::slice::from_raw_parts(ptr1, length as usize);
|
||||
let mut v: alloc::vec::Vec<i64> = slice.to_vec();
|
||||
NetworkEndian::from_slice_i64(&mut v);
|
||||
let slice2 = core::slice::from_raw_parts(
|
||||
v.as_ptr() as usize as *const u8,
|
||||
length as usize * 8
|
||||
);
|
||||
writer.write_all(slice2)?;
|
||||
},
|
||||
// non-primitive types, not sure if this would happen but we can handle it...
|
||||
_ => {
|
||||
for _ in 0..length {
|
||||
send_value(writer, elt_tag, &mut data)?;
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user