swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.58k stars 10.36k forks source link

[SR-5197] RandomKit: Swift 4 running 2x slower than Swift 3 #47773

Open ee21ea02-9d7a-4385-8c3c-ad21e8e490a8 opened 7 years ago

ee21ea02-9d7a-4385-8c3c-ad21e8e490a8 commented 7 years ago
Previous ID SR-5197
Radar rdar://problem/32718853
Original Reporter @moiseev
Type Bug
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: 419e2486ade04f21483f51715c17b46f

Issue Description:

https://www.reddit.com/r/swift/comments/6fxerp/swift_4_running_2x_slower_than_swift_3/

So I made Swift 4 compatibility changes to RandomKit and it seems that some of the changes (internal or external) made in Swift 4 result in a slowdown in some areas.
Generator Swift 3.1.1 Swift 4 (Xcode 9 beta 9M136h)
Xoroshiro 0.0271 0.0538
Xorshift 0.0568 0.1070
XorshiftStar 0.0319 0.0609
ChaCha 0.2027 0.2650
MersenneTwister 0.0432 0.0729
ARC4Random 0.2416 0.2429
DeviceRandom 5.3348 5.4001
These benchmarks were run with the current master branch as of this commit.
My guess is that it's either a change with array allocation or with bit shifts.

ee21ea02-9d7a-4385-8c3c-ad21e8e490a8 commented 7 years ago

@swift-cicreate

ee21ea02-9d7a-4385-8c3c-ad21e8e490a8 commented 7 years ago

Comments suggest that the problem might be related to the new shifts.

A quick check reveals that the code emitted by the compiler for the Xorshift.randomBytes does not change (except for the mangled names) from Swift 3.1 to Swift 3.2 to Swift 4.0.

The following code:

public struct Xorshift {

    /// Returns an unseeded instance.
    public static var unseeded: Xorshift {
        return Xorshift(seed: (0x193A6754, 0xA8A7D469, 0x97830E05, 0x113BA7BB))
    }

    private var x, y, z, w: UInt32

    /// Creates an instance from `seed`.
    ///
    /// - precondition: `seed` is nonzero.
    public init(seed: (UInt32, UInt32, UInt32, UInt32)) {
        (x, y, z, w) = seed
    }

    /// Returns random `Bytes`.
    @inline(never)
    public mutating func randomBytes() -> UInt32 {
        let t = x ^ (x << (11 as UInt32))
        x = y
        y = z
        z = w
        w = w ^ (w >> (19 as UInt32)) ^ (t ^ (t >> (8 as UInt32)))
        return w
    }
}

var rand = Xorshift.unseeded

public var x = UInt32()

for _ in 0..<10_000_000_000 {
  x |= rand.randomBytes()
}

print(x)

Which is the essence of the benchmark, has no performance difference between versions of the compiler.

atrick commented 7 years ago

Can we confirm the benchmarks were built with -O?

ee21ea02-9d7a-4385-8c3c-ad21e8e490a8 commented 7 years ago

It uses swift build -c release here which, I guess, calls the compiler with -O.