@@ -1973,17 +1973,27 @@ func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) {
19731973//sys preadv2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PREADV2
19741974//sys pwritev2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PWRITEV2
19751975
1976- func bytes2iovec (bs [][]byte ) []Iovec {
1977- iovecs := make ([]Iovec , len (bs ))
1978- for i , b := range bs {
1979- iovecs [i ].SetLen (len (b ))
1976+ // minIovec is the size of the small initial allocation used by
1977+ // Readv, Writev, etc.
1978+ //
1979+ // This small allocation gets stack allocated, which lets the
1980+ // common use case of len(iovs) <= minIovs avoid more expensive
1981+ // heap allocations.
1982+ const minIovec = 8
1983+
1984+ // appendBytes converts bs to Iovecs and appends them to vecs.
1985+ func appendBytes (vecs []Iovec , bs [][]byte ) []Iovec {
1986+ for _ , b := range bs {
1987+ var v Iovec
1988+ v .SetLen (len (b ))
19801989 if len (b ) > 0 {
1981- iovecs [ i ] .Base = & b [0 ]
1990+ v .Base = & b [0 ]
19821991 } else {
1983- iovecs [ i ] .Base = (* byte )(unsafe .Pointer (& _zero ))
1992+ v .Base = (* byte )(unsafe .Pointer (& _zero ))
19841993 }
1994+ vecs = append (vecs , v )
19851995 }
1986- return iovecs
1996+ return vecs
19871997}
19881998
19891999// offs2lohi splits offs into its low and high order bits.
@@ -1993,22 +2003,25 @@ func offs2lohi(offs int64) (lo, hi uintptr) {
19932003}
19942004
19952005func Readv (fd int , iovs [][]byte ) (n int , err error ) {
1996- iovecs := bytes2iovec (iovs )
2006+ iovecs := make ([]Iovec , 0 , minIovec )
2007+ iovecs = appendBytes (iovecs , iovs )
19972008 n , err = readv (fd , iovecs )
19982009 readvRacedetect (iovecs , n , err )
19992010 return n , err
20002011}
20012012
20022013func Preadv (fd int , iovs [][]byte , offset int64 ) (n int , err error ) {
2003- iovecs := bytes2iovec (iovs )
2014+ iovecs := make ([]Iovec , 0 , minIovec )
2015+ iovecs = appendBytes (iovecs , iovs )
20042016 lo , hi := offs2lohi (offset )
20052017 n , err = preadv (fd , iovecs , lo , hi )
20062018 readvRacedetect (iovecs , n , err )
20072019 return n , err
20082020}
20092021
20102022func Preadv2 (fd int , iovs [][]byte , offset int64 , flags int ) (n int , err error ) {
2011- iovecs := bytes2iovec (iovs )
2023+ iovecs := make ([]Iovec , 0 , minIovec )
2024+ iovecs = appendBytes (iovecs , iovs )
20122025 lo , hi := offs2lohi (offset )
20132026 n , err = preadv2 (fd , iovecs , lo , hi , flags )
20142027 readvRacedetect (iovecs , n , err )
@@ -2035,7 +2048,8 @@ func readvRacedetect(iovecs []Iovec, n int, err error) {
20352048}
20362049
20372050func Writev (fd int , iovs [][]byte ) (n int , err error ) {
2038- iovecs := bytes2iovec (iovs )
2051+ iovecs := make ([]Iovec , 0 , minIovec )
2052+ iovecs = appendBytes (iovecs , iovs )
20392053 if raceenabled {
20402054 raceReleaseMerge (unsafe .Pointer (& ioSync ))
20412055 }
@@ -2045,7 +2059,8 @@ func Writev(fd int, iovs [][]byte) (n int, err error) {
20452059}
20462060
20472061func Pwritev (fd int , iovs [][]byte , offset int64 ) (n int , err error ) {
2048- iovecs := bytes2iovec (iovs )
2062+ iovecs := make ([]Iovec , 0 , minIovec )
2063+ iovecs = appendBytes (iovecs , iovs )
20492064 if raceenabled {
20502065 raceReleaseMerge (unsafe .Pointer (& ioSync ))
20512066 }
@@ -2056,7 +2071,8 @@ func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) {
20562071}
20572072
20582073func Pwritev2 (fd int , iovs [][]byte , offset int64 , flags int ) (n int , err error ) {
2059- iovecs := bytes2iovec (iovs )
2074+ iovecs := make ([]Iovec , 0 , minIovec )
2075+ iovecs = appendBytes (iovecs , iovs )
20602076 if raceenabled {
20612077 raceReleaseMerge (unsafe .Pointer (& ioSync ))
20622078 }
0 commit comments