Netty Object Pool Usage and recycling

Source: Internet
Author: User

1. Recycler Object Pooling recycler The implementation of the abstract class is very simple, there are only three methods: Get object: Recycler:get () Recycled object: Recycler:recycle () object created: Recycler:newobject () Newo  Bject is an abstract method that needs to be implemented by the implementation class itself to create the object.  The purpose of the Recycler object pool is to reuse objects created by the same thread as much as possible, and in order to avoid consuming too much memory, the objects are recycled at a certain scale (as explained in the default 1/7 rule note), and objects that are not reclaimed are handled by the JVM garbage collection mechanism. The data storage structure for the Recycler object pool is as follows:

The same thread that created the stack reclaims the object when it is stored in the elements array (Pushnow method recycles), and if the same thread is not placed in the Weakorderqueue queue, when a Get object is required and the stack is empty, All elements of the Weakorderqueue collection are transferred to the elements array of the stack according to certain rules.

2. Acquisition of objects

The first is to determine if an object exists in the pool, if it is taken first from the local thread stack, and if the stack is empty, then all objects in the queue collection of other threads are transferred to the local thread stack (1/7 rules) according to certain rules. The object is then fetched from the stack and returned.
If the object does not exist in the pool, the object is created and returned. The relevant code is as follows:
    Public final T get () {if (Maxcapacityperthread = = 0) {return NewObject ((handle<t>) Noop_hand        LE);        } stack<t> Stack = Threadlocal.get (); Defaulthandle<t> handle = Stack.pop ();//First determine if an object exists in the pool, if it is taken precedence from the local thread stack, if the stack is empty,        Then all objects in the queue collection of other threads are transferred to the local thread stack (1/7 rules) according to certain rules, and then the object is fetched from the stack and returned.            if (handle = = NULL) {//If the object does not exist in the pool, the object is created and returned.            handle = Stack.newhandle ();        Handle.value = NewObject (handle);        }//System.out.println (Threadlocal.getclass () + "=" + stack + "=" + handle);    Return (T) Handle.value;        } defaulthandle<t> Pop () {int size = This.size;                if (size = = 0) {First determine if an object exists in the pool//if (!scavenge ()) {//If the stack is empty, then all objects of the other thread's queue collection are transferred to the local thread stack (1/7 rules) according to certain rules            return null;        } size = This.size;        } size--;        Defaulthandle ret = elements[size];        Elements[size] = null; if (ret.lastRecycledid! = Ret.recycleid) {throw new IllegalStateException ("Recycled multiple times");        } Ret.recycleid = 0;        Ret.lastrecycledid = 0;        this.size = size;    return ret; } Boolean scavenge () {//Continue an existing scavenge, if any if (Scavengesome ()) {Retu        RN true;        }//Reset our scavenge cursor prev = NULL;        cursor = head;    return false;        } Boolean Scavengesome () {Weakorderqueue prev;        Weakorderqueue cursor = this.cursor;            if (cursor = = null) {prev = null;            cursor = head;            if (cursor = = NULL) {return false;        }} else {prev = This.prev;        } Boolean success = FALSE;                do {if (Cursor.transfer (this)) {//will transfer all objects of the other thread's queue collection to the local thread stack (1/7 rule) according to certain Rules success = true;            Break } Weakorderqueue Next = CursOr.next;                if (cursor.owner.get () = = null) {//If the thread associated with the ' queue is ' gone, unlink it, after                Performing a volatile read to confirm there are no data left to collect.                We never unlink the first queue, as we don ' t want to synchronize on updating the head. if (Cursor.hasfinaldata ()) {for (;;)                        {if (Cursor.transfer (this)) {success = true;                        } else {break;                }}} if (prev! = null) {Prev.setnext (next);            }} else {prev = cursor;        } cursor = next;        } while (cursor! = null &&!success);//traverse all weakorderqueue This.prev = prev;        This.cursor = cursor;    return success; } Boolean Transfer (Stack<?>        DST) {Link head = This.head.link;        if (head = = null) {return false;            } if (Head.readindex = = link_capacity) {if (Head.next = = null) {return false;        } This.head.link = head = Head.next;        } final int srcstart = Head.readindex;        int srcend = Head.get ();        Final int srcsize = Srcend-srcstart;        if (srcsize = = 0) {return false;        } final int dstsize = dst.size;        Final int expectedcapacity = dstsize + srcsize; if (Expectedcapacity > Dst.elements.length) {final int actualcapacity = dst.increasecapacity (Expectedcapaci            TY);        srcend = min (Srcstart + actualcapacity-dstsize, srcend);            } if (Srcstart! = srcend) {final defaulthandle[] srcelems = head.elements;            Final defaulthandle[] Dstelems = dst.elements;            int newdstsize = dstsize; for (int i = Srcstart; I <Srcend;                i++) {//To save all elements of the queue in accordance with (1/7 rules) to the stack defaulthandle element = srcelems[i];                if (Element.recycleid = = 0) {Element.recycleid = Element.lastrecycledid; } else if (Element.recycleid! = Element.lastrecycledid) {throw new IllegalStateException ("Recycled ALR                Eady ");                } Srcelems[i] = null;                    if (Dst.drophandle (Element)) {//Drop the object.                Continue                } element.stack = DST;            dstelems[newdstsize++] = element; } if (srcend = = Link_capacity && Head.next! = null) {//ADD capacity back as the LINK I                S GCed.                This.head.reclaimSpace (link_capacity);            This.head.link = Head.next;            } Head.readindex = Srcend;            if (dst.size = = Newdstsize) {return false;            }Dst.size = newdstsize;        return true;            } else {//the destination stack is full already.        return false;         }    }
View Code

3. Retrieving objects

If the currently reclaimed thread is the original thread (the thread that created the object), then call Pushnow if the capacity of the stack is exceeded (default 4*1024) or the 1/7 rule is drop (released by the JVM recycle)
If the currently reclaimed thread is not the original thread, then call Pushlater if the current thread is the first to reclaim the original thread's object. Weakorderqueue that need to be created by the current thread (the weakorderqueue of the original thread's stack object can be associated with another thread). If the queue is created successfully, the queue is entered, and the failure (queue number greater than maxdelayedqueues) discards the object (freed by the JVM Recycle) Note: 1) The object is reclaimed by the weakorderqueue of the local thread, The reason for doing this is to avoid concurrency (races competition), and not every object has an object recycle pool to reclaim, if exceeding the maximum capacity limit is discarded, and the local thread stack takes 1/8 rule measures, and transfers the object of the GEO thread queue to the local thread stack also takes 1/ 8 Rule measures 2) 1/7 rule means that each 7 object only leaves 1 recovery, the remainder is discarded, such as 1-7 recycled 1, 8-15 recycled 2 ...
The associated code for the recycled object is as follows:
     (1)                Defaulthandle class @Override public void Recycle (Object object) {if (Object! = value) {            throw new IllegalArgumentException ("object does not belong to handle");        } stack.push (this); } (2) Stack class void push (Defaulthandle<?> item) {Thread CurrentThread = Thread.CurrentThread (        ); if (threadref.get () = = CurrentThread) {//The current thread is the thread of the belongs to the Stack, we can t            Ry to push the object now.        Pushnow (item); } else {//The current thread isn't the one that belongs to the Stack//(or the Thread that Belon            Ged to the Stack is collected already), we need to signal that the push//happens later.        Pushlater (item, CurrentThread); } (3) private void Pushnow (defaulthandle<?> item) {if ((Item.recycleid | item.lastrecycledid)! = 0) {throw new IlleGalstateexception ("recycled already");            } Item.recycleid = Item.lastrecycledid = own_thread_id;            int size = This.size; if (size >= maxcapacity | | drophandle (item)) {//In order to avoid the collection of objects too much, take up too much memory, took 1/8 rule measures, Parameters adjustable/hit the maximum C                Apacity or should drop-drop the possibly youngest object.            Return if (size = = elements.length) {elements = arrays.copyof (elements, min (size << 1, Maxcapa            City));            } Elements[size] = Item;        this.size = size + 1; } (4) private void Pushlater (defaulthandle<?> item, thread thread) {//We don ' t want to ha ve a ref to the queue as the value of our weak map//So we null it out;            To ensure there is no races with restoring it later//we impose a memory ordering here (No-op on x86) Map<stack<?&gt, weakorderqueue> delayedrecycled = Delayed_recyclEd.get ();            Weakorderqueue queue = Delayedrecycled.get (this);                    if (queue = = null) {if (Delayedrecycled.size () >= maxdelayedqueues) {The number of offsite queues in the Recycle pool is limited and the capacity of each queue is limited ADD a dummy queue so we know we should drop the object Delayedrecycled.put (this, Weakorde                    Rqueue.dummy);                Return                }//Check If we already reached the maximum number of delayed queues and if we can allocate at all.                    if (queue = Weakorderqueue.allocate (this, thread)) = = null) {//Drop object                Return            } delayedrecycled.put (this, queue);            } else if (queue = = Weakorderqueue.dummy) {//Drop object return;        } queue.add (item);            } (5) Weakorderqueue class void Add (Defaulthandle<?> handle) {Handle.lastrecycledid = ID; Link tail = tHis.tail;            int writeindex;                    if ((Writeindex = Tail.get ()) = = link_capacity) {if (!head.reservespace (link_capacity)) {                    Drop it.                Return                }//We allocate a link so reserve the space this.tail = tail = Tail.next = new Link ();            Writeindex = Tail.get ();            } Tail.elements[writeindex] = handle;            Handle.stack = null;            We lazy set to ensure this setting stack to null appears before we unnull it in the owning thread; This also means we guarantee visibility of a element in the the queue if we see the index updated Tail.lazyset (        Writeindex + 1);  }
View Code

Netty Object Pool Usage and recycling

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.