github.com/cloudwego/frugal@v0.1.15/pretouch.go (about) 1 /* 2 * Copyright 2022 ByteDance Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package frugal 18 19 import ( 20 `reflect` 21 `sync` 22 23 `github.com/cloudwego/frugal/internal/binary/decoder` 24 `github.com/cloudwego/frugal/internal/binary/encoder` 25 `github.com/cloudwego/frugal/internal/opts` 26 `github.com/cloudwego/frugal/internal/rt` 27 `github.com/oleiade/lane` 28 ) 29 30 type _Ty struct { 31 d int 32 ty *rt.GoType 33 } 34 35 var ( 36 typool sync.Pool 37 ) 38 39 func newty(ty *rt.GoType, d int) *_Ty { 40 if v := typool.Get(); v == nil { 41 return &_Ty { d, ty } 42 } else { 43 r := v.(*_Ty) 44 r.d, r.ty = d, ty 45 return r 46 } 47 } 48 49 // Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in 50 // order to reduce the first-hit latency. 51 func Pretouch(vt reflect.Type, options ...Option) error { 52 d := 0 53 o := opts.GetDefaultOptions() 54 55 /* apply all the options */ 56 for _, fn := range options { 57 fn(&o) 58 } 59 60 /* unpack the type */ 61 v := make(map[*rt.GoType]bool) 62 t := rt.Dereference(rt.UnpackType(vt)) 63 64 /* add the root type */ 65 q := lane.NewQueue() 66 q.Enqueue(newty(t, 1)) 67 68 /* BFS the type tree */ 69 for !q.Empty() { 70 ty := q.Pop().(*_Ty) 71 tv, err := decoder.Pretouch(ty.ty, o) 72 73 /* also pretouch the encoder */ 74 if err == nil { 75 err = encoder.Pretouch(ty.ty, o) 76 } 77 78 /* mark the type as been visited */ 79 d, v[ty.ty] = ty.d, true 80 typool.Put(ty) 81 82 /* check for errors */ 83 if err != nil { 84 return err 85 } 86 87 /* check for cutoff conditions */ 88 if !o.CanPretouch(d) { 89 continue 90 } 91 92 /* add all the not visited sub-types */ 93 for s := range tv { 94 if t = rt.UnpackType(s); !v[t] { 95 q.Enqueue(newty(t, d + 1)) 96 } 97 } 98 } 99 100 /* completed with no errors */ 101 return nil 102 }