[Mono-dev] MonoListWrapper WIP - code review/feedback

rfine at tbrf.net rfine at tbrf.net
Sat Jul 20 10:03:00 UTC 2013


On 2013-07-19 11:12, Robert Jordan <robertj at gmx.net> wrote:
> 
> Hi,
> 
> On 18.07.2013 19:16, rfine at tbrf.net wrote:
>> I've been working on a little wrapper library for working with
>> System.Collections.Generic.List<T> instances from native code. The
>> motivation is to provide a way for Mono embedders to easily design 
>> APIs
>> that use List<T> instances as output buffers, whilst running as 
>> quickly
>> as possible and with minimal allocations. Presently I'm getting 
>> around a
>> 30x speedup for bulk loading a chunk of data, compared to allocating 
>> a
>> new array to return that data in. Particular users I envision for 
>> this
>> are game engines like Unity3D.
>> 
>> Any chance I could get a review of what I've done so far? It's just a
>> couple of files, plus a short readme:
>> 
>> https://github.com/richard-fine/mono/tree/MonoListWrapper/contrib/MonoListWrapper
>> 
>> 
>> I'm interested in any "there's a better way to do this" observations,
>> suggestions for things I should add, ways to speed up the new-array
>> cases, bugs you can spot, or any generally "un-Mono" things about it.
> 
> Although I understand your motivation, I find that you're
> exposing/using too much internals to make this wrapper
> ready for public consumption with an unchanged Mono runtime.
> 
> You seem to have exposed mono/class-internals.h, which is
> a no-go.

Mmm, I figured this is a downside of it. On the one hand I want to use 
official APIs as much as possible; on the other hand I want to cache 
things to get the best performance possible, which I think sometimes may 
require bypassing the APIs. But let's see... my use of 
mono/class-internals.h comes down to:

1) Using MonoClassField::offset to construct direct pointers to the 
values of fields in the object:

I missed that mono_field_get_offset() exists. Fixed.

2) Using mono_class_get_generic_class(), 
mono_generic_class_get_context(), and the MonoGenericContext structure 
to retrieve the List<T> generic type argument:

I can't find any public API for retrieving info about a generic 
instantiation. There's a couple of methods for checking whether 
something *is* inflated, but nothing for retrieving or working with the 
MonoGenericContext that it was inflated *with*. So I'm not sure what to 
change this to. Any suggestions?

> Also, poking into List<T> internals isn't quite
> safe, as there is no "written" contract between runtime and BCL
> regarding List<T>.

True enough - the perils of reflection-on-private-members-based 
approaches. I don't think the implementation of List<T> is likely to 
change - at least not the few members in it that I'm using - but it 
would be nice not to rely on that.

FWIW, there's actually nothing in the present implementation that 
requires List<T> *specifically* - any generic class with int Capacity { 
set; }, int _size, int _version and int _items will work.

> It would be safer if you'd copy and rename List<T> and provide
> it together with your MonoListWrapper implementation.

Sure, can do. WrappableList<T> or something.

> Also, there are public mono_array_* macros that
> you can use for accessing MonoArray* elements. You can still
> use them unsafely (like taking the address of the first element
> and access elements using pointer arithmetic) but at least
> it won't poke into too much internals.

Ah, yes, thank you. Fixed to use mono_array_length() and 
mono_array_addr_with_size().

- Richard


More information about the Mono-devel-list mailing list