[rust-dev] Misc questions

Michael Neumann mneumann at ntecs.de
Thu Jan 24 15:55:41 PST 2013


Hi,

Again a couple of random question...

* Would it be possible to optimize this kind of enum (two cases, where 
one case contains a borrowed pointer)
into a simple pointer, where None would be represented as the null pointer?

enum Option<A> {
None,
Some(~A)
}

As the pointer to A can never be null it should be possible. This 
probably wouldn't affect performance much,
but when storing it into an Array that would save a lot of space 
(basically cut down space usage half).

* match() statements. I think the order in which the matches are 
performed are important. But when I have
a very simple statement like this:

match io.read_char() as u8 {
0x0c => ...,
0x0d => ...,
0x0f .. 0x1a =>
...
}

will the compiler construct an efficient goto jump table or will it 
construct sequential if statements instead?
´ My question is if it makes sense to reorder more frequent cases to the 
top or not.

Also I wonder why I get a "non-exhaustive patterns" error message for 
this one:

match c as u8 {
0 .. 255 => 1
}

* Using str::as_bytes()

I cannot get str::as_bytes working. The example in the documention is 
not working for several reasons (wrong syntax...)

I tried this:

fn write(buf: ~[u8]) {
io::println(fmt!("%?", buf));
}

fn main() {
let mystr = ~"Hello World";
do str::as_bytes(&mystr) |bytes| {
write(*bytes);
}
}

But get the compiler error:

t.rs:8:10: 8:16 error: moving out of dereference of immutable & pointer
t.rs:8 write(*bytes);
^~~~~~

* A ~str is internally represented by an ~[u8] vector.
It is basically a heap-allocated

struct rust_vec {
size_t fill;
size_t alloc;
uint8_t data[];
}

When I correctly read the code the string is allocated in-place, i.e. 
for a string of size 5,
you will allocate sizeof(struct rust_vec) + 5 + 1 bytes. So the data 
pointer points past the
data. As a reallocation can change the pointer to the rust_vec, I know 
understand why
I have to pass sometimes a &mut ~[T]into a function. In case the 
reallocation returns a new
pointer, the passed pointer has to be updated.

I guess slices use the same rust_vec struct, but allocated on the stack, 
where data points to
another ~vectors data.

What I don't understand is the following comment for struct rust_vec:

size_t fill; // in bytes; if zero, heapified

Please correct me if I am wrong.

* There is a severe performance bug in TcpSocketBuf.read(). I am trying 
to fix it right now myself,
once I am done, I will do another post. This explains why I get very bad 
network I/O performance.
Basically the function copies the internal buffer over and over again, 
once for each call.
This is especially bad when using read_line(), as it calls read() for 
every byte.

* What exaclty is the semantic of "as"? Is it like a C-cast?

Imagine if I have

let b: u8 = 255;
let s: i8 = b as i8;

This gives -1 for s. But when I do "b as i32", it gives 255.
If I want to keep the sign I have to do "(b as i8) as i32".

* I don't like the way libuv is currently integrated into the system. It 
works, but performance is
quite low and IMHO the blocking interface is not very usable. For 
example I want to write a process
that accepts messages from other processes, and then writes something to 
the socket or reads from
the socket. This will currently not work, as reading from the socket 
will block the process, and
then no more requests can be sent to the process.
So instead of using the read() / write() API of an io::Reader, I'd 
prefer to expose the read/write
events of libuv via messages (this is already done between the iotask 
and the read()/write() methods,
but it is not accessible to the "end-user").

So instead of:

io.read(...)

one would simply write:

readport.recv()

The same for writes. EOF results in closing the readport. The question 
is how these messages
should look like to be usable for the programmer (how to handle errors?).

What do you think?

Actually there would be connecting ports, which receive events whenever 
a new connection is established.
A successfully established connection would then be represented by a 
readport and writechannel.

* I'd like to know more how the task scheduler and the pipes work 
together. Is there any info available somewhere?
Also, if I would create a native pthread in C, could I simply call an 
external rust function?

Best,

Michael


More information about the Rust-dev mailing list