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

Reply via email to