And just for completeness, ebp vs ecx also swapped:
BenchmarkAddEBP 1000000000 2.66 ns/op
BenchmarkIncEBP 1000000000 2.47 ns/op
BenchmarkAddECX 1000000000 2.74 ns/op
BenchmarkIncECX 1000000000 2.47 ns/op
And inc first:
BenchmarkIncEBP 1000000000 2.54 ns/op
BenchmarkAddEBP 1000000000 2.47 ns/op
BenchmarkIncECX 1000000000 2.52 ns/op
BenchmarkAddECX 1000000000 2.47 ns/op
Whoever goes second is the winner... Here's the full code:
// asm.s
// func IncECX(z *int64)
TEXT ·IncECX(SB),$0-8
MOVQ z+0(FP),AX // make z accessible
MOVQ (AX),CX // load *z
INCQ CX // add 1
MOVQ CX,(AX) // store sum in *z
RET
// func IncEBP(z *int64)
TEXT ·IncEBP(SB),$0-8
MOVQ z+0(FP),AX // make z accessible
MOVQ (AX),BP // load *z
INCQ BP // add 1
MOVQ BP,(AX) // store sum in *z
RET
// func AddEBP(z *int64)
TEXT ·AddECX(SB),$0-8
MOVQ z+0(FP),AX // make z accessible
MOVQ (AX),CX // load *z
ADDQ $1,CX // add 1
MOVQ CX,(AX) // store sum in *z
RET
// func AddEBP(z *int64)
TEXT ·AddEBP(SB),$0-8
MOVQ z+0(FP),AX // make z accessible
MOVQ (AX),BP // load *z
ADDQ $1,BP // add 1
MOVQ BP,(AX) // store sum in *z
RET
// main.go
package main
func IncECX(z *int64)
func IncEBP(z *int64)
func AddECX(z *int64)
func AddEBP(z *int64)
// main_test.go
package main
import (
"testing"
)
func BenchmarkIncEBP(b *testing.B) {
a := new(int64)
for i := 0; i < b.N; i++ {
IncEBP(a)
}
}
func BenchmarkAddEBP(b *testing.B) {
a := new(int64)
for i := 0; i < b.N; i++ {
AddEBP(a)
}
}
func BenchmarkIncECX(b *testing.B) {
a := new(int64)
for i := 0; i < b.N; i++ {
IncECX(a)
}
}
func BenchmarkAddECX(b *testing.B) {
a := new(int64)
for i := 0; i < b.N; i++ {
AddECX(a)
}
}
On Sat, Mar 2, 2013 at 1:32 PM, Alexey Borzenkov wrote:Hi,
This could likely be a fluke, due to the order of these tests. I tried
testing inc vs add performance with and see something like this:
BenchmarkIncECX 1000000000 2.51 ns/op
BenchmarkAddECX 1000000000 2.47 ns/op
BenchmarkIncEBP 1000000000 2.53 ns/op
BenchmarkAddEBP 1000000000 2.47 ns/op
However, if I change tests order, then suddenly it's like this:
BenchmarkAddECX 1000000000 2.70 ns/op
BenchmarkIncECX 1000000000 2.46 ns/op
BenchmarkAddEBP 1000000000 2.46 ns/op
BenchmarkIncEBP 1000000000 2.46 ns/op
Besides, these results on my machine (Intel Core i7, 2.3GHz) are very
unstable, they often change from run to run.
On Sat, Mar 2, 2013 at 9:16 AM, Michael Jones wrote:Summary: NEVER use the x86 increment instruction.
Details (n-word fixed precision math library code generated automatically
by my AWK script):
// FixedInc: z++, z is a 2-word (128 bit) fixed precision integer
// func FixedInc(z *Integer)
TEXT ·FixedInc(SB),$0-8
MOVQ z+0(FP),AX // make z[] accessible
MOVQ (AX),BP // load z[0]
// Version (A) using Increment
//INCQ BP // add 1
// Version (B) using Add with an immediate constant of 1
ADDQ $1,BP
MOVQ BP,(AX) // store sum in z[0]
MOVQ 8(AX),BP // load z[1]
ADCQ $0,BP // add carry
MOVQ BP,8(AX) // store sum in z[1]
RET
Driver, because we can't generate a call to a method in assembler. :-(
// increment: z += 1
func (z *Integer) Inc() {
FixedInc(z) // Sigh... not possible to generate methods in assembler
}
Test:
func BenchmarkInc(b *testing.B) {
a := New().SetUint64(0)
for i := 0; i < b.N; i++ {
a.Inc()
}
}
Results:
Version A using INCQ, BenchmarkInc 100000000 10.2 ns/op
Version B using ADDQ, BenchmarkInc 500000000 7.19 ns/op
Summary: NEVER use an x86 increment instruction. This is embarrassing,
because I've known it for >2 decades.
NOTE: 6g also seems to use INC. My suggestion is that we wean ourselves
from this needless expense.
func test() int {
* i := 0*
* i++*
return i
}
--- prog list "test" ---
0032 (/Users/mtj/gocode/src/inc/inc.go:7) TEXT test+0(SB),$0-8
0033 (/Users/mtj/gocode/src/inc/inc.go:7) LOCALS ,$0
0034 (/Users/mtj/gocode/src/inc/inc.go:7) TYPE ~anon0+0(FP){int},$8
0035 (/Users/mtj/gocode/src/inc/inc.go:8)* MOVQ $0,AX*
0036 (/Users/mtj/gocode/src/inc/inc.go:9) *INCQ ,AX*
0037 (/Users/mtj/gocode/src/inc/inc.go:10) MOVQ AX,~anon0+0(FP)
0038 (/Users/mtj/gocode/src/inc/inc.go:10) RET ,
Michael T. Jones | Chief Technology Advocate |
mtj@google.com | +1
650-335-5765
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit
https://groups.google.com/groups/opt_out. --
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit
https://groups.google.com/groups/opt_out.