s := []byte("")
fmt.Println(cap(s)) //32
but
s := []byte("")
fmt.Println(cap(s)) //0
fmt.Println(s)
Is the compiler does some optimizations?
s := []byte("")
fmt.Println(cap(s)) //32
but
s := []byte("")
fmt.Println(cap(s)) //0
fmt.Println(s)
Is the compiler does some optimizations?
this phenomenon is indeed caused by compiler optimization, and we can find some evidence from the source code.
137995 0000000000483200 <main.main>:
138009 48323b: 0f 11 44 24 08 movups %xmm0,0x8(%rsp)
138010 483240: e8 bb a4 fb ff callq 43d700 <runtime.stringtoslicebyte>
138011 483245: 48 8b 44 24 20 mov 0x20(%rsp),%rax
138012 48324a: 48 8b 4c 24 28 mov 0x28(%rsp),%rcx
We disassemble the program. As shown above, for statements like s: = [] byte (""), the compiler generates a stringtoslicebyte function for us to convert from string to slice. This function is defined in:
146 func stringtoslicebyte(buf *tmpBuf, s string) []byte {
147 var b []byte
148 if buf != nil && len(s) <= len(buf) {
149 *buf = tmpBuf{}
150 b = buf[:len(s)]
151 } else {
152 b = rawbyteslice(len(s))
153 }
154 copy(b, s)
155 return b
156 }
"runtime/string.go" 443 lines --22%--
tmpBuf is defined as an array of length 32.
9 // The constant is known to the compiler.
10 // There is no fundamental theory behind this number.
11 const tmpStringBufSize = 32
12
13 type tmpBuf [tmpStringBufSize]byte
14
when stringtoslicebyte takes the first branch, it allocates memory from the stack. If allocated from the stack, it allocates an array of length 32, which is a dead value agreed with the compiler.
when stringtoslicebyte takes the second branch, memory is allocated from the heap, and if allocated from the heap, it is allocated based on the actual length of the string.
255 // rawbyteslice allocates a new byte slice. The byte slice is not zeroed.
256 func rawbyteslice(size int) (b []byte) {
257 cap := roundupsize(uintptr(size))
258 p := mallocgc(cap, nil, false)
259 if cap != uintptr(size) {
260 memclrNoHeapPointers(add(p, uintptr(size)), cap-uintptr(size))
261 }
262
263 *(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)}
264 return
265 }
"runtime/string.go" 443 lines --47%--
We then search the source code of the compiler to find the generation logic of stringtoslicebyte.
1635 case OSTRARRAYBYTE:
1636 a := nodnil()
1637
1638 if n.Esc == EscNone {
1639 // Create temporary buffer for slice on stack.
1640 t := types.NewArray(types.Types[TUINT8], tmpstringbufsize)
1641
1642 a = nod(OADDR, temp(t), nil)
1643 }
1644
1645 n = mkcall("stringtoslicebyte", n.Type, init, a, conv(n.Left, types.Types[TSTRING]))
"cmd/compile/internal/gc/walk.go" 3928 lines --40%--
according to the comments, the condition for the compiler to judge whether to allocate on the stack is whether the object will escape-
the compiler will determine whether an object will be referenced outside the current function, and if not, it can be optimized by allocating the object on the current stack without GC processing.
this process is part of compiler escape analysis (optimization). The related source code of escape analysis is
"cmd/compile/internal/gc/esc.go"
the result of compiler escape analysis can be obtained by using the following command
results of escape analysis without fmt.Println (s):
$ go tool compile -m test.go
test.go:7:16: cap(s) escapes to heap
test.go:7:24: len(s) escapes to heap
test.go:6:12: main ([]byte)("") does not escape
test.go:7:12: main ... argument does not escape
results of escape analysis with fmt.Println (s):
$ go tool compile -m test.go
test.go:7:16: cap(s) escapes to heap
test.go:7:24: len(s) escapes to heap
test.go:8:12: s escapes to heap
test.go:6:12: ([]byte)("") escapes to heap
test.go:7:12: main ... argument does not escape
test.go:8:12: main ... argument does not escape
The above basically explains what we have seen.
this is an interesting question. As a result, the compiler must have optimized the temporary array variables allocated on the stack (the temporarily allocated capacity of a fixed size), and once the array variables are manipulated, the capacity size of the array variables will be updated according to actual usage.
in addition, if the array is defined as a package internal variable or a global variable, the result of this cap will also be 0, because it will be allocated on the heap.
I am only guessing based on the test results, and the specific internal implementation details may need Daniel to popularize science.
have you ever used goquery? I want to use an agent to crawl. Does goquery support it? After looking for it, I don t seem to find ....
Overview: the younger brother s program can query the sql in the database and write it into excel performance by entering the database type, database connection string, executing sql or files containing sql. Currently, 25W pieces of data are exported,...
introduce Mutex into the object to ensure atomicity, but when the object is a value reference, it is found that the cable has no effect. What is its internal implementation logic? the code is as follows: package main import ( "fmt" ...
popularize the QR code what to do when 1 out of 1 million people cannot generate a QR code? ...
I want to package an ios sdk, instruction with gomobile bind instruction. There is always a unknown GOARCH: " " error in the execution of the sdk, instruction. The error is as follows: AndroidmacGOARCH, ...
has anyone ever used a reliable golang TCP services framework? the framework had better have the following two modules: 1. Session management of connections 2. The framework can customize the protocol ...
firewall, the integrated environment of system Centos7, lnmp.org, does not have the permission to run mysql. Iptables has been restarted. Refresh authorization error: Mysql user:Iptables: New processing: 1. Modify mysql configuration file vi ...
goal: golang service, prepare to get banner information of ip:port. if ip:port is http, you can get http response, if it is ssh service, you can get ssh service output information. Such as version information. pre-condition: the corresponding tcpAddr...
< hr > finally found that time.Sleep (100 * time.Millisecond) will affect the database. After removing it, I didn t encounter the problem of busy buffer . < hr > I have encountered some problems in converting a piece of data from Table 1 to Table ...
other people s project code is as follows jsonStr := `{"Name":"lepig", "Age":100}` abc := []byte(jsonStr) var result []string if err := json.Unmarshal(abc, &result); err != nil { fmt.Println(err) ...
how do I convert it? func GetPlan(c *gin.Context){ expect := c.PostForm("expect") prevexpect,_ := strconv.Atoi(PrevExpect()) sql := "SELECT * from plan pl " + "left JOIN program pr on pl.program_id = p...
I can accomplish all kinds of business requirements without this thing. What s the use of this? ...
etc rc.d rc.local and etc rc.local are both given execution permissions etc rc.d rc.local and etc rc.local are configured as follows -sharp! bin bash -sharp THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES -sharp -sharp It is highly advisable to ...
ask for advice background uses beego to build scenario description: background has some operations for each row of data, such as editing and deletion, etc. Now the server has passed the InsertFilter time before routing permission detection. now it j...
recently encountered a problem, go write websocket server how to achieve file upload function? Baidu Google did not find the answer they wanted. Is there any example of a third party or that can run successfully? tried to search for some answers, but ...
1. Is learning the go language and trying to write a website, one of the functions is that after the user logs in, all the file directories contained by the user are displayed on the home page of the user, that is, the file information is mapped. At pres...
whether this situation can only be judged by sync.Map and Channel ....
which language has more advantages in building short video websites? The mobile phone will be used later. Is there any similar source code reference for ? ...
similar to GORM, execute some functions before and after executing the query by registering them db.Callback().Create().Before("gorm:create").Register("update_created_at", updateCreated) db.Callback().Create().After("gorm:creat...
I am thinking about a question: how to downgrade the service? for example, there was an interface before, and an average was determined through the other three interfaces. Hypothetically, it doesn t necessarily make sense. To get the location of the ...