On Thu, 23 Jun 2016 15:04:22 -0700 Cedric BAIL <cedric.b...@free.fr> said:
> On Wed, Jun 22, 2016 at 6:42 PM, Carsten Haitzler <ras...@rasterman.com> > wrote: > > On Wed, 22 Jun 2016 10:38:13 -0700 Cedric BAIL <cedric.b...@free.fr> said: > >> On Wed, Jun 22, 2016 at 6:46 AM, Felipe Magno de Almeida > >> <felipe.m.alme...@gmail.com> wrote: > >> > On Jun 22, 2016 9:22 AM, "Daniel Kolesa" <dan...@octaforge.org> wrote: > >> >> On Mon, Jun 20, 2016 at 1:04 AM, Felipe Magno de Almeida > >> >> <felipe.m.alme...@gmail.com> wrote: > >> >> > it is the _perfect_ match IMO. Probably we should ask someone > >> >> > that actually uses Lua about it, instead of guessing. > >> >> > >> >> I'm inclined to agree with raster here. I honestly don't see > >> >> coroutines being a good match here - the API is one thing, and there > >> >> is one other thing to consider that wasn't brought up and that is > >> >> performance - coroutines cannot be JITed and for async stuff we'll be > >> >> jumping across C-Lua border all the time over classic C API rather > >> >> than fast FFI stuff (it will also add a significant amount of new > >> >> runtime on C side, which I would rather avoid) which will abort traces > >> >> and hurt perf. > >> > > >> > Not using coroutines because of performance in lua doesn't seem like a > >> > good reason at all IMO. > >> > >> <snip> > >> > >> Just focusing here on the performance issue. If you think that > >> coroutine are going to be a performance issue for promise, I think > >> this raise two points to discuss. First how good is the JIT on short > >> function, because if we go with events/callbacks, we will endup with > >> very short snippet of code. I don't know for lua jit, but most JIT I > >> know about are bad with short code anyway (It will literray come from > >> C, execute a small amount of code and go back to C). So I don't really > >> see why coroutine will be any worse than events/callbacks in that > >> case. > >> > >> Second point, if you are concerned by performance, then why is it a > >> good idea to switch to an eo object at all. We are now going to pay a > >> way higher price for an API that will be wrapped in C to be convenient > >> and manually binded in all bindings. So where do people still see any > >> win at all into moving to an eo object ? > > > > just speaking of the eo promise performance thing - here is a summary of > > discussions i've had with both jpeg and tasn: > > > > 1. for the vast majority of usage promises are not common and thus not an > > issue > > I am not to sure of this assesment. As we are going for more > asynchronous behavior, we will use it a lot more. I am specifically > worried about our use in the new list view which will likely be a big > user of it. We may be able to reduce pressure by doing groupped > binding, still not sure at all how that can be done with model > intereception (Will require some time before such an optimization can > land). > > 2. performance issues in creating and destroying eo objects are not unique > > to promises, so omptimizing to make them faster will help ALL eo objects. > > How many object will have a life time and a cycle as short as a > promise ? Not many in my opinion. We do try hard to recycle object > everywhere for that reason. Sure, it is nice to optimize and bet that > we can optimize it later if necessary, but still why pay the cost in > the first place ? jobs, timers have such short lifetimes. they always have. in fact part proxy objects will have an ever shorter lifetime and will be more common than promises. so here is my view. let's take the worst case we have. model. with a genlist. how many promise api calls will we make vs other eo api calls - eg move obj, resize, set text, set color, etc. etc. etc. - what percentage are a method call on a promise vs others. let us for now ignore the content of a call and let's just talk about call overhead. let's for now ignore creation/destruction. just calls. ignore cpu time to render and everything else. just the call overhead of an eo call on a promise vs what eina had. what percentage of calls are promise ones during any given second of scrolling around? i argue maybe 1 in 100 is a call on a promise. maybe. on a bad day. more likely 1 in 500. but let's just talk of the worst side - 1% of calls. 1% of calls are slower now because they are eo calls. now lets' throw in all the other cpu time in ACTUALLY doing the work. that has to dwarf the call cost by at least 100 times. the code spent sorting lists, walking through objects to render, doing i/o etc. so my back-of-a-napkin numbers say that 0.01% of our cpu time will be slower... what by maybe 3x? 5x? let's say 10x slower.... so on a bad day 0.1% overhead. that's within error margins. you can't measure it really. and that's imho worst case scenario. in general it'll be far less so like 0.001% or so. maybe. > > 3. we already have the ability to optimize with del intercepts. we could > > actually make a del intercept at the class level (which makes much more > > sense for the following)... we can cache objects. since caching will only be > > effective on objects that don't change a lot from their constructed state to > > their destructed one (promises for example do not change much). so when > > destruction is about to begin... cache the object somewhere, and now we > > need to also extend construction to allow there to be a lookup for a cached > > object. my point here is that we can add caching class by class easily > > enough and all we need is maybe 10-20 cached promise objects floating about > > at most and pick them from the cache each time we need one. chances are > > this will address pretty much all the performance issues. the only other is > > calling methods on a promise via eo is slower but really... how much will > > that really matetr given that 100's of other eo calls will happen as well > > at the same time to handle the result of a promise etc. etc. - it's a > > rounding error of difference at best in the overall performance of efl > > With all the complexity added in going with an eo object, let's just > say, that maybe we will find a way to get performance kinda ok and > maybe find some useful case where eo api does help in some way. So > here is my current proposal on how we can do a promise with eo with > the constraint as outlined by tom (no overriding of the reference > count infrastructure). First example of the api for user : > > Example 1: > > eo_future_use(&destination, efl_file_set(obj, file, key)); > eo_future_then(destination, _then, _cancel, _progress, NULL); > eo_future_cancel(destination); // No barking on NULL > > Example 2: > > eo_future_use(&destination, efl_file_set(obj, file, key)); > eo_ref(destination); > eo_future_then(destination, _then1, _cancel1, _progress1, NULL); > eo_future_then(destination, _then2, _cancel2, _progress2, NULL); > eo_future_use(&chain, eo_future_chain_then(destination, _then_chain, > _cancel_chain, NULL, NULL)); > eo_future_use(&all, eo_future_all(destination, destination1, > destination2, chain)); > eo_future_then(all, _then_all, _cancel_all, _progress_all, NULL); > eo_future_link(obj, all); // We need to register a proper then/cancel > callback to handle linking eo object with promise > eo_unref(destination); > eo_future_cancel(destination); > > Example 3: > > eo_future_then(efl_file_set(obj, file, key), _then, _cancel, NULL, NULL); > > Example 4: > > eo_future_use(&destination, efl_file_set(obj, file, key)); > some->where = eo_ref(destination); > f = eo_future_value_get(some->where); > eo_unref(some->where); is there a reason you called it a future? you want to break it up into promise vs future objects? can i just suggest not bothering? js doesn't bother. it's a promise. just have 1 interface class for the owner to use and another for the "user". if someone uses the wrong api on the obj - well too bad for them. at least it is clear which you should use. this should reduce complexity. so let us then just assume file_set returns a promise like above... why not just do: Example 5: p = efl_file_async_set(obj, file, key); eo_promise_then(p, cb_ok, cb_err, data); that's it? it's almost like example 3 but with a single data ptr to both then and err cb's. so the short version like in example 3: eo_promise_then(efl_file_async_set(obj, file, key), cb_ok, cb_err, NULL); if i do this i can no longer cancel the action as i lost the promise object handle. personally i don't like/see the point of multiple then/err cb's, but ok, if you want to use multiple ones on the same promise (beyond the first one) you HAVE to ref the promise: p = efl_file_async_set(obj, file, key); eo_ref(p); eo_promise_then(p, cb1_ok, cb1_err, data); eo_promise_then(p, cb2_ok, cb2_err, data); eo_promise_then(p, cb3_ok, cb3_err, data); eo_unref(p); this should be exceedingly rare (multiple then/else's). > On a returned promise, you can use as many time as you want > eo_promise_use and eo_ref, but any other function call will trigger > the fullfillment of that said promise. The trick here is in > eo_future_use, which will be a wrapper on top of eo_wref_add. As > eo_wref_add is an eo API that can be overriden and we can change the > life cycle of the promise that way. Of course, now all promise need to > actually be an Efl.Loop_User as they depend on the return on the main > loop to notice that no call has been made on them and that they are > unused. This means that evas will depend on ecore. > > On the other side the provider of a future will do : ok. so you do want to split. as above. i suggest not splitting. js does not. i don't really see a point in splitting within efl. with other langs that split future vs promise like c++, then sure - bind manually there as appropriate. :) > p = eo_promise_add(parent); > f = eo_promise_future_get(p); > eo_promise_link(obj, p); // due to restriction on future API, we can > not make any call in the provider on the future, so we need a > promise_link also > eo_override(f, EO_OVERRIDE_OPS(replace_eo_future_cancel)); > eo_promise_value_set(p, stuff, stuff_free_cb); > return f; > > We will use Tom suggested solution by providing one object that is a > promise and future at the same time, but Eo_Promise and Eo_Future type > will be opaque, so we will get proper type checking in C. bingo. i'm with tom here. one object, but 2 interfaces on it. the promise class on the promise itself (for the owner) then a future class that inherits the promise class and adds future api's for the "user" > As their is no point on using eo callback infrastructure at all, we > will just reuse the same function prototype for consistency, but won't well there is use - for progress events. > use the callback infrastructure. This way we will have consistency and > people will just have to do some cast as they do with every other > events. The event structure for chained then (that return a new > promise), will contain the value, the source future and the > destination promise, while the the non chained one will just contain > the future and the value. > > Since we can't make any change to the life cycle of an eo object that > use eo_ref/unref/del, the rule will be that a future can't be > fullfilled until all reference have been removed. This means that you > should not use eo_ref/eo_unref and store a future pointer anywhere > else than on the stack and temporarily. If you want to keep it around, > eo_future_use is the only way. It also means that eo_del make no sense i don't see why youy need the eo_future_use... example 3. :) and as per my example - if you want multiple then's - take an extra ref, add them all, then unref. :) > and its behavior to kill the parent will be a problem. As the future > and the promise are the same object, they can only have one parent. So > eo_parent_set will be disabled, except on constructor/destructor and > internal use. In the same sense, eo_del will be trowing a warning and > be render useless as it will be confusing to have it. i think this is bringing up. what happens to a promise when it gits zero refcount AND it is not finished yet? my view is - it should be canceled then implicitly. that means you actually don't need a cancel call - you just need to be able to delete the object. in c and c++ as they are explicitly managed, this will do. no need to cancel. for gc'd languages you then do need an explicit cancel. now should we leave this to bindings to implement specially and just drop a cancel from the api or... still keep an explicit cancel? > This is pretty much the proposal I can sanely push on top of Eo (For a > certain definition of sane). I still see no win at all into doing it > (and I do see a lot of cost into doing it), but whatever I have raised > my opinion and nobody really care, so... win -> no duplicate ref/unref calls. auto deletion by parent if set as child (or as data key), existing use with weak refs. re-use of eoid, runtime type etc. etc. safety checking. no duplicating this in efl. -- ------------- Codito, ergo sum - "I code, therefore I am" -------------- The Rasterman (Carsten Haitzler) ras...@rasterman.com ------------------------------------------------------------------------------ Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San Francisco, CA to explore cutting-edge tech and listen to tech luminaries present their vision of the future. This family event has something for everyone, including kids. Get more information and register today. http://sdm.link/attshape _______________________________________________ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel