1
0
mirror of https://github.com/golang/go synced 2024-11-19 15:44:44 -07:00

runtime: implement fastrand in go

So it could be inlined.

Using bit-tricks it could be implemented without condition
(improved trick version by Minux Ma).

Simple benchmark shows it is faster on i386 and x86_64, though
I don't know will it be faster on other architectures?

benchmark                       old ns/op     new ns/op     delta
BenchmarkFastrand-3             2.79          1.48          -46.95%
BenchmarkFastrandHashiter-3     25.9          24.9          -3.86%

Change-Id: Ie2eb6d0f598c0bb5fac7f6ad0f8b5e3eddaa361b
Reviewed-on: https://go-review.googlesource.com/34782
Reviewed-by: Minux Ma <minux@golang.org>
Run-TryBot: Minux Ma <minux@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Sokolov Yura 2017-01-05 09:36:27 +03:00 committed by Josh Bleecher Snyder
parent 9f75ecd5e1
commit d03c124860
12 changed files with 43 additions and 105 deletions

View File

@ -1595,20 +1595,6 @@ allsame:
MOVL BX, (AX) MOVL BX, (AX)
RET RET
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
get_tls(CX)
MOVL g(CX), AX
MOVL g_m(AX), AX
MOVL m_fastrand(AX), DX
ADDL DX, DX
MOVL DX, BX
XORL $0x88888eef, DX
JPL 2(PC)
MOVL BX, DX
MOVL DX, m_fastrand(AX)
MOVL DX, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0 TEXT runtime·return0(SB), NOSPLIT, $0
MOVL $0, AX MOVL $0, AX
RET RET

View File

@ -2163,19 +2163,6 @@ eqret:
MOVB $0, ret+48(FP) MOVB $0, ret+48(FP)
RET RET
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
get_tls(CX)
MOVQ g(CX), AX
MOVQ g_m(AX), AX
MOVL m_fastrand(AX), DX
ADDL DX, DX
MOVL DX, BX
XORL $0x88888eef, DX
CMOVLMI BX, DX
MOVL DX, m_fastrand(AX)
MOVL DX, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0 TEXT runtime·return0(SB), NOSPLIT, $0
MOVL $0, AX MOVL $0, AX
RET RET

View File

@ -991,19 +991,6 @@ eqret:
MOVB AX, ret+24(FP) MOVB AX, ret+24(FP)
RET RET
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
get_tls(CX)
MOVL g(CX), AX
MOVL g_m(AX), AX
MOVL m_fastrand(AX), DX
ADDL DX, DX
MOVL DX, BX
XORL $0x88888eef, DX
CMOVLMI BX, DX
MOVL DX, m_fastrand(AX)
MOVL DX, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0 TEXT runtime·return0(SB), NOSPLIT, $0
MOVL $0, AX MOVL $0, AX
RET RET

View File

@ -971,15 +971,6 @@ _sib_notfound:
MOVW R0, ret+12(FP) MOVW R0, ret+12(FP)
RET RET
TEXT runtime·fastrand(SB),NOSPLIT,$-4-4
MOVW g_m(g), R1
MOVW m_fastrand(R1), R0
ADD.S R0, R0
EOR.MI $0x88888eef, R0
MOVW R0, m_fastrand(R1)
MOVW R0, ret+0(FP)
RET
TEXT runtime·return0(SB),NOSPLIT,$0 TEXT runtime·return0(SB),NOSPLIT,$0
MOVW $0, R0 MOVW $0, R0
RET RET

View File

@ -959,18 +959,6 @@ equal:
MOVB R0, ret+48(FP) MOVB R0, ret+48(FP)
RET RET
TEXT runtime·fastrand(SB),NOSPLIT,$-8-4
MOVD g_m(g), R1
MOVWU m_fastrand(R1), R0
ADD R0, R0
CMPW $0, R0
BGE notneg
EOR $0x88888eef, R0
notneg:
MOVW R0, m_fastrand(R1)
MOVW R0, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0 TEXT runtime·return0(SB), NOSPLIT, $0
MOVW $0, R0 MOVW $0, R0
RET RET

View File

@ -831,16 +831,6 @@ notfound:
MOVV R1, ret+24(FP) MOVV R1, ret+24(FP)
RET RET
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
MOVV g_m(g), R2
MOVWU m_fastrand(R2), R1
ADDU R1, R1
BGEZ R1, 2(PC)
XOR $0x88888eef, R1
MOVW R1, m_fastrand(R2)
MOVW R1, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0 TEXT runtime·return0(SB), NOSPLIT, $0
MOVW $0, R1 MOVW $0, R1
RET RET

View File

@ -904,16 +904,6 @@ cmp_ret:
MOVW R8, ret+24(FP) MOVW R8, ret+24(FP)
RET RET
TEXT runtime·fastrand(SB),NOSPLIT,$0-4
MOVW g_m(g), R2
MOVW m_fastrand(R2), R1
ADDU R1, R1
BGEZ R1, 2(PC)
XOR $0x88888eef, R1
MOVW R1, m_fastrand(R2)
MOVW R1, ret+0(FP)
RET
TEXT runtime·return0(SB),NOSPLIT,$0 TEXT runtime·return0(SB),NOSPLIT,$0
MOVW $0, R1 MOVW $0, R1
RET RET

View File

@ -1224,17 +1224,6 @@ TEXT bytes·Compare(SB),NOSPLIT|NOFRAME,$0-56
BR cmpbodyBE<>(SB) BR cmpbodyBE<>(SB)
#endif #endif
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
MOVD g_m(g), R4
MOVWZ m_fastrand(R4), R3
ADD R3, R3
CMPW R3, $0
BGE 2(PC)
XOR $0x88888eef, R3
MOVW R3, m_fastrand(R4)
MOVW R3, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0 TEXT runtime·return0(SB), NOSPLIT, $0
MOVW $0, R3 MOVW $0, R3
RET RET

View File

@ -851,17 +851,6 @@ TEXT runtime·memeqbodyclc(SB),NOSPLIT|NOFRAME,$0-0
CLC $1, 0(R3), 0(R5) CLC $1, 0(R3), 0(R5)
RET RET
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
MOVD g_m(g), R4
MOVWZ m_fastrand(R4), R3
ADD R3, R3
CMPW R3, $0
BGE 2(PC)
XOR $0x88888eef, R3
MOVW R3, m_fastrand(R4)
MOVW R3, ret+0(FP)
RET
TEXT bytes·IndexByte(SB),NOSPLIT|NOFRAME,$0-40 TEXT bytes·IndexByte(SB),NOSPLIT|NOFRAME,$0-40
MOVD s+0(FP), R3 // s => R3 MOVD s+0(FP), R3 // s => R3
MOVD s_len+8(FP), R4 // s_len => R4 MOVD s_len+8(FP), R4 // s_len => R4

View File

@ -245,3 +245,5 @@ func CountPagesInUse() (pagesInUse, counted uintptr) {
return return
} }
func Fastrand() uint32 { return fastrand() }

32
src/runtime/rand_test.go Normal file
View File

@ -0,0 +1,32 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime_test
import (
. "runtime"
"testing"
)
func BenchmarkFastrand(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
Fastrand()
}
})
}
func BenchmarkFastrandHashiter(b *testing.B) {
var m = make(map[int]int, 10)
for i := 0; i < 10; i++ {
m[i] = i
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
for _ = range m {
break
}
}
})
}

View File

@ -93,8 +93,15 @@ func reflect_memmove(to, from unsafe.Pointer, n uintptr) {
// exported value for testing // exported value for testing
var hashLoad = loadFactor var hashLoad = loadFactor
// in asm_*.s //go:nosplit
func fastrand() uint32 func fastrand() uint32 {
mp := getg().m
fr := mp.fastrand
fr <<= 1
fr ^= uint32(int32(fr)>>31) & 0x88888eef
mp.fastrand = fr
return fr
}
//go:linkname sync_fastrand sync.fastrand //go:linkname sync_fastrand sync.fastrand
func sync_fastrand() uint32 { return fastrand() } func sync_fastrand() uint32 { return fastrand() }