github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/ekalog/entry_pool_private.go (about) 1 // Copyright © 2020-2021. All rights reserved. 2 // Author: Ilya Stroy. 3 // Contacts: iyuryevich@pm.me, https://github.com/qioalice 4 // License: https://opensource.org/licenses/MIT 5 6 package ekalog 7 8 import ( 9 "runtime" 10 "sync" 11 "sync/atomic" 12 13 "github.com/qioalice/ekago/v3/internal/ekaletter" 14 ) 15 16 type ( 17 // EntryPoolStat is an internal struct that allows you to inspect 18 // how Logger's Entry pool utilized and it's current state. 19 EntryPoolStat struct { 20 21 // AllocCalls is how much absolutely new Entry objects 22 // with included ekaletter.LetterField are created using new RAM slice. 23 AllocCalls uint64 24 25 // NewCalls is how much attempts both of to allocate a new Entry objects 26 // or pop an one from Entry's pool were here. 27 // 28 // Once again. 29 // It contains AllocCalls + popping an oldest (and prepared to reuse) 30 // Entry objects from its pool. 31 NewCalls uint64 32 33 // ReleaseCalls is how much Entry objects were returned to its pool 34 // and prepared for being reused. 35 ReleaseCalls uint64 36 } 37 ) 38 39 // EPS returns an EntryPoolStat object that contains an info about utilizing 40 // Logger's Entry pool. Using that info you can figure out how often 41 // a new Logger's Entry objects are created and how often the oldest ones 42 // are reused. 43 // 44 // In 99% cases you don't need to know that stat, 45 // and you should not to worry about that. 46 func EPS() EntryPoolStat { 47 return EntryPoolStat{ 48 AllocCalls: atomic.LoadUint64(&eps.AllocCalls), 49 NewCalls: atomic.LoadUint64(&eps.NewCalls), 50 ReleaseCalls: atomic.LoadUint64(&eps.ReleaseCalls), 51 } 52 } 53 54 var ( 55 // entryPool is the pool of Entry (with allocated ekaletter.Letter) objects 56 // for being reused. 57 entryPool sync.Pool 58 59 // eps contains current state of Entry's pool utilizing, 60 // and its copy is returned by EPS() function. 61 eps EntryPoolStat 62 ) 63 64 // allocEntry creates a new Entry object, creates a new ekaletter.Letter object inside, 65 // performs base initialization and returns it. 66 func allocEntry() any { 67 68 e := new(Entry) 69 e.LogLetter = new(ekaletter.Letter) 70 e.LogLetter.Messages = make([]ekaletter.LetterMessage, 0, 1) 71 72 runtime.SetFinalizer(e, releaseEntryForFinalizer) 73 e.needSetFinalizer = false 74 75 // SystemFields is used for saving Entry's meta data. 76 // https://github.com/qioalice/ekago/internal/letter/letter.go 77 78 // TODO: Is there any meta info we have to save to the SystemFields? 79 // TODO: Is there something we need to save to e.LogLetter.something? 80 81 atomic.AddUint64(&eps.AllocCalls, 1) 82 return e 83 } 84 85 // acquireEntry returns a new *Entry object from the Entry's pool or newly instantiated. 86 func acquireEntry() *Entry { 87 atomic.AddUint64(&eps.NewCalls, 1) 88 return entryPool.Get().(*Entry).prepare() 89 } 90 91 // releaseEntry returns Entry to the Entry's pool for being reused in the future 92 // and that Entry could be obtained later using acquireEntry(). 93 func releaseEntry(e *Entry) { 94 atomic.AddUint64(&eps.ReleaseCalls, 1) 95 entryPool.Put(e.cleanup()) 96 } 97 98 // releaseEntryForFinalizer is a callback for runtime.SetFinalizer() 99 // that allows to return an Entry to its pool if it's gone out of scope 100 // without automatic returning to its pool by any Logger's finisher. 101 func releaseEntryForFinalizer(e *Entry) { 102 e.needSetFinalizer = true 103 releaseEntry(e) 104 }