[go] net/ip: IPv4 ip.net.String() is not efficient

46 views
Skip to first unread message

Vladimir Kuzmin (Gerrit)

unread,
Mar 7, 2018, 10:56:23 PM3/7/18
to Matthew Dempsky, Giovanni Bajo, Ian Lance Taylor, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Vladimir Kuzmin would like Matthew Dempsky and Giovanni Bajo to review this change.

View Change

net/ip: IPv4 ip.net.String() is not efficient

Fixes #24306

On a scale 1000 IPs, pprof reported it as a one of the most expensive operation.
This is why I started to look at implementation and found that it can be
more efficient. This is optimiztion only for IPv4. It allocates buffer only once
and writes converted octets into given buffer.

../bin/go test -bench=BenchmarkIPString -run=^ip ./net/
Before fix:
pkg: net
BenchmarkIPString/IPv4-8 5000000 271 ns/op
BenchmarkIPString/IPv6-8 1000000 1287 ns/op
PASS
ok net 2.986s

After fix:
pkg: net
BenchmarkIPString/IPv4-8 10000000 155 ns/op
BenchmarkIPString/IPv6-8 1000000 1189 ns/op
PASS
ok net 2.938s

Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
---
M src/net/ip.go
M src/net/ip_test.go
2 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/src/net/ip.go b/src/net/ip.go
index 6b7ba4c..03c3bf6 100644
--- a/src/net/ip.go
+++ b/src/net/ip.go
@@ -260,6 +260,25 @@
return out
}

+// ubtoa converts unsigned byte to integer string. It writes result to destination
+// buffer and returns number of written bytes. Caller guarante that dst has enough size
+// and start is valid start index.
+func ubtoa(dst []byte, start uint, v byte) uint {
+ if v < 10 {
+ dst[start] = byte(v + '0')
+ return 1
+ } else if v < 100 {
+ dst[start+1] = byte(v%10 + '0')
+ dst[start] = byte(v/10 + '0')
+ return 2
+ }
+
+ dst[start+2] = byte(v%10 + '0')
+ dst[start+1] = byte((v/10)%10 + '0')
+ dst[start] = byte(v/100 + '0')
+ return 3
+}
+
// String returns the string form of the IP address ip.
// It returns one of 4 forms:
// - "<nil>", if ip has length 0
@@ -275,10 +294,23 @@

// If IPv4, use dotted notation.
if p4 := p.To4(); len(p4) == IPv4len {
- return uitoa(uint(p4[0])) + "." +
- uitoa(uint(p4[1])) + "." +
- uitoa(uint(p4[2])) + "." +
- uitoa(uint(p4[3]))
+ const maxIPv4StringLen = len("255.255.255.255")
+ byteArray := make([]byte, maxIPv4StringLen)
+
+ n := ubtoa(byteArray, 0, p4[0])
+ byteArray[n] = '.'
+ n++
+
+ n += ubtoa(byteArray, n, p4[1])
+ byteArray[n] = '.'
+ n++
+
+ n += ubtoa(byteArray, n, p4[2])
+ byteArray[n] = '.'
+ n++
+
+ n += ubtoa(byteArray, n, p4[3])
+ return string(byteArray[:n])
}
if len(p) != IPv6len {
return "?" + hexString(ip)
diff --git a/src/net/ip_test.go b/src/net/ip_test.go
index ad13388..044dc0f 100644
--- a/src/net/ip_test.go
+++ b/src/net/ip_test.go
@@ -252,9 +252,18 @@
func BenchmarkIPString(b *testing.B) {
testHookUninstaller.Do(uninstallTestHooks)

+ b.Run("IPv4", func(b *testing.B) {
+ benchmarkIPString(b, IPv4len)
+ })
+ b.Run("IPv6", func(b *testing.B) {
+ benchmarkIPString(b, IPv6len)
+ })
+}
+
+func benchmarkIPString(b *testing.B, size int) {
for i := 0; i < b.N; i++ {
for _, tt := range ipStringTests {
- if tt.in != nil {
+ if tt.in != nil && len(tt.in) == size {
sink = tt.in.String()
}
}

To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
Gerrit-Change-Number: 99395
Gerrit-PatchSet: 1
Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
Gerrit-MessageType: newchange

Andrew Bonventre (Gerrit)

unread,
Mar 8, 2018, 1:37:17 AM3/8/18
to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

View Change

3 comments:

    • On a scale 1000 IPs, pprof reported it as a one of the most expensive operation.
      This is why I started to look at implementation and found that it can be
      more efficient.

    • This part isn’t necessary.

      I would describe what it currently does and what you are doing to make it more efficient. Also why uitoa can’t be optimized in favor of adding a new function.

  • File src/net/ip.go:

To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
Gerrit-Change-Number: 99395
Gerrit-PatchSet: 1
Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
Gerit-CC: Andrew Bonventre <andy...@golang.org>
Gerrit-Comment-Date: Thu, 08 Mar 2018 06:37:14 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment

Vladimir Kuzmin (Gerrit)

unread,
Mar 8, 2018, 2:37:34 AM3/8/18
to goph...@pubsubhelper.golang.org, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

View Change

2 comments:

    • On a scale 1000 IPs, pprof reported it as a one of the most expensive operation.
      This is why I started to look at implementation and found that it can be
      more efficient.

    • This part isn’t necessary. […]

      Will fix the comment and title. uitoa doesn't accept destination buffer and returns string. It means it can't be optimized for this case. This is pretty specific case, I want function that works with byte array and uses caller's buffer.

  • File src/net/ip.go:

    • this is a byte slice, not a byte array. […]

      Done

To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
Gerrit-Change-Number: 99395
Gerrit-PatchSet: 1
Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
Gerit-CC: Andrew Bonventre <andy...@golang.org>
Gerrit-Comment-Date: Thu, 08 Mar 2018 07:37:32 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Andrew Bonventre <andy...@golang.org>
Gerrit-MessageType: comment

Vladimir Kuzmin (Gerrit)

unread,
Mar 8, 2018, 2:42:32 AM3/8/18
to Matthew Dempsky, Giovanni Bajo, goph...@pubsubhelper.golang.org, Andrew Bonventre, golang-co...@googlegroups.com

Vladimir Kuzmin uploaded patch set #2 to this change.

View Change

net/ip: Optimize ip.net.String() for IPv4

This is optimization only for IPv4. It allocates result buffer as array
of bytes only once and writes octets as dotted decimal into given buffer.
At the end it converts given array to string.

Benchmark shows 75% performance improvement:


../bin/go test -bench=BenchmarkIPString -run=^ip ./net/
Before fix:
pkg: net
BenchmarkIPString/IPv4-8 5000000 271 ns/op
BenchmarkIPString/IPv6-8 1000000 1287 ns/op
PASS
ok net 2.986s

After fix:
pkg: net
BenchmarkIPString/IPv4-8 10000000 155 ns/op
BenchmarkIPString/IPv6-8 1000000 1189 ns/op
PASS
ok net 2.938s

Fixes #24306


Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
---
M src/net/ip.go
M src/net/ip_test.go
2 files changed, 46 insertions(+), 5 deletions(-)

To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
Gerrit-Change-Number: 99395
Gerrit-PatchSet: 2
Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
Gerit-CC: Andrew Bonventre <andy...@golang.org>
Gerrit-MessageType: newpatchset

Vladimir Kuzmin (Gerrit)

unread,
Mar 8, 2018, 3:33:35 AM3/8/18
to goph...@pubsubhelper.golang.org, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

View Change

2 comments:

    • this doesn’t accurately describe what this change does.

    • Done

    • At the end it converts given array to string.

      Benchmark shows

      Will fix the comment and title. uitoa doesn't accept destination buffer and returns string. […]

      Done

To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
Gerrit-Change-Number: 99395
Gerrit-PatchSet: 2
Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
Gerit-CC: Andrew Bonventre <andy...@golang.org>
Gerrit-Comment-Date: Thu, 08 Mar 2018 08:33:32 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Vladimir Kuzmin <vku...@uber.com>

Alberto Donizetti (Gerrit)

unread,
Mar 8, 2018, 3:34:38 AM3/8/18
to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

For optimization changes we usually run each benchmark multiple times before and after the CL using -count, to reduce noise. You can put the results into a file, like this:

  go test -bench=BenchmarkIPString -count 20 > old.txt
go test -bench=BenchmarkIPString -count 20 > new.txt

and then compare the results using benchstat:

  $ benchstat old.txt new.txt

and finally put the benchstat output in the commit message.

View Change

    To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: go
    Gerrit-Branch: master
    Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
    Gerrit-Change-Number: 99395
    Gerrit-PatchSet: 2
    Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
    Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
    Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
    Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
    Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
    Gerit-CC: Andrew Bonventre <andy...@golang.org>
    Gerrit-Comment-Date: Thu, 08 Mar 2018 08:34:35 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    Vladimir Kuzmin (Gerrit)

    unread,
    Mar 8, 2018, 4:08:36 AM3/8/18
    to goph...@pubsubhelper.golang.org, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com
    Patch Set 2:
    $ benchstat old.txt new.txt

    and finally put the benchstat output in the commit message.

    Thanks, this is exactly what I wanted to have.

    benchstat oldip2str.txt newip2str.txt
    name old time/op new time/op delta
    IPString/IPv4-8 273ns ± 8% 143ns ± 8% -47.83% (p=0.000 n=20+20)
    IPString/IPv6-8 1.30µs ± 6% 1.11µs ± 3% -14.55% (p=0.000 n=20+18)

    15% improvement for IPv6 is not expected. I can explain it that both are running in the same Benchmark and reduced allocation improvement/GC for IPv4 has positive impact on IPv6.

    View Change

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 2
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerrit-Comment-Date: Thu, 08 Mar 2018 09:08:34 +0000

      Vladimir Kuzmin (Gerrit)

      unread,
      Mar 8, 2018, 4:09:06 AM3/8/18
      to Matthew Dempsky, Giovanni Bajo, goph...@pubsubhelper.golang.org, Alberto Donizetti, Andrew Bonventre, golang-co...@googlegroups.com

      Vladimir Kuzmin uploaded patch set #3 to this change.

      View Change

      net/ip: Optimize ip.net.String() for IPv4


      This is optimization only for IPv4. It allocates result buffer as array
      of bytes only once and writes octets as dotted decimal into given buffer.
      At the end it converts given array to string.

      Benchmark shows performance improvement:

      ../bin/go test -bench=BenchmarkIPString -run=^ip ./net/ -count 20


      benchstat oldip2str.txt newip2str.txt
      name old time/op new time/op delta
      IPString/IPv4-8 273ns ± 8% 143ns ± 8% -47.83% (p=0.000 n=20+20)
      IPString/IPv6-8 1.30µs ± 6% 1.11µs ± 3% -14.55% (p=0.000 n=20+18)

      Fixes #24306


      Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      ---
      M src/net/ip.go
      M src/net/ip_test.go
      2 files changed, 46 insertions(+), 5 deletions(-)

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 3
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerrit-MessageType: newpatchset

      Brad Fitzpatrick (Gerrit)

      unread,
      Mar 8, 2018, 11:23:52 AM3/8/18
      to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      View Change

      3 comments:


        • IPString/IPv4-8 273ns ± 8% 143ns ± 8% -47.83% (p=0.000 n=20+20)
          IPString/IPv6-8 1.30µs ± 6% 1.11µs ± 3% -14.55% (p=0.000 n=20+18)

        • can you include allocation numbers?

          Add b.ReportAllocs() to the benchmark.

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 3
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Comment-Date: Thu, 08 Mar 2018 16:23:50 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Gerrit-MessageType: comment

      Brad Fitzpatrick (Gerrit)

      unread,
      Mar 8, 2018, 11:32:25 AM3/8/18
      to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      View Change

      3 comments:

      • File src/net/ip.go:

        • Patch Set #3, Line 264: // buffer and returns number of written bytes. Caller guarante that dst has enough size

          typo: guarantees

        • Patch Set #3, Line 266: func ubtoa(dst []byte, start uint, v byte) uint {

          Don't use uint. It's rarely used in Go. Just change both to "int".

          For docs, I'd just write:

            // ubtoa encodes the string form of the integer v to dst[start:] and
          // returns the number of bytes written to dst. The caller must ensure
          // that dst has sufficient length.
        • Patch Set #3, Line 300: n := ubtoa(b, 0, p4[0])

          you could be consistent here, like:

              var n int
          n += ubtoa(b, n, p4[0])

          Like the lines below.

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 3
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Comment-Date: Thu, 08 Mar 2018 16:32:23 +0000

      Vladimir Kuzmin (Gerrit)

      unread,
      Mar 8, 2018, 3:06:43 PM3/8/18
      to Matthew Dempsky, Giovanni Bajo, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, golang-co...@googlegroups.com

      Vladimir Kuzmin uploaded patch set #4 to this change.

      View Change

      net/ip: Optimize ip.net.String() for IPv4


      This is optimization only for IPv4. It allocates result buffer as array
      of bytes only once and writes octets as dotted decimal into given buffer.
      At the end it converts given array to string.

      Benchmark shows performance improvement:

      name             old time/op    new time/op    delta
      IPString/IPv4-8     284ns ± 4%     144ns ± 6%  -49.35%  (p=0.000 n=19+17)
      IPString/IPv6-8 1.34µs ± 5% 1.14µs ± 5% -14.37% (p=0.000 n=19+20)

      name old alloc/op new alloc/op delta
      IPString/IPv4-8 24.0B ± 0% 16.0B ± 0% -33.33% (p=0.000 n=20+20)
      IPString/IPv6-8 232B ± 0% 224B ± 0% -3.45% (p=0.000 n=20+20)

      name old allocs/op new allocs/op delta
      IPString/IPv4-8 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.000 n=20+20)
      IPString/IPv6-8 12.0 ± 0% 11.0 ± 0% -8.33% (p=0.000 n=20+20)

      Fixes #24306


      Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      ---
      M src/net/ip.go
      M src/net/ip_test.go
      2 files changed, 49 insertions(+), 5 deletions(-)

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 4
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-MessageType: newpatchset

      Vladimir Kuzmin (Gerrit)

      unread,
      Mar 8, 2018, 3:07:05 PM3/8/18
      to goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      View Change

      4 comments:


        • name old alloc/op new alloc/op delta
          IPString/IPv4-8 24.0B ± 0% 16.0B ± 0% -33.33% (p=0.000 n=20

        • can you include allocation numbers? […]

          Done

      • File src/net/ip.go:

        • Patch Set #3, Line 264: // returns the number of bytes written to dst. The caller must ensure

          typo: guarantees

          Done

        • Patch Set #3, Line 266: func ubtoa(dst []byte, start int, v byte) int {

          Don't use uint. It's rarely used in Go. Just change both to "int". […]

          I like your word flow.

        • you could be consistent here, like: […]

          I considered it when wrote the code, but the version I have hides type of "n", this is deducted by compiler from context. And for instance, after I changed start and return type of ubtoa to `int' (as you suggested), this code is not affected. So, in fact we could even change it to uint8 if need extra efficiency and again, this part is not affected.

          Let me know if you have concern though.

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 4
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Comment-Date: Thu, 08 Mar 2018 20:07:03 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-MessageType: comment

      Ilya Tocar (Gerrit)

      unread,
      Mar 8, 2018, 3:42:50 PM3/8/18
      to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      View Change

      1 comment:

      • File src/net/ip.go:

        • Patch Set #4, Line 266: func ubtoa(dst []byte, start int, v byte) int {

          strconv/itoa.go uses lookup "table" for small integers, have you testes something similar?
          If this is faster, perhaps we should update itoa?

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 4
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerit-CC: Ilya Tocar <ilya....@intel.com>
      Gerrit-Comment-Date: Thu, 08 Mar 2018 20:42:47 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Gerrit-MessageType: comment

      Vladimir Kuzmin (Gerrit)

      unread,
      Mar 8, 2018, 4:22:11 PM3/8/18
      to Matthew Dempsky, Giovanni Bajo, goph...@pubsubhelper.golang.org, Ilya Tocar, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, golang-co...@googlegroups.com

      Vladimir Kuzmin uploaded patch set #5 to this change.

      View Change

      net: Optimize ip.net.String() for IPv4


      This is optimization only for IPv4. It allocates result buffer as array
      of bytes only once and writes octets as dotted decimal into given buffer.
      At the end it converts given array to string.

      Benchmark shows performance improvement:

      name old time/op new time/op delta
      IPString/IPv4-8 284ns ± 4% 144ns ± 6% -49.35% (p=0.000 n=19+17)
      IPString/IPv6-8 1.34µs ± 5% 1.14µs ± 5% -14.37% (p=0.000 n=19+20)

      name             old alloc/op   new alloc/op   delta
      IPString/IPv4-8     24.0B ± 0%     16.0B ± 0%  -33.33%  (p=0.000 n=20+20)
      IPString/IPv6-8 232B ± 0% 224B ± 0% -3.45% (p=0.000 n=20+20)

      name old allocs/op new allocs/op delta
      IPString/IPv4-8 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.000 n=20+20)
      IPString/IPv6-8 12.0 ± 0% 11.0 ± 0% -8.33% (p=0.000 n=20+20)

      Fixes #24306

      Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      ---
      M src/net/ip.go
      M src/net/ip_test.go
      2 files changed, 49 insertions(+), 5 deletions(-)

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 5
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerit-CC: Ilya Tocar <ilya....@intel.com>
      Gerrit-MessageType: newpatchset

      Vladimir Kuzmin (Gerrit)

      unread,
      Mar 8, 2018, 4:22:38 PM3/8/18
      to goph...@pubsubhelper.golang.org, Ilya Tocar, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      View Change

      3 comments:

        • no need for this line.

        • strconv/itoa.go uses lookup "table" for small integers, have you testes something similar? […]

          ubtoa covers a specific case and use single buffer for 4 numbers in a range 0-255 separated with "." as separator. This is why this is faster than any other standard-generic function that doesn't work with external buffer.

          Table for 0-255 could be a little bit faster than (v/10)%10 +'0') by the cost of memory. During implementation I looked at itoa and its tables:

          // small returns the string for an i with 0 <= i < nSmalls.
          func small(i int) string {
          off := 0
          if i < 10 {
          off = 1
          }
          return smallsString[i*2+off : i*2+2]
          }

          I don't think namely this is a something that can give a gain for ip.String(). Anyway, for this CL I don't want to use table, but code optimization only.

          Looking at itoa - probably we could optimize something there as well but as a separate issue. The net.IP optimization is from my real-life project problem, I found with pprof that it was too expensive (more than I expected) and I found that original implementation was too naive for standard method.

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 5
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerit-CC: Ilya Tocar <ilya....@intel.com>
      Gerrit-Comment-Date: Thu, 08 Mar 2018 21:22:36 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Ilya Tocar <ilya....@intel.com>

      Andrew Bonventre (Gerrit)

      unread,
      Mar 8, 2018, 6:44:51 PM3/8/18
      to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Ilya Tocar, Brad Fitzpatrick, Alberto Donizetti, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      View Change

      1 comment:

        • ubtoa covers a specific case and use single buffer for 4 numbers in a range 0-255 separated with ". […]

          I also don’t think a lookup table is necessary at this stage.

          The code that Vladimir has written already gives a substantial improvement in performance with a reduction in allocs. I’d say this is a win for now.

          Nice work.

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 5
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerit-CC: Ilya Tocar <ilya....@intel.com>
      Gerrit-Comment-Date: Thu, 08 Mar 2018 23:44:44 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Ilya Tocar <ilya....@intel.com>
      Comment-In-Reply-To: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-MessageType: comment

      Vladimir Kuzmin (Gerrit)

      unread,
      Mar 8, 2018, 6:57:19 PM3/8/18
      to goph...@pubsubhelper.golang.org, Ilya Tocar, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      View Change

      1 comment:

        • I also don’t think a lookup table is necessary at this stage. […]

          btw, I tried to adopt smallsString string from itoa, it works only for numbers <100. In my case, I need bytes, not a string and this is why I read it as: smallsString[v*2] and smallsString[v*2 +1], it's 15% slower.

          Frankly, I don't follow how appeared that smallsString are good for itoa, maybe smallsString[i*2+off : i*2+2] is doing some copy on write and avoids new string allocation. Anyway, on this particular case this is useless.

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 5
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerit-CC: Ilya Tocar <ilya....@intel.com>
      Gerrit-Comment-Date: Thu, 08 Mar 2018 23:57:16 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Ilya Tocar <ilya....@intel.com>
      Comment-In-Reply-To: Vladimir Kuzmin <vku...@uber.com>

      Joe Tsai (Gerrit)

      unread,
      Mar 8, 2018, 7:35:23 PM3/8/18
      to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Joe Tsai, Ilya Tocar, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      View Change

      1 comment:

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 5
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerit-CC: Ilya Tocar <ilya....@intel.com>
      Gerit-CC: Joe Tsai <thebroke...@gmail.com>
      Gerrit-Comment-Date: Fri, 09 Mar 2018 00:35:21 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Gerrit-MessageType: comment

      Joe Tsai (Gerrit)

      unread,
      Mar 8, 2018, 7:48:31 PM3/8/18
      to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Joe Tsai, Ilya Tocar, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      View Change

      1 comment:

        • How about strings.Builder? […]

          Hmm. I see the compiler has gotten smart enough now that it realizes b does not escape and does the string conversation without allocating+copying.

          Disregard my comment.

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 5
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerit-CC: Ilya Tocar <ilya....@intel.com>
      Gerit-CC: Joe Tsai <thebroke...@gmail.com>
      Gerrit-Comment-Date: Fri, 09 Mar 2018 00:48:29 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Joe Tsai <thebroke...@gmail.com>
      Gerrit-MessageType: comment

      Brad Fitzpatrick (Gerrit)

      unread,
      Mar 8, 2018, 11:53:33 PM3/8/18
      to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Joe Tsai, Ilya Tocar, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      View Change

      1 comment:

        • Hmm. […]

          The net package is low in the dependency chart, so it can't depend on many things we otherwise take for granted (like strconv).

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 5
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerit-CC: Ilya Tocar <ilya....@intel.com>
      Gerit-CC: Joe Tsai <thebroke...@gmail.com>
      Gerrit-Comment-Date: Fri, 09 Mar 2018 04:53:30 +0000

      Vladimir Kuzmin (Gerrit)

      unread,
      Mar 9, 2018, 3:16:53 AM3/9/18
      to goph...@pubsubhelper.golang.org, Joe Tsai, Ilya Tocar, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      Please advise who can run "Run-TryBot", necessary step as I understand. Thanks you all for a useful feedback, I learn from it!

      View Change

      1 comment:

        • The net package is low in the dependency chart, so it can't depend on many things we otherwise take […]

          I would be happy to see the better solution, even it means external dependency, we may always extract (copy-paste:) idea from the good package. But as Joe mentioned, compiler likes "local make". To confirm, I tried [15]bytes buffer at method (and then pointer to buffer at ubtoa), it was slower. Joe's observation that conversion to string uses buffer w/o copy explains it.

      To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: go
      Gerrit-Branch: master
      Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
      Gerrit-Change-Number: 99395
      Gerrit-PatchSet: 5
      Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
      Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
      Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
      Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
      Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
      Gerit-CC: Andrew Bonventre <andy...@golang.org>
      Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
      Gerit-CC: Ilya Tocar <ilya....@intel.com>
      Gerit-CC: Joe Tsai <thebroke...@gmail.com>
      Gerrit-Comment-Date: Fri, 09 Mar 2018 08:16:47 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Joe Tsai <thebroke...@gmail.com>

      Joe Tsai (Gerrit)

      unread,
      Mar 9, 2018, 3:17:39 AM3/9/18
      to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Joe Tsai, Ilya Tocar, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

      Patch set 5:Run-TryBot +1

      View Change

        To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: go
        Gerrit-Branch: master
        Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
        Gerrit-Change-Number: 99395
        Gerrit-PatchSet: 5
        Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
        Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
        Gerrit-Reviewer: Joe Tsai <thebroke...@gmail.com>
        Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
        Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
        Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
        Gerit-CC: Andrew Bonventre <andy...@golang.org>
        Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
        Gerit-CC: Ilya Tocar <ilya....@intel.com>
        Gerrit-Comment-Date: Fri, 09 Mar 2018 08:17:31 +0000
        Gerrit-HasComments: No
        Gerrit-Has-Labels: Yes
        Gerrit-MessageType: comment

        Gobot Gobot (Gerrit)

        unread,
        Mar 9, 2018, 3:17:52 AM3/9/18
        to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Joe Tsai, Ilya Tocar, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

        TryBots beginning. Status page: https://farmer.golang.org/try?commit=d174d633

        View Change

          To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

          Gerrit-Project: go
          Gerrit-Branch: master
          Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
          Gerrit-Change-Number: 99395
          Gerrit-PatchSet: 5
          Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
          Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
          Gerrit-Reviewer: Joe Tsai <thebroke...@gmail.com>
          Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
          Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
          Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
          Gerit-CC: Andrew Bonventre <andy...@golang.org>
          Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
          Gerit-CC: Gobot Gobot <go...@golang.org>
          Gerit-CC: Ilya Tocar <ilya....@intel.com>
          Gerrit-Comment-Date: Fri, 09 Mar 2018 08:17:50 +0000

          Gobot Gobot (Gerrit)

          unread,
          Mar 9, 2018, 3:28:14 AM3/9/18
          to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Joe Tsai, Ilya Tocar, Brad Fitzpatrick, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

          TryBots are happy.

          Patch set 5:TryBot-Result +1

          View Change

            To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: go
            Gerrit-Branch: master
            Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
            Gerrit-Change-Number: 99395
            Gerrit-PatchSet: 5
            Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
            Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
            Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
            Gerrit-Reviewer: Joe Tsai <thebroke...@gmail.com>
            Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
            Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
            Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
            Gerit-CC: Andrew Bonventre <andy...@golang.org>
            Gerit-CC: Brad Fitzpatrick <brad...@golang.org>
            Gerit-CC: Ilya Tocar <ilya....@intel.com>
            Gerrit-Comment-Date: Fri, 09 Mar 2018 08:28:12 +0000

            Brad Fitzpatrick (Gerrit)

            unread,
            Mar 9, 2018, 12:01:11 PM3/9/18
            to Vladimir Kuzmin, goph...@pubsubhelper.golang.org, Brad Fitzpatrick, Gobot Gobot, Joe Tsai, Ilya Tocar, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

            Patch set 5:Code-Review +2

            View Change

              To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

              Gerrit-Project: go
              Gerrit-Branch: master
              Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
              Gerrit-Change-Number: 99395
              Gerrit-PatchSet: 5
              Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
              Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
              Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
              Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
              Gerrit-Reviewer: Joe Tsai <thebroke...@gmail.com>
              Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
              Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
              Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
              Gerit-CC: Andrew Bonventre <andy...@golang.org>
              Gerit-CC: Ilya Tocar <ilya....@intel.com>
              Gerrit-Comment-Date: Fri, 09 Mar 2018 17:01:07 +0000

              Brad Fitzpatrick (Gerrit)

              unread,
              Mar 9, 2018, 12:01:32 PM3/9/18
              to Brad Fitzpatrick, Vladimir Kuzmin, Matthew Dempsky, Joe Tsai, Gobot Gobot, Giovanni Bajo, goph...@pubsubhelper.golang.org, Ilya Tocar, Alberto Donizetti, Andrew Bonventre, golang-co...@googlegroups.com

              Brad Fitzpatrick uploaded patch set #6 to the change originally created by Vladimir Kuzmin.

              View Change

              net: optimize IP.String for IPv4


              This is optimization only for IPv4. It allocates result buffer as array
              of bytes only once and writes octets as dotted decimal into given buffer.
              At the end it converts given array to string.

              Benchmark shows performance improvement:

              name             old time/op    new time/op    delta
              IPString/IPv4-8     284ns ± 4%     144ns ± 6%  -49.35%  (p=0.000 n=19+17)
              IPString/IPv6-8 1.34µs ± 5% 1.14µs ± 5% -14.37% (p=0.000 n=19+20)

              name old alloc/op new alloc/op delta
              IPString/IPv4-8 24.0B ± 0% 16.0B ± 0% -33.33% (p=0.000 n=20+20)
              IPString/IPv6-8 232B ± 0% 224B ± 0% -3.45% (p=0.000 n=20+20)

              name old allocs/op new allocs/op delta
              IPString/IPv4-8 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.000 n=20+20)
              IPString/IPv6-8 12.0 ± 0% 11.0 ± 0% -8.33% (p=0.000 n=20+20)

              Fixes #24306

              Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
              ---
              M src/net/ip.go
              M src/net/ip_test.go
              2 files changed, 49 insertions(+), 5 deletions(-)

              To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

              Gerrit-Project: go
              Gerrit-Branch: master
              Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
              Gerrit-Change-Number: 99395
              Gerrit-PatchSet: 6
              Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
              Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
              Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
              Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
              Gerrit-Reviewer: Joe Tsai <thebroke...@gmail.com>
              Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
              Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
              Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
              Gerit-CC: Andrew Bonventre <andy...@golang.org>
              Gerit-CC: Ilya Tocar <ilya....@intel.com>
              Gerrit-MessageType: newpatchset

              Brad Fitzpatrick (Gerrit)

              unread,
              Mar 9, 2018, 12:03:04 PM3/9/18
              to Brad Fitzpatrick, Vladimir Kuzmin, Matthew Dempsky, Joe Tsai, Gobot Gobot, Giovanni Bajo, goph...@pubsubhelper.golang.org, Ilya Tocar, Alberto Donizetti, Andrew Bonventre, golang-co...@googlegroups.com

              Brad Fitzpatrick uploaded patch set #7 to the change originally created by Vladimir Kuzmin.

              View Change

              net: optimize IP.String for IPv4

              This is optimization is only for IPv4. It allocates a result buffer and
              writes the IPv4 octets as dotted decimal into it before converting
              it to a string just once, reducing allocations.


              Benchmark shows performance improvement:

              name old time/op new time/op delta
              IPString/IPv4-8 284ns ± 4% 144ns ± 6% -49.35% (p=0.000 n=19+17)
              IPString/IPv6-8 1.34µs ± 5% 1.14µs ± 5% -14.37% (p=0.000 n=19+20)

              name old alloc/op new alloc/op delta
              IPString/IPv4-8 24.0B ± 0% 16.0B ± 0% -33.33% (p=0.000 n=20+20)
              IPString/IPv6-8 232B ± 0% 224B ± 0% -3.45% (p=0.000 n=20+20)

              name old allocs/op new allocs/op delta
              IPString/IPv4-8 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.000 n=20+20)
              IPString/IPv6-8 12.0 ± 0% 11.0 ± 0% -8.33% (p=0.000 n=20+20)

              Fixes #24306

              Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
              ---
              M src/net/ip.go
              M src/net/ip_test.go
              2 files changed, 49 insertions(+), 5 deletions(-)

              To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

              Gerrit-Project: go
              Gerrit-Branch: master
              Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
              Gerrit-Change-Number: 99395
              Gerrit-PatchSet: 7

              Brad Fitzpatrick (Gerrit)

              unread,
              Mar 9, 2018, 12:03:08 PM3/9/18
              to Brad Fitzpatrick, Vladimir Kuzmin, goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, Gobot Gobot, Joe Tsai, Ilya Tocar, Alberto Donizetti, Andrew Bonventre, Matthew Dempsky, Giovanni Bajo, golang-co...@googlegroups.com

              Brad Fitzpatrick merged this change.

              View Change

              Approvals: Brad Fitzpatrick: Looks good to me, approved
              net: optimize IP.String for IPv4

              This is optimization is only for IPv4. It allocates a result buffer and
              writes the IPv4 octets as dotted decimal into it before converting
              it to a string just once, reducing allocations.

              Benchmark shows performance improvement:

              name old time/op new time/op delta
              IPString/IPv4-8 284ns ± 4% 144ns ± 6% -49.35% (p=0.000 n=19+17)
              IPString/IPv6-8 1.34µs ± 5% 1.14µs ± 5% -14.37% (p=0.000 n=19+20)

              name old alloc/op new alloc/op delta
              IPString/IPv4-8 24.0B ± 0% 16.0B ± 0% -33.33% (p=0.000 n=20+20)
              IPString/IPv6-8 232B ± 0% 224B ± 0% -3.45% (p=0.000 n=20+20)

              name old allocs/op new allocs/op delta
              IPString/IPv4-8 3.00 ± 0% 2.00 ± 0% -33.33% (p=0.000 n=20+20)
              IPString/IPv6-8 12.0 ± 0% 11.0 ± 0% -8.33% (p=0.000 n=20+20)

              Fixes #24306

              Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
              Reviewed-on: https://go-review.googlesource.com/99395
              Reviewed-by: Brad Fitzpatrick <brad...@golang.org>

              ---
              M src/net/ip.go
              M src/net/ip_test.go
              2 files changed, 49 insertions(+), 5 deletions(-)

              diff --git a/src/net/ip.go b/src/net/ip.go
              index 6b7ba4c..a94ff73 100644
              --- a/src/net/ip.go
              +++ b/src/net/ip.go
              @@ -260,6 +260,25 @@
              return out
              }

              +// ubtoa encodes the string form of the integer v to dst[start:] and
              +// returns the number of bytes written to dst. The caller must ensure
              +// that dst has sufficient length.
              +func ubtoa(dst []byte, start int, v byte) int {
              + if v < 10 {
              + dst[start] = byte(v + '0')
              + return 1
              + } else if v < 100 {
              + dst[start+1] = byte(v%10 + '0')
              + dst[start] = byte(v/10 + '0')
              + return 2
              + }
              +
              + dst[start+2] = byte(v%10 + '0')
              + dst[start+1] = byte((v/10)%10 + '0')
              + dst[start] = byte(v/100 + '0')
              + return 3
              +}
              +
              // String returns the string form of the IP address ip.
              // It returns one of 4 forms:
              // - "<nil>", if ip has length 0
              @@ -275,10 +294,23 @@

              // If IPv4, use dotted notation.
              if p4 := p.To4(); len(p4) == IPv4len {
              - return uitoa(uint(p4[0])) + "." +
              - uitoa(uint(p4[1])) + "." +
              - uitoa(uint(p4[2])) + "." +
              - uitoa(uint(p4[3]))
              + const maxIPv4StringLen = len("255.255.255.255")
              + b := make([]byte, maxIPv4StringLen)
              +
              + n := ubtoa(b, 0, p4[0])
              + b[n] = '.'
              + n++
              +
              + n += ubtoa(b, n, p4[1])
              + b[n] = '.'
              + n++
              +
              + n += ubtoa(b, n, p4[2])
              + b[n] = '.'
              + n++
              +
              + n += ubtoa(b, n, p4[3])
              + return string(b[:n])
              }
              if len(p) != IPv6len {
              return "?" + hexString(ip)
              diff --git a/src/net/ip_test.go b/src/net/ip_test.go
              index ad13388..60329e9 100644
              --- a/src/net/ip_test.go
              +++ b/src/net/ip_test.go
              @@ -252,9 +252,21 @@
              func BenchmarkIPString(b *testing.B) {
              testHookUninstaller.Do(uninstallTestHooks)

              + b.Run("IPv4", func(b *testing.B) {
              + benchmarkIPString(b, IPv4len)
              + })
              +
              + b.Run("IPv6", func(b *testing.B) {
              + benchmarkIPString(b, IPv6len)
              + })
              +}
              +
              +func benchmarkIPString(b *testing.B, size int) {
              + b.ReportAllocs()
              + b.ResetTimer()
              for i := 0; i < b.N; i++ {
              for _, tt := range ipStringTests {
              - if tt.in != nil {
              + if tt.in != nil && len(tt.in) == size {
              sink = tt.in.String()
              }
              }

              To view, visit change 99395. To unsubscribe, or for help writing mail filters, visit settings.

              Gerrit-Project: go
              Gerrit-Branch: master
              Gerrit-Change-Id: I4e2d30d364e78183d55a42907d277744494b6df3
              Gerrit-Change-Number: 99395
              Gerrit-PatchSet: 8
              Gerrit-Owner: Vladimir Kuzmin <vku...@uber.com>
              Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
              Gerrit-Reviewer: Giovanni Bajo <ra...@develer.com>
              Gerrit-Reviewer: Gobot Gobot <go...@golang.org>
              Gerrit-Reviewer: Joe Tsai <thebroke...@gmail.com>
              Gerrit-Reviewer: Matthew Dempsky <mdem...@google.com>
              Gerrit-Reviewer: Vladimir Kuzmin <vku...@uber.com>
              Gerit-CC: Alberto Donizetti <alb.do...@gmail.com>
              Gerit-CC: Andrew Bonventre <andy...@golang.org>
              Gerit-CC: Ilya Tocar <ilya....@intel.com>
              Gerrit-MessageType: merged
              Reply all
              Reply to author
              Forward
              0 new messages