By the way, an advantage of this feature is that you can easily put a condition on a breakpoint in gdb by using the "pointer" of the previous run. It works on some condition, like the scenario must be the same and you have to hope that there is not too much timers in the background. But if you have these conditions (in elementary_tests, it is easy :-)), you can do that. For example, if someone calls eo_data_get on an object after it has been removed, and you want to know when it has been removed, just break on eo_del with the object id and run it.
I know, it's a dumb example, but the concept is interesting. On 04/24/2013 11:24 AM, Carsten Haitzler (The Rasterman) wrote: > On Wed, 24 Apr 2013 16:41:49 +0900 Carsten Haitzler (The Rasterman) > <ras...@rasterman.com> said: > > oh.. and i probably should... edit this for.. typos... > >> On Wed, 24 Apr 2013 16:19:50 +0900 Carsten Haitzler (The Rasterman) >> <ras...@rasterman.com> said: >> >>> On Wed, 24 Apr 2013 08:27:01 +0300 "daniel.za...@samsung.com" >>> <daniel.za...@samsung.com> said: >>> >>>> Hi Jeremy, >>>> >>>> On 04/24/2013 12:00 AM, Jérémy Zurcher wrote: >>>>> Hi, >>>>> I did enjoy it! >>>>> even if I'wd prefered a pointer then ID_TABLE macro, >>>>> just a matter of taste I suppose ;) >>>> I did it because it was too much with the >>>> _eo_ids_tables[table_id][int_table_id], I mean not readable. But I am >>>> sure it can be written better ;-) >>>>> a question, >>>>> what did you based your 32 and 64 bits decomposition on? >>>>> equations, benchmarks, moon's CxA ? >>>> no equations. >>>> Well let's say that for the moment, it is not enough optimized. The most >>>> important was to not have big internal tables and to have enough bits >>>> for the generation to be efficient. >>>> For 64 bits, well, hum, I don't know what I thought to put 20 bits for a >>>> table size. Raster already spanked me for that ;-) >>>> >>>> Concerning optimization, in 32 bits, I think we could increase the >>>> generation #bits and reduce the tables #bits because we will never reach >>>> 4M of objects. I never saw more than 5K objects. So we could steal 2 >>>> bits from there (we would have max. 1M objects) for the generation and >>>> so increase the stability. >>> really? no more than 5k objects? interesting. i was maybe expecting 20-40k. >>> and yes - i did have to spank a bit on the table sizes on 64bit. i adjusted >>> things so we use 30bits for generation counter on 64bit and thus 34bits for >>> obj id. since the code splits object lookup into a 3 level table (master >>> table array, inter table and then child table),i allocated 11 bits for >>> master and inter tables and 12 for child table. this means our "base cost" >>> for our first 4k objects is 16k+16k+65k. for every extra 4k object we spend >>> another 65k. >>> >>> now slight catch... i ALSO changed the table allocation to use mmap() of >>> anonymous memory. why? separate memory regions for storign the table away >>> from memory managed by libc (malloc etc.). this means the "chance" of >>> someone finding the memory areas by ccidentally overrunning an existing >>> allocation (walk off the end or beginning of an allocation), OR by >>> accidentally accessing a previously freed pointer that has ben recycled... >>> is basically almost 0. to talk off the end means they will probably have to >>> walk of a valid memry mapping into unmapped space and then segv anyway, so >>> chances of table corruption now are very very very small, UNLESS that >>> corruption problem is inside eo_id code. >>> >>> now to the catch... to do this i made it mmap and that means it mmapes in >>> units of 4k pages.. so adding in accounting overhead, we actually cost 20k >>> +20k +68k for the base and each new set of 4k objects costs another 68k (on >>> 64bit). these costs on 32bit are moe like 4k+4k+8k for the first 1024 >>> objects and an extra 8k for each 1024 objects. i'm actually thinking i >>> should re-jig 32bit. >>> >>> so we divide the obj id into 3 tables (master.inter.sub): >>> >>> 32bit: 8.4.10 = 22bits (max 4 million objects) = 4k+4k+8k (first 1024) >>> 64bit: 11.11.12 = 34bits (max 16 billion objects) = 20k+20k+68k (first 4096) >>> >>> i think i should adjust 32bit to be maybe 5.5.12 (this brings our costs to >>> 4k+4k+20k for the first 4096 objects, and an extra 20k for the next 4096)... >>> since object COUNTs will be the same on 32 and 64bit i think this works well >>> as given "no more than 5k" for i guess large complex apps (lets pad this up >>> to 8k) we pay the base cost plus an extra leaf table ... on a heavy app (20 >>> +20 +68+68 on 64bit or 4+4+20+20 on 32bit - after rejing (before rejig 4+4 >>> +(8*8) so we go from 72k to 48k - but if we assume small # of objects we >>> are better off adjusting to 6.7.9 so our base cost is 4k+4k+4k for 512 and >>> 4k for each 512 which is a lower base cost of 12k and then for 8k objects >>> the same as now >>> - 72k). >>> >>> so the question is.. optimize for 4-8k objects and thus lower our cost for >>> that from 72k to 48k... or optimize for small # of objetcs, which means >>> adjusting the current setup anyway to 6.7.9... for small object counts our >>> base cost goes from 28k to 12k. i think i lean to optimizing for 4-8k >>> objects... because over time i suspect we will use eo more and more and make >>> more objects... a quick look at counting # of objects daniel is right. i'm >>> seeing things like 2-4k for elementary_test (even if i push it) and e17 too >>> (with some pushing)... they break the 4k mark after some pushing ... so i >>> suspect this will be common enough. >>> >>> (sorry - lots of thinking out aloud here to give reasoning for wanting to >>> change the 32bit obj id allocation division). >>> >>> so people know... what the obj id vs generation count is... the id is the >>> actoual object identifier number. each object has a unique one. it is >>> literally its entry in a table (0, 1, 2, 3... N). this table has a fixed >>> capacity per architecture (22bits or 4m objects on 32bit, and 34bits or 16b >>> objects on 64bit). objects may, in the c api appear to return a pointer, but >>> stuffed into this pointer is now the id... and all acess is done by looking >>> UP this id in this multi-level table and safely checking the appropriate >>> slot in the table has a valid (non-null) pointer finally pointing to an >>> actual object struct. every table entry is EITHER null OR valid. it can >>> never be non-null and non-valid. on creation of every object it gets a >>> table entry. on freeing (deletion) its entry is released and nulled out. at >>> least that is the theory ASSUMING all object creation points go through >>> this table path as well as deletion paths. if they don't - we have a bug in >>> eo and that must be fixed. this also assumes that efl code that has access >>> to the obj ptr itself is "much more trusted" than "3rd party code" so efl >>> wont accidentally free this obj pointer and thus not go through the >>> deletion path that fixes up the table. >>> >>> all of this work is a result of observing developer usage of efl over years >>> and finding that there is gnerally a problem in "pointer/memory management" >>> inside apps and that spills over into efl in the form of accessing invalid >>> (deleted) evas objects or deleted timers etc. etc., then using up efl >>> developer time hunting down a bug in an application just because a crash >>> happens inside some object sanity check (eg magic number checking and the >>> magic number is store in the obj struct and if the ptr points to >>> inaccessible memory... we segv). this table indirection does add overhead. >>> we know that. it is a "necessary evil" to address "application developer >>> concerns" and to cut back on time chasing irrelevant bugs. this is WHY eo >>> has this odd eo_do() thing that you can pack MULTIPLE methods/operations >>> for a single object into the args... it means we pay this table lookup cost >>> only ONCE for several method calls - thus ammortising the cost across >>> multiple "old school" method and thus hopefully "breaking even" once >>> everything is using this eo api and batching methods nicely. >>> >>> so what are the other 10 or 30 bits in the pointer - now become id handle - >>> used for? well it's a sanity check. eveyr time any object is created, a >>> gneration counter ticks over. it loops/repeats every N values (1024 on >>> 32bit, 1billion or so on 64bit). this generation count is no part of the id >>> entry in he table but it IS packed into the pointer returned and so when we >>> do a lookup we strip off the generation count (10 or 30 bits) and then use >>> the id section to do the lookup we then COMPARE the generation count ALSO >>> stored in the table next to the entry to the generation count we stripped >>> out. i they do not match... it is an invalid access. why? we are recycling >>> a table entry. likely an object was deleted, table entry freed, then >>> recycled, and we try access again with an old handle frm the outside. it >>> *IS* possible, in theory, for the generation count to accidentally match (1 >>> in 1024 chance on 32bit and 1 in a billion chance on 64bit). then the >>> object dereference goes through and our code calls methods on perhaps the >>> wrong object. this would happen if malloc recycled a pointer address too, >>> so we are no worse off really. we STILL check on object class types (ie the >>> method id has to exist for that object class and since method ides are >>> unique globally and not class-relative) we still have a lot of safety here. >>> no crashing inside efl still, but maybe misbehaviour... but our CHANCES of >>> this should have been drastically reduced... ESPECIALLY on 64bit >>> architectures. rememebr this applies ONLY to invalid object references that >>> ALSO have been recycled AND whose generation id match. >>> >>> now... we still hve a few things to do here to make safety even more robust. >>> >>> 1. don't recycle id's so aggressively. have a "zombie pool" of id's with a >>> high and low watermark. this means an object id is not going to be recycled >>> "soon" and thus he most common accesses like del() then use() a few lines >>> later or while walking back up the stack to parent callers, are caught as >>> the id itself simply is forcibly invalud (nulled out) and remains so for a >>> while as its in the zombie trash pool. maybe have 1024 or 2048 zombie >>> entries. >>> >>> 2. obj ptr and gneration cunt are in 2 separate arrays - thus not continuous >>> in memory. ue to cacheline fetches these should be merged so they are >>> adjacent so we pay only 1 cacheline fetch delay if not already in cache >>> instead of 2. >>> >>> 3. checksum each table row. we consunme 1 void * size for the pointer in >>> each row AND 1 void * for the generation count. even if gneration count is >>> only 10bit or 30bit, due to alignment and doing #2 above we will spend a >>> void * for alignment reasons. we SHOULD pack a checksum into the generation >>> count region. if a table entry should now be struct { void *ptr; unitptr_t >>> checksum:22; unitptr_t generation:10; } or... similar for 64bit. this >>> checksum should just be a ead simple checksum of pointer+generation count >>> elements (maybe a simple xor or so) to try detect if perhaps someone did >>> accidentally find out table and scribble over parts of it. we chould >>> compare checksum on each access and generate it on each write to that table >>> row. this doesn't help with our master and inter table though which are >>> just raw pointers... no generation count in there. perhaps we should >>> checksum all the pointers in each of these tables too... or checksum >>> sections/ranges. this might be lean enough to ship with production >>> releases, BUT... might not be... we have to see, but it is an option for >>> debug releases (during development) for sanity checks. >>> >>> 4. since we forcibly took control over our table allocation... and it is >>> always a multiple of pages... we can use mprotect to remove write access >>> UNLESS eo_id is modifying that table. this is expensive as every change has >>> to go into kernel space and change pagetable information, so it wouln't be >>> something we do in production release code, BUT debug code could definitely >>> enable this as a way of catching table corruption instantly via a segv. :) >>> >>> 5. we currently nver free tables once they are empty. we just keep a bunch >>> of empty tables arund to be re-used. we need to of course keep a zombie >>> table pool around of maybe a few tables.. again - high/low watermark, and >>> then release when we ee we are not going to re-use our spare tables any >>> time soon. given current object counts in things like elementary_test and >>> enlightenmnt, we at most will find ourselves with only 1 spare empty leafe >>> table at the moment... so this is not high priority. >> oh... 6. the trash queue is managed by eina.. in malloced memory - this needs >> to move into probably fixed size buffers inside the table leaf struct so this >> only lives in custom mmaped memory owned by eo_id. >> >>> someone... should... blog... about... this... :) i have to say.. the eo id >>> thing is rather cool and unique... you don't see this kind of thing many >>> places in c or c++ toolkits like efl (or gtk+ or qt) and it really can hlp >>> with robustness a LOT. this is all part of some major groundwork overhauling >>> these guys in israel have done and i have to say... it has been done very >>> well, considering how deep in the stack this lives and how many things it >>> affects (not just eo_id but eo in general). so kudos to the team! >>> >>>>> regards >>>>> Jérémy >>>>> >>>>> >>>>> On Tuesday 23 April 2013 09:59, daniel.za...@samsung.com wrote : >>>>>> Hi all, >>>>>> >>>>>> This morning, I pushed the Eo pointers indirection feature. As I wrote >>>>>> in the log, it is not API break. It will help us against bad usage of >>>>>> Eo objects pointers, e.g access an object that has already been >>>>>> deleted... So if you see that the Eo* that you receive from eo_add >>>>>> doesn't seem like a "normal" pointer, but like 0x1000401, just know it >>>>>> is normal. If you need a better explanation on the mechanism used, >>>>>> check the file eo_ptr_indirection.c in src/lib/eo. >>>>>> >>>>>> If you see error messages "obj_id ... is not pointing to a valid >>>>>> object. Maybe it has already been freed.", check your Eo objects or >>>>>> contact me. >>>>>> >>>>>> Enjoy >>>>>> JackDanielZ >>>>>> >>>>>> ------------------------------------------------------------------------------ >>>>>> Try New Relic Now & We'll Send You this Cool Shirt >>>>>> New Relic is the only SaaS-based application performance monitoring >>>>>> service that delivers powerful full stack analytics. Optimize and >>>>>> monitor your browser, app, & servers with just a few lines of code. Try >>>>>> New Relic and get this awesome Nerd Life shirt! >>>>>> http://p.sf.net/sfu/newrelic_d2d_apr >>>>>> _______________________________________________ enlightenment-devel >>>>>> mailing list enlightenment-devel@lists.sourceforge.net >>>>>> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel >>>>> ------------------------------------------------------------------------------ >>>>> Try New Relic Now & We'll Send You this Cool Shirt >>>>> New Relic is the only SaaS-based application performance monitoring >>>>> service that delivers powerful full stack analytics. Optimize and >>>>> monitor your browser, app, & servers with just a few lines of code. Try >>>>> New Relic and get this awesome Nerd Life shirt! >>>>> http://p.sf.net/sfu/newrelic_d2d_apr >>>>> _______________________________________________ enlightenment-devel >>>>> mailing list enlightenment-devel@lists.sourceforge.net >>>>> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel >>>> >>>> >>>> ------------------------------------------------------------------------------ >>>> Try New Relic Now & We'll Send You this Cool Shirt >>>> New Relic is the only SaaS-based application performance monitoring >>>> service that delivers powerful full stack analytics. Optimize and monitor >>>> your browser, app, & servers with just a few lines of code. Try New Relic >>>> and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr >>>> _______________________________________________ >>>> enlightenment-devel mailing list >>>> enlightenment-devel@lists.sourceforge.net >>>> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel >>> >>> -- >>> ------------- Codito, ergo sum - "I code, therefore I am" -------------- >>> The Rasterman (Carsten Haitzler) ras...@rasterman.com >>> >>> >>> ------------------------------------------------------------------------------ >>> Try New Relic Now & We'll Send You this Cool Shirt >>> New Relic is the only SaaS-based application performance monitoring service >>> that delivers powerful full stack analytics. Optimize and monitor your >>> browser, app, & servers with just a few lines of code. Try New Relic >>> and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr >>> _______________________________________________ >>> enlightenment-devel mailing list >>> enlightenment-devel@lists.sourceforge.net >>> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel >> >> -- >> ------------- Codito, ergo sum - "I code, therefore I am" -------------- >> The Rasterman (Carsten Haitzler) ras...@rasterman.com >> >> >> ------------------------------------------------------------------------------ >> Try New Relic Now & We'll Send You this Cool Shirt >> New Relic is the only SaaS-based application performance monitoring service >> that delivers powerful full stack analytics. Optimize and monitor your >> browser, app, & servers with just a few lines of code. Try New Relic >> and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr >> _______________________________________________ >> enlightenment-devel mailing list >> enlightenment-devel@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel > ------------------------------------------------------------------------------ Try New Relic Now & We'll Send You this Cool Shirt New Relic is the only SaaS-based application performance monitoring service that delivers powerful full stack analytics. Optimize and monitor your browser, app, & servers with just a few lines of code. Try New Relic and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr _______________________________________________ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel