Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use SipHash-1-3 for all hashing, through a resilient hashing interface #14913

Merged
merged 5 commits into from
Mar 9, 2018

Conversation

lorentey
Copy link
Member

@lorentey lorentey commented Mar 1, 2018

This PR implements resilient hashing for stdlib types and types with synthesized Hashable implementations. It changes the standard hash function to SipHash-1-3 with a per-execution random seed.

Background

Hash tables are probabilistic data structures; their expected performance depends on (implicit and largely unknown) assumptions on the statistical distribution of their keys and the properties of the hash function that is used to derive bucket indices for individual key values.

Weak hash functions can enable accidental (or deliberate) skewing of the key distribution in such a way that collisions become more likely. In extreme cases, lookup performance may become linear rather than the promised O(1), which may turn other operations using lookups quadratic rather than linear, etc. This is not a hypothetical concern: there have been major cases of successful denial of service attacks targeted against hash tables implemented in various programming languages and libraries.

In general purpose collection types like Swift's Set or Dictionary, we can't meaningfully constrain the distribution of keys. Our only option to protect against hash collision cascades is to choose a hash function that's strong enough to handle all key distributions, ideally even those that deliberately try to defeat it.

The Status Quo

Our current approach is not particularly great in this regard: the choice of the hash function is mostly in the hands of the programmer implementing hashValue, and we provide no public API to guide them. Implementing a good hash function requires careful consideration and specialist knowledge; it takes time and effort they clearly can't be expected to invest.

To fix this, we should start by improving cases where hashValue is under Swift's control: inside the Standard Library and in Hashable implementations synthesized by the compiler. For these, we currently rely on two underscored functions:

  • _mixInt: (Int) -> Int was designed to be used as a hashValue post-processing tool in hashed collections, improving distribution of user-generated hash values so that occupied buckets are less likely to bunch together in long chains. It does a fine job on this task; however, hash ^= _mixInt(foo) has been widely (mis)used as a rudimentary compression function, providing essentially no protection against even trivial accidental collisions.
  • _combineHashes: (Int, Int) -> Int is our recently introduced hash compression function, used in synthesized Hashable implementations. Its current implementation wasn't designed to protect against deliberate collisions, even if we were to seed it with a random key. Unfortunately, its stateless interface severely limits the scope of hash functions it can implement. For example, SipHash needs to maintain 256 bits of state; it is not possible to fit that into this interface.

This PR intends to improve matters by standardizing on a high quality hash function, SipHash, for use inside the standard library and inside compiler-synthesized Hashable implementations. (SipHash is already implemented in the stdlib, but so far it has been sitting there largely unused.)

This PR does not introduce public API to help with manual Hashable implementations -- but it provides the first step towards providing one.

Requirements

  • Stateful hash function -- We need to be able to support hash functions with a state larger than a single pointer-sized integer.
  • Random hash seeding -- Hashable has been documented since Swift 1.0 to allow per-execution hash seeds, but so far we have only implemented random seeds for Strings on non-Apple platforms. Random seeding makes hash values harder to predict; we need to enable it on all platforms and all Hashable types. (In some contexts, we may want to go further and introduce local seeds for each Dictionary capacity (or even instance). But a per-execution seed is the obvious first step.)
  • Resiliency -- To enable us to replace/evolve the hash function in future versions of the stdlib, the hash algorithm must not be baked into types implementing Hashable; it must be implemented entirely behind resiliency boundaries. (Ideally this includes the size/layout of the state, not just the code itself.)

New Hashable Requirement

To satisfy these constraints, this PR adds a new requirement to Hashable that allows the hash function to be supplied externally:

protocol Hashable {
  var hashValue: Int { get } // Existing public interface
  func _hash(into hasher: inout _Hasher) // New internal hotness
}

The new requirement is not designed to be manually implemented outside the stdlib, so it remains underscored, with a default implementation. hashValue remains the public API for manual hashing. To help users provide high-quality hashValue implementations, we may expose Hasher as documented API later. In addition, we may decide to promote hash(into:) into a documented requirement, intended to replace hashValue. (These require swift-evolution proposals.)

_Hasher represents the internal state of the hash function. It provides a mutating interface to append additional bits to the hash function, mixing them into the state.

_Hasher has a public parameterless initializer and a public finalizer. The struct itself is intentionally not marked @_fixed_layout; its members are not inlinable, either, except for the generic variant of append(_:). Here is its full exported interface:

public struct _Hasher { // Size/layout isn't exposed
  public init()

  @inline(__always)
  public func append<H: Hashable>(_ value: H) {
    value._hash(into: &self)
  }

  public func append(bits: Int)
  // ... other integer overloads for append(bits:) ...

  public func finalize() -> Int
}

Synthesized Hashable Implementations

Note _hash(into:) synthesis has been deferred to a future PR.

Synthesized implementations of Hashable now generate a _hash(into:) implementation that does the actual work of hashing a type's components. The generated hashValue implementation simply instantiates a new hasher and feeds it to _hash(into:). For example, here is how Hashable conformance is derived for a simple struct:

struct Book: Hashable {
  let title: String
  let authors: [Author]
  let pageCount: Int

  @derived var hashValue: Int { 
    return _hashValue(for: self) 
  }
  @derived func _hash(into hasher: inout _Hasher) {
    hasher.append(title)
    hasher.append(authors)
    hasher.append(pageCount)
  }
}

Per-execution Random Hash Seed

Introducing a per-execution hash seed fulfills a long-standing prophecy in the documentation about hash values not being stable across different executions. Indeed, not even integers return a predictable hashValue any more:

$ cat hash.swift
print("42.hashValue = \(42.hashValue)")
$ swiftc hash.swift
$ ./hash
42.hashValue = 4676625759386310310
$ ./hash
42.hashValue = -2488622482260669029

(The hash values remain stable within the same process, though.) To enable repeatable results in cases like unit testing, the 128-bit hash seed is exposed as _Hashing.secretKey; setting it to a fixed constant value disables randomization. Currently this needs to be done before the first Set or Dictionary is created. StdlibUnitTest.TestSuite in the Swift test suite automatically zeroes out the key when it is first instantiated.

Performance

SipHash is more reliable, but it's also a bit more complicated than _mixInt/_combineHashes. Resiliency also adds a little bit of extra overhead. At the end of the day, #14442 measured these changes to cost up to +80% performance on our microbenchmarks. I expect we'll be able to optimize things further after this lands.

Resolves rdar://problem/24109692, rdar://problem/35052153

@lorentey
Copy link
Member Author

lorentey commented Mar 1, 2018

@swift-ci please test

@swift-ci
Copy link
Contributor

swift-ci commented Mar 1, 2018

Build failed
Swift Test Linux Platform
Git Sha - e5f5ffb

@lorentey
Copy link
Member Author

lorentey commented Mar 1, 2018

Sigh Let's try that again, shall we.

@lorentey
Copy link
Member Author

lorentey commented Mar 1, 2018

@swift-ci please test

@swiftlang swiftlang deleted a comment from swift-ci Mar 1, 2018
@swiftlang swiftlang deleted a comment from swift-ci Mar 1, 2018
@milseman
Copy link
Member

milseman commented Mar 1, 2018

@atrick @aschwaighofer is this ok usage of @effects(readonly)?

@jrose-apple
Copy link
Contributor

is this ok usage of @effects(readonly)?

I'm not Andy or Arnold but I say definitely not. @effects(readonly) means that the optimizer can omit the call to the function if its return value isn't used. Even if we don't do that optimization today I really wouldn't want to put it in that way. We can invent something else to avoid retain/releasing the Hasher, or just cross our fingers for MichaelG's +0 work.

@jrose-apple
Copy link
Contributor

Question: why isn't _UnsafeHasher taken as inout, rather than taken/returned?

@lorentey
Copy link
Member Author

lorentey commented Mar 1, 2018

The return value is actually being used here, though; the calls are chained together to prevent invalid optimizations. The hasher state itself is just a bunch of integers; @effects(readonly) prevents ARC traffic protecting components of the Hashable types, not the hasher itself.

@aschwaighofer
Copy link
Contributor

@milseman (@atrick, @eeckstein ) Like you suspected -- I don't think we would want to annotate a function that mutates state as 'readonly' even if it happens that within our existing pipeline this might work for you.

I think we need a @effects(releasenone) and map that to sideeffectsanalysis' 'GlobalEffects.Release=false'. I think that should trick. @eeckstein?

@lorentey
Copy link
Member Author

lorentey commented Mar 1, 2018

inout implies mutations, and every time I tried providing opaque mutating functions on Hasher, I measured major ARC-related slowdowns (as much as +300%, if I recall correctly). Inlineable mutating funcs were fine, but as soon as the body wasn't available, things got really slow.

I am yet to try running this on the +0 branch, but it sure would be nice to replace this with a straightforward interface.

@lorentey
Copy link
Member Author

lorentey commented Mar 1, 2018

@aschwaighofer Ah, GlobalEffects.mayRelease() explains so much; it seems like a new @effects attribute for it would fit the bill perfectly here, and we'd probably use it elsewhere throughout the stdlib.

Replacing the fragile _UnsafeHasher hack with an inout Hasher would allow us to consider promoting hash(into:) into a public replacement for hashValue.

@aschwaighofer
Copy link
Contributor

aschwaighofer commented Mar 1, 2018

@lorentey I have prototyped this in the following branch:
https://github.com/aschwaighofer/swift/tree/wip_effects_release_none

@eeckstein
Copy link
Contributor

I think we need a @effects(releasenone) and map that to sideeffectsanalysis' 'GlobalEffects.Release=false'. I think that should trick. @eeckstein?

Yes, that should work.

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments on the compiler part, which mostly looks good save for the one glaring cheat of synthesizing _hash(into:) whenever we synthesize hashValue.

/// \param hashable The parameter to the call.
static CallExpr* createHasherAppendingCall(ASTContext &C,
Expr* hasher,
Expr* hashable) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: The old style wasn't being consistent about this, but please put pointer *s on the name rather than the type. (That is, space before, not after.)

Expr* hashable) {
// hasher.appending(_:)
SmallVector<Identifier, 1> argNames{Identifier()};
DeclName name(C, C.Id_appending, argNames);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: You don't need a SmallVector for this; just pass {Identifier()} directly to DeclName's constructor. Or if you want to give it a name, declare it as a C array: Identifier argNames[] = …. (As you do below, I see.)

Expr *args[1] = {hashable};
Identifier argLabels[1] = {Identifier()};
return CallExpr::createImplicit(C, appendingCall, C.AllocateCopy(args),
C.AllocateCopy(argLabels));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these will be copied by createImplicit, so you don't need to do another copy here. (ASan will shout at you very fast if I'm wrong about that.)

// otherwise matter.

// hashDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
hashDecl->setAccess(std::max(typeDecl->getFormalAccess(), AccessLevel::FilePrivate));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems very fishy to me. Why can't we use copyFormalAccessAndVersionedAttrFrom? And can that go into the comment?

Copy link
Member Author

@lorentey lorentey Mar 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verily, it is extremely fishy. Adding some clarification:

 if (typeDecl->getFormalAccess() != AccessLevel::Private) {
    hashDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
  } else {
    // FIXME: We want to call copyFormalAccessAndVersionedAttrFrom here, but we
    // can't copy the access level of a private type, because of the backhanded
    // way we synthesize _hash(into:) in deriveHashable -- we need to make sure
    // the resolver will find the new function, so it needs to be at least
    // fileprivate. (The access level of synthesized members doesn't normally
    // matter; they don't go through an access level check after being returned
    // from the synthesizer.)
    hashDecl->setAccess(AccessLevel::FilePrivate);
    if (typeDecl->getAttrs().hasAttribute<VersionedAttr>()) {
      hashDecl->getAttrs().add(new (C) VersionedAttr(/*implicit=*/true));
    }
  }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I'm pretty sure copyFormalAccessAndVersionedAttrFrom should just take a flag that says whether you're copying from the context or from a peer declaration. We've had this problem elsewhere.

SourceLoc(),
resultPat, nullptr,
hashValueDecl);
// hasher
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put a bit more context into comments like this.

else if (auto theStruct = dyn_cast<StructDecl>(type))
hashIntoSynthesizer = &deriveBodyHashable_struct_hashInto;
else
llvm_unreachable("");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please leave an actual comment here, like "attempt to derived hashInto for a type other than a struct or enum".

// would be nicer to remove the default implementation and independently
// synthesize either/both of the two Hashable requirements as needed;
// however, synthesizing methods (as opposed to properties) into imported
// types is not yet fully supported.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want @DougGregor or @huonw to at least glance at this. It seems like it'll work, but I'm not at all sure that your assertion below won't fail.

Copy link
Member Author

@lorentey lorentey Mar 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did find one concrete case so far where this fails: in a particular compiler crasher test where multiple diagnostics preceded the one generated by the sad path here.

I'll submit my alternative implementation as a followup PR soon. The obstacles didn't seem unsurmountable at all, it just took too long for me to understand/fix all of them. The final two issues were a weird IRGen issue with _CFObject's vtable and diagnostic regressions due to canDeriveHashable unconditionally returning true.

@jrose-apple
Copy link
Contributor

cc @allevato

@lorentey lorentey changed the title Use SipHash-1-3 for all hashing, through a resilient hashing interface 🛑 Use SipHash-1-3 for all hashing, through a resilient hashing interface Mar 2, 2018
Copy link
Collaborator

@xwu xwu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some scattered thoughts. Unfortunately not able to spend as much time with this PR as I'd have liked, but overall excited to see a clearly better solution taking shape.

for _ in 0..<${c_rounds} {
_SipHashDetail._sipRound(v0: &v0, v1: &v1, v2: &v2, v3: &v3)
}
% for _ in range(0, c_rounds):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes, do we really need to manually unroll this loop using gyb?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really think so; I intend to run a set of benchmarks for it later (and a separate set for removing @always(__inline) on compress(_:)).

In any case, c_rounds is 1 in SipHash13, so it doesn't really matter.

return hasher
.appending(value)
.appending(isStoredProperty)
.appending(isTableOffset)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice, after the possibility of inout _UnsafeHasher and any coordinating changes to the API are sorted out, if in the final form of the API we could make a single call at the use site. That is, hasher.append{ing}(foo, bar, baz).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do that for an arbitrary number of heterogeneous arguments?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, they'd have to be AnyHashable-boxed. That said, if it's a transparent convenience function I'd expect the whole thing might be optimized away.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had some concerns about the original suggestion because of the fear that an array would need to be heap-allocated for the variable-length argument list. In some cases it looks like the compiler is smart enough to optimize that out—for example, unrolling a loop over those arguments. Is there any way we can guarantee that?

// `AnyHashable`-boxed integers, all integer values are currently required
// to hash exactly the same way as the corresponding (U)Int64 value. To fix
// this, we should introduce a custom AnyHashable box for integer values
// that sign-extends values to 64 bits.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't think it's problematic that equal integer values hash the same way regardless of their bit width.

In fact, it helps us out nicely if ever we want to extend heterogeneous == beyond BinaryInteger types to, say, Array<T> where T: BinaryInteger. I absolutely agree that enabling per-execution variation in hash values for integers is strictly an improvement, but I don't think treating this as a fixme falls into the same category.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It causes potential performance issues, because we're doing a full 64-bit SipHash compress round for every UInt8 value, when we could batch eight of them up into a single round instead. This also applies to Bools, small enums and the like. This effect needs to be measured to quantify it, though; it may not actually turn out to be significant.

Another potential issue is that extending everything to 32/64 bits washes away distinctions between distinct types, perhaps slightly weakening SipHash.

An alternative is to analyze wide integer values and hash them at the shortest width that can contain them -- like the code currently does for Int64 on 32-bit systems. I suspect this would have a measurable effect on Int.hashValue's performance, though -- but this needs to be verified. We'd also have to devise separate API for code that wants to feed a specific series of bytes to the hasher, with no such arbitrary preprocessing.

// The effects attribute is a lie; however, it enables the compiler to
// eliminate unnecessary retain/releases protecting Hashable state around
// calls to `_Hasher.append(_:)`.
//
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a whole bunch of thoughts earlier on this particular design, but I think everyone who's commented is in agreement so far about how we feel about it. Hopefully, the new @effects annotation will fall into place swiftly.

It's not merely for the sake of elegance, but I think the whole design of the API suffers in how comprehensible it is to the reader when what's clearly a stateful object being mutated (after all, the whole point of this PR is to enable a stateful hasher--or at least that's my understanding of it) is masquerading as a value type.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fun thing is that a fully immutable SipHash implementation (with a 100% valid @effect(readonly) declaration) actually performed surprisingly well, considering it had to keep passing around five words. In use it looked exactly the same as this one, except it actually was a real value type.

However, its performance relied on the size/layout of the hasher state being part of the ABI -- hence the clever replacement. Struct resiliency may cause performance problems for the @effects(releasenone) mutating case, too -- we'll have to find out.

static func overrideHashingKey() {
if !hashingKeyOverridden {
// FIXME(hasher): This has to run before creating the first Set/Dictionary
_Hashing.secretKey = (0, 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviously, we need some way to set a deterministic key for testing purposes. I'm not expert in this area by miles, but is it preferable to expose a public, undocumented API which a nefarious third-party could conceivably set at will, or would it be safer to make this, say, a build option for the compiler (say, debug only)? (I genuinely don't know.) I recognize that you didn't create this property originally, but now this clearly "does more."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed! This is a really interesting issue with no fully satisfying solution. We somehow need to pass a flag to the runtime during early process startup to override the random value.

A compile-time option is one way to do this, but I think I'd prefer to just use an environment variable. It is simple, it doesn't need a recompilation, and influencing runtime behavior via the environment has oodles of precedent (not all good, mind you 🙂).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option to consider is to store a copy of the key in every hash table instance. (That may be worth doing anyway to explicitly prepare for the possibility of per-instance keys.) Doing this would eliminate the awful effects of someone changing the master key while a hash table already exists, even if we keep the key accessible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In pure Swift, AFAIK we don't have a way to guarantee that we could read that environment variable and cache its value before any other Swift code has executed. Can we play some static initialization tricks with the C portion of the standard library to do that instead? Like @xwu I understand the need for this behavior but the possibilities for abuse do worry me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The keys are initialized the runtime before main(), in a C++ global static constructor. The code currently uses C++'s Mersenne Twister implementation to generate the two halves of the key. Although we can't run Swift code there, but we could easily call getenv or look up some special symbol, or pretty much do whatever we want:

https://github.com/apple/swift/blob/master/stdlib/public/stubs/GlobalObjects.cpp#L109-L120

We could also make use of HashingDetail.fixedSeedOverride, if we want to keep the original key around for some reason. (The fixed seed override is currently unused.)

It's unlikely we can protect the key from sufficiently motivated Swift code running within the process; thankfully we don't really need to do that -- the key's role is merely to protect hash table performance against data that is fed into the process from external sources.

Copy link
Member

@milseman milseman Mar 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eww, is there any alternative to static constructors? Also important, does that have a corresponding static destructor?

edit: grammar

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that I know of! Do you foresee issues?

We don't have destructors, but these are integer values -- AFAIK, we don't have to run any cleanup for them at exit.

@lorentey
Copy link
Member Author

lorentey commented Mar 2, 2018

While we have the tests passing, let's see if anyone relies on specific hash values:

@swift-ci please test source compatibility

For build progress, see https://ci.swift.org/view/Pull%20Request/job/swift-PR-source-compat-suite/819/

self._core = Core()
}

@inline(__always)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@_inlineable or not?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't @inline(__always) imply @_inlineable? (Still, it is a good idea to make it explicit.)

@lorentey lorentey force-pushed the resilient-hashing branch from 28effb8 to 7edec4d Compare March 7, 2018 19:51
@lorentey lorentey changed the title 🛑 Use SipHash-1-3 for all hashing, through a resilient hashing interface Use SipHash-1-3 for all hashing, through a resilient hashing interface Mar 7, 2018
@lorentey lorentey force-pushed the resilient-hashing branch from 7edec4d to 64679fb Compare March 7, 2018 19:56
@lorentey
Copy link
Member Author

lorentey commented Mar 7, 2018

@swift-ci please test

@lorentey
Copy link
Member Author

lorentey commented Mar 7, 2018

@swift-ci please benchmark

@swift-ci
Copy link
Contributor

swift-ci commented Mar 7, 2018

Build failed
Swift Test Linux Platform
Git Sha - 64679fb6d77b0f6e24b5e202189e0e33339b1b79

@swift-ci
Copy link
Contributor

swift-ci commented Mar 7, 2018

Build failed
Swift Test OS X Platform
Git Sha - 64679fb6d77b0f6e24b5e202189e0e33339b1b79

@swift-ci
Copy link
Contributor

swift-ci commented Mar 8, 2018

Build comment file:

Optimized (O)

Regression (46)
TEST OLD NEW DELTA SPEEDUP
SetIntersect 321 995 +210.0% 0.32x
DictionarySwap 469 1383 +194.9% 0.34x
Histogram 322 761 +136.3% 0.42x
Dictionary4OfObjects 200 445 +122.5% 0.45x
DictionaryGroup 133 293 +120.3% 0.45x
Dictionary4 148 323 +118.2% 0.46x
DictionarySubscriptDefaultMutation 143 309 +116.1% 0.46x
ReversedDictionary 134 279 +108.2% 0.48x
SetExclusiveOr 3379 5988 +77.2% 0.56x
DictionaryRemove 2997 5044 +68.3% 0.59x
SetIntersect_OfObjects 1764 2908 +64.9% 0.61x
SetUnion 3106 5093 +64.0% 0.61x
TwoSum 992 1528 +54.0% 0.65x
RGBHistogram 2207 3371 +52.7% 0.65x
SetExclusiveOr_OfObjects 8744 13168 +50.6% 0.66x
Prims 756 1127 +49.1% 0.67x
PrimsSplit 757 1122 +48.2% 0.67x
Sim2DArray 411 603 +46.7% 0.68x
SetUnion_OfObjects 7163 10498 +46.6% 0.68x
SetIsSubsetOf_OfObjects 363 481 +32.5% 0.75x
Dictionary3 234 301 +28.6% 0.78x
CharacterPropertiesPrecomputed 965 1234 +27.9% 0.78x
DictionaryLiteral 1594 2024 +27.0% 0.79x
WordCountUniqueASCII 1780 2260 +27.0% 0.79x
DictionarySubscriptDefaultMutationArray 488 612 +25.4% 0.80x
Dictionary 507 622 +22.7% 0.82x
DictionarySwapOfObjects 7305 8941 +22.4% 0.82x
DictionarySubscriptDefaultMutationOfObjects 1385 1686 +21.7% 0.82x
DictionaryRemoveOfObjects 23862 27968 +17.2% 0.85x
SetIsSubsetOf 298 348 +16.8% 0.86x
DictionaryGroupOfObjects 1756 2034 +15.8% 0.86x
RemoveWhereSwapInts 19 22 +15.8% 0.86x
CharacterPropertiesStashedMemo 1516 1748 +15.3% 0.87x
ObjectiveCBridgeFromNSSetAnyObjectToString 66109 74733 +13.0% 0.88x (?)
RGBHistogramOfObjects 23570 26248 +11.4% 0.90x
ObjectiveCBridgeStubToNSStringRef 112 124 +10.7% 0.90x
Dictionary3OfObjects 670 741 +10.6% 0.90x
StringComparison_abnormal 743 817 +10.0% 0.91x
DictionarySubscriptDefaultMutationArrayOfObjects 3805 4165 +9.5% 0.91x
PointerArithmetics 31487 34351 +9.1% 0.92x
SuffixCountableRangeLazy 11 12 +9.1% 0.92x
WordCountUniqueUTF16 16193 17479 +7.9% 0.93x (?)
ObjectiveCBridgeStubFromNSStringRef 155 167 +7.7% 0.93x (?)
MapReduceAnyCollection 400 429 +7.2% 0.93x (?)
Dictionary2 1619 1725 +6.5% 0.94x
FrequenciesUsingReduceInto 3105 3297 +6.2% 0.94x (?)
Improvement (14)
TEST OLD NEW DELTA SPEEDUP
WordSplitASCII 21622 7824 -63.8% 2.76x (?)
WordSplitUTF16 23377 10210 -56.3% 2.29x (?)
StringEnumRawValueInitialization 987 802 -18.7% 1.23x
PrefixWhileArray 105 88 -16.2% 1.19x
PrefixWhileCountableRange 53 46 -13.2% 1.15x
ObjectiveCBridgeFromNSSetAnyObject 58214 50821 -12.7% 1.15x (?)
MapReduceLazyCollectionShort 37 34 -8.1% 1.09x
NopDeinit 23470 21586 -8.0% 1.09x
Hanoi 3632 3344 -7.9% 1.09x
IterateData 1364 1271 -6.8% 1.07x
ObjectiveCBridgeToNSDictionary 52487 49300 -6.1% 1.06x (?)
StringComparison_latin1 592 557 -5.9% 1.06x
ObjectiveCBridgeFromNSDictionaryAnyObject 123381 116118 -5.9% 1.06x (?)
LazilyFilteredArrayContains 37453 35459 -5.3% 1.06x
No Changes (325)
TEST OLD NEW DELTA SPEEDUP
AngryPhonebook 3655 3648 -0.2% 1.00x (?)
AnyHashableWithAClass 74839 74738 -0.1% 1.00x (?)
Array2D 2550 2552 +0.1% 1.00x (?)
ArrayAppend 1018 1019 +0.1% 1.00x (?)
ArrayAppendArrayOfInt 794 783 -1.4% 1.01x (?)
ArrayAppendAscii 13333 13241 -0.7% 1.01x (?)
ArrayAppendFromGeneric 795 797 +0.3% 1.00x (?)
ArrayAppendGenericStructs 1410 1421 +0.8% 0.99x (?)
ArrayAppendLatin1 38138 37937 -0.5% 1.01x (?)
ArrayAppendLazyMap 1339 1330 -0.7% 1.01x (?)
ArrayAppendOptionals 1414 1428 +1.0% 0.99x (?)
ArrayAppendRepeatCol 1333 1337 +0.3% 1.00x (?)
ArrayAppendReserved 750 759 +1.2% 0.99x (?)
ArrayAppendSequence 1132 1130 -0.2% 1.00x (?)
ArrayAppendStrings 15208 15240 +0.2% 1.00x (?)
ArrayAppendToFromGeneric 795 796 +0.1% 1.00x (?)
ArrayAppendToGeneric 796 794 -0.3% 1.00x (?)
ArrayAppendUTF16 37187 37389 +0.5% 0.99x (?)
ArrayInClass 85 85 +0.0% 1.00x
ArrayLiteral 0 0 +0.0% 1.00x
ArrayOfGenericPOD2 150 151 +0.7% 0.99x (?)
ArrayOfGenericRef 4421 4422 +0.0% 1.00x (?)
ArrayOfPOD 183 183 +0.0% 1.00x
ArrayOfRef 4367 4377 +0.2% 1.00x (?)
ArrayPlusEqualArrayOfInt 795 796 +0.1% 1.00x (?)
ArrayPlusEqualFiveElementCollection 5528 5552 +0.4% 1.00x (?)
ArrayPlusEqualSingleElementCollection 1022 1026 +0.4% 1.00x (?)
ArrayPlusEqualThreeElements 1647 1648 +0.1% 1.00x (?)
ArraySubscript 1526 1518 -0.5% 1.01x (?)
ArrayValueProp 8 8 +0.0% 1.00x
ArrayValueProp2 8 8 +0.0% 1.00x
ArrayValueProp3 8 8 +0.0% 1.00x
ArrayValueProp4 8 8 +0.0% 1.00x
BinaryFloatingPointConversionFromBinaryInteger 38 39 +2.6% 0.97x
BinaryFloatingPointPropertiesBinade 94 91 -3.2% 1.03x
BinaryFloatingPointPropertiesNextUp 146 143 -2.1% 1.02x
BinaryFloatingPointPropertiesUlp 77 77 +0.0% 1.00x
BitCount 200 202 +1.0% 0.99x (?)
ByteSwap 98 98 +0.0% 1.00x
COWTree 5294 5465 +3.2% 0.97x (?)
CSVParsing 755443 755959 +0.1% 1.00x (?)
CSVParsingAlt 724333 740137 +2.2% 0.98x
CSVParsingAltIndices 356866 360782 +1.1% 0.99x (?)
CStringLongAscii 4770 4769 -0.0% 1.00x (?)
CStringLongNonAscii 2163 2110 -2.5% 1.03x (?)
CStringShortAscii 4734 4751 +0.4% 1.00x (?)
Calculator 652 661 +1.4% 0.99x
CaptureProp 3904 3877 -0.7% 1.01x (?)
CharIndexing_ascii_unicodeScalars 15406 15407 +0.0% 1.00x (?)
CharIndexing_ascii_unicodeScalars_Backwards 14338 14490 +1.1% 0.99x
CharIndexing_chinese_unicodeScalars 11668 11667 -0.0% 1.00x (?)
CharIndexing_chinese_unicodeScalars_Backwards 10865 10982 +1.1% 0.99x (?)
CharIndexing_japanese_unicodeScalars 18446 18444 -0.0% 1.00x (?)
CharIndexing_japanese_unicodeScalars_Backwards 17160 17353 +1.1% 0.99x
CharIndexing_korean_unicodeScalars 14945 14943 -0.0% 1.00x (?)
CharIndexing_korean_unicodeScalars_Backwards 13907 14052 +1.0% 0.99x
CharIndexing_punctuatedJapanese_unicodeScalars 2787 2784 -0.1% 1.00x (?)
CharIndexing_punctuatedJapanese_unicodeScalars_Backwards 2612 2636 +0.9% 0.99x
CharIndexing_punctuated_unicodeScalars 3488 3485 -0.1% 1.00x (?)
CharIndexing_punctuated_unicodeScalars_Backwards 3267 3291 +0.7% 0.99x
CharIndexing_russian_unicodeScalars 12839 12835 -0.0% 1.00x (?)
CharIndexing_russian_unicodeScalars_Backwards 11954 12075 +1.0% 0.99x
CharIndexing_tweet_unicodeScalars 30297 30298 +0.0% 1.00x (?)
CharIndexing_tweet_unicodeScalars_Backwards 28222 28256 +0.1% 1.00x (?)
CharIndexing_utf16_unicodeScalars 20350 20342 -0.0% 1.00x (?)
CharIndexing_utf16_unicodeScalars_Backwards 20916 20991 +0.4% 1.00x (?)
CharIteration_ascii_unicodeScalars 19957 20079 +0.6% 0.99x (?)
CharIteration_ascii_unicodeScalars_Backwards 13515 13507 -0.1% 1.00x (?)
CharIteration_chinese_unicodeScalars 15106 15191 +0.6% 0.99x
CharIteration_chinese_unicodeScalars_Backwards 10242 10238 -0.0% 1.00x (?)
CharIteration_japanese_unicodeScalars 23900 23996 +0.4% 1.00x (?)
CharIteration_japanese_unicodeScalars_Backwards 16171 16172 +0.0% 1.00x (?)
CharIteration_korean_unicodeScalars 19362 19474 +0.6% 0.99x (?)
CharIteration_korean_unicodeScalars_Backwards 13105 13104 -0.0% 1.00x (?)
CharIteration_punctuatedJapanese_unicodeScalars 3582 3612 +0.8% 0.99x
CharIteration_punctuatedJapanese_unicodeScalars_Backwards 2471 2468 -0.1% 1.00x (?)
CharIteration_punctuated_unicodeScalars 4489 4523 +0.8% 0.99x
CharIteration_punctuated_unicodeScalars_Backwards 3085 3082 -0.1% 1.00x (?)
CharIteration_russian_unicodeScalars 16587 16722 +0.8% 0.99x (?)
CharIteration_russian_unicodeScalars_Backwards 11264 11262 -0.0% 1.00x (?)
CharIteration_tweet_unicodeScalars 39611 39640 +0.1% 1.00x (?)
CharIteration_tweet_unicodeScalars_Backwards 26679 26707 +0.1% 1.00x (?)
CharIteration_utf16_unicodeScalars 27027 27095 +0.3% 1.00x (?)
CharIteration_utf16_unicodeScalars_Backwards 17116 17238 +0.7% 0.99x
CharacterLiteralsLarge 5945 6021 +1.3% 0.99x (?)
CharacterLiteralsSmall 410 410 +0.0% 1.00x
CharacterPropertiesFetch 4653 4648 -0.1% 1.00x (?)
CharacterPropertiesStashed 1537 1543 +0.4% 1.00x (?)
Chars 971 963 -0.8% 1.01x
ClassArrayGetter 15 15 +0.0% 1.00x
Combos 462 462 +0.0% 1.00x
DictOfArraysToArrayOfDicts 779 807 +3.6% 0.97x (?)
Dictionary2OfObjects 2974 3083 +3.7% 0.96x
DictionaryBridge 2026 1985 -2.0% 1.02x (?)
DictionaryOfObjects 2176 2268 +4.2% 0.96x
DoubleWidthDivision 0 0 +0.0% 1.00x
DropFirstAnyCollection 101 101 +0.0% 1.00x
DropFirstAnyCollectionLazy 66301 66355 +0.1% 1.00x (?)
DropFirstAnySeqCRangeIter 19780 19789 +0.0% 1.00x (?)
DropFirstAnySeqCRangeIterLazy 19767 19762 -0.0% 1.00x (?)
DropFirstAnySeqCntRange 94 94 +0.0% 1.00x
DropFirstAnySeqCntRangeLazy 94 94 +0.0% 1.00x
DropFirstAnySequence 5148 5213 +1.3% 0.99x (?)
DropFirstAnySequenceLazy 5148 5208 +1.2% 0.99x
DropFirstArray 35 35 +0.0% 1.00x
DropFirstArrayLazy 35 35 +0.0% 1.00x
DropFirstCountableRange 35 35 +0.0% 1.00x
DropFirstCountableRangeLazy 35 35 +0.0% 1.00x
DropFirstSequence 2699 2698 -0.0% 1.00x (?)
DropFirstSequenceLazy 2785 2785 +0.0% 1.00x
DropLastAnyCollection 36 37 +2.8% 0.97x (?)
DropLastAnyCollectionLazy 22491 22305 -0.8% 1.01x (?)
DropLastAnySeqCRangeIter 3924 3953 +0.7% 0.99x (?)
DropLastAnySeqCRangeIterLazy 3922 3960 +1.0% 0.99x (?)
DropLastAnySeqCntRange 29 29 +0.0% 1.00x
DropLastAnySeqCntRangeLazy 29 29 +0.0% 1.00x
DropLastAnySequence 5227 5290 +1.2% 0.99x
DropLastAnySequenceLazy 5321 5387 +1.2% 0.99x (?)
DropLastCountableRange 11 11 +0.0% 1.00x
DropLastCountableRangeLazy 11 11 +0.0% 1.00x
DropLastSequence 682 689 +1.0% 0.99x (?)
DropLastSequenceLazy 682 689 +1.0% 0.99x
DropWhileAnyCollection 125 125 +0.0% 1.00x
DropWhileAnyCollectionLazy 166 166 +0.0% 1.00x
DropWhileAnySeqCRangeIter 16335 16455 +0.7% 0.99x (?)
DropWhileAnySeqCRangeIterLazy 166 166 +0.0% 1.00x
DropWhileAnySeqCntRange 117 117 +0.0% 1.00x
DropWhileAnySeqCntRangeLazy 166 166 +0.0% 1.00x
DropWhileAnySequence 5988 5928 -1.0% 1.01x
DropWhileAnySequenceLazy 1857 1856 -0.1% 1.00x (?)
DropWhileArrayLazy 129 129 +0.0% 1.00x
DropWhileCountableRange 36 36 +0.0% 1.00x
DropWhileCountableRangeLazy 111 111 +0.0% 1.00x
DropWhileSequence 1343 1343 +0.0% 1.00x
DropWhileSequenceLazy 88 88 +0.0% 1.00x
EqualStringSubstring 48 48 +0.0% 1.00x
EqualSubstringString 48 48 +0.0% 1.00x
EqualSubstringSubstring 47 48 +2.1% 0.98x
EqualSubstringSubstringGenericEquatable 48 47 -2.1% 1.02x
ErrorHandling 2281 2304 +1.0% 0.99x (?)
ExclusivityGlobal 5 5 +0.0% 1.00x
ExclusivityIndependent 2 2 +0.0% 1.00x
FilterEvenUsingReduce 1310 1313 +0.2% 1.00x (?)
FilterEvenUsingReduceInto 151 150 -0.7% 1.01x (?)
FrequenciesUsingReduce 6544 6691 +2.2% 0.98x (?)
HashTest 1742 1760 +1.0% 0.99x (?)
Integrate 336 336 +0.0% 1.00x
Join 372 374 +0.5% 0.99x (?)
LazilyFilteredArrays 65236 65329 +0.1% 1.00x (?)
LazilyFilteredRange 3874 3825 -1.3% 1.01x
LessSubstringSubstring 47 48 +2.1% 0.98x
LessSubstringSubstringGenericComparable 48 48 +0.0% 1.00x
LinkedList 7538 7531 -0.1% 1.00x (?)
LuhnAlgoEager 571 570 -0.2% 1.00x (?)
LuhnAlgoLazy 569 569 +0.0% 1.00x
MapReduce 398 398 +0.0% 1.00x
MapReduceAnyCollectionShort 2303 2246 -2.5% 1.03x (?)
MapReduceClass 3049 3029 -0.7% 1.01x
MapReduceClassShort 4613 4589 -0.5% 1.01x (?)
MapReduceLazyCollection 13 13 +0.0% 1.00x
MapReduceLazySequence 86 86 +0.0% 1.00x
MapReduceSequence 455 454 -0.2% 1.00x (?)
MapReduceShort 2010 2036 +1.3% 0.99x (?)
MapReduceShortString 21 21 +0.0% 1.00x
MapReduceString 80 81 +1.2% 0.99x (?)
Memset 216 217 +0.5% 1.00x (?)
MonteCarloE 10346 10307 -0.4% 1.00x (?)
MonteCarloPi 42879 42686 -0.5% 1.00x (?)
NSDictionaryCastToSwift 5440 5442 +0.0% 1.00x (?)
NSError 297 295 -0.7% 1.01x (?)
NSStringConversion 283 292 +3.2% 0.97x
NibbleSort 3691 3710 +0.5% 0.99x (?)
ObjectAllocation 184 184 +0.0% 1.00x
ObjectiveCBridgeFromNSArrayAnyObject 20175 20307 +0.7% 0.99x (?)
ObjectiveCBridgeFromNSArrayAnyObjectForced 4093 4057 -0.9% 1.01x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToString 37998 38356 +0.9% 0.99x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToStringForced 33170 33502 +1.0% 0.99x (?)
ObjectiveCBridgeFromNSSetAnyObjectForced 4273 4242 -0.7% 1.01x (?)
ObjectiveCBridgeFromNSString 1331 1311 -1.5% 1.02x (?)
ObjectiveCBridgeFromNSStringForced 2448 2396 -2.1% 1.02x (?)
ObjectiveCBridgeStubDataAppend 3882 3888 +0.2% 1.00x (?)
ObjectiveCBridgeStubDateMutation 257 257 +0.0% 1.00x
ObjectiveCBridgeStubFromArrayOfNSString 25351 25718 +1.4% 0.99x (?)
ObjectiveCBridgeStubFromNSDate 4016 3959 -1.4% 1.01x (?)
ObjectiveCBridgeStubFromNSString 848 862 +1.7% 0.98x (?)
ObjectiveCBridgeStubNSDataAppend 2469 2502 +1.3% 0.99x (?)
ObjectiveCBridgeStubNSDateMutationRef 12963 13043 +0.6% 0.99x (?)
ObjectiveCBridgeStubToArrayOfNSString 28803 28753 -0.2% 1.00x (?)
ObjectiveCBridgeStubToNSDate 14710 14723 +0.1% 1.00x (?)
ObjectiveCBridgeStubToNSDateRef 3423 3397 -0.8% 1.01x (?)
ObjectiveCBridgeStubToNSString 1519 1523 +0.3% 1.00x (?)
ObjectiveCBridgeStubURLAppendPath 318504 319682 +0.4% 1.00x (?)
ObjectiveCBridgeStubURLAppendPathRef 327188 322125 -1.5% 1.02x (?)
ObjectiveCBridgeToNSArray 29101 28788 -1.1% 1.01x (?)
ObjectiveCBridgeToNSSet 40721 41026 +0.7% 0.99x (?)
ObjectiveCBridgeToNSString 1294 1295 +0.1% 1.00x (?)
ObserverClosure 2158 2167 +0.4% 1.00x (?)
ObserverForwarderStruct 1002 1047 +4.5% 0.96x (?)
ObserverPartiallyAppliedMethod 3736 3771 +0.9% 0.99x (?)
ObserverUnappliedMethod 2367 2383 +0.7% 0.99x (?)
OpenClose 125 125 +0.0% 1.00x
PartialApplyDynamicType 0 0 +0.0% 1.00x
Phonebook 3917 3854 -1.6% 1.02x
PolymorphicCalls 25 25 +0.0% 1.00x
PopFrontArray 1865 1935 +3.8% 0.96x (?)
PopFrontArrayGeneric 1884 1875 -0.5% 1.00x (?)
PopFrontUnsafePointer 8750 8760 +0.1% 1.00x (?)
PrefixAnyCollection 101 101 +0.0% 1.00x
PrefixAnyCollectionLazy 67203 66417 -1.2% 1.01x (?)
PrefixAnySeqCRangeIter 15200 15380 +1.2% 0.99x (?)
PrefixAnySeqCRangeIterLazy 15199 15376 +1.2% 0.99x
PrefixAnySeqCntRange 94 94 +0.0% 1.00x
PrefixAnySeqCntRangeLazy 94 94 +0.0% 1.00x
PrefixAnySequence 4732 4573 -3.4% 1.03x
PrefixAnySequenceLazy 4628 4587 -0.9% 1.01x
PrefixArray 35 35 +0.0% 1.00x
PrefixArrayLazy 35 35 +0.0% 1.00x
PrefixCountableRange 35 35 +0.0% 1.00x
PrefixCountableRangeLazy 35 35 +0.0% 1.00x
PrefixSequence 1325 1325 +0.0% 1.00x
PrefixSequenceLazy 1413 1413 +0.0% 1.00x
PrefixWhileAnyCollection 172 171 -0.6% 1.01x (?)
PrefixWhileAnyCollectionLazy 108 108 +0.0% 1.00x
PrefixWhileAnySeqCRangeIter 9711 9891 +1.9% 0.98x (?)
PrefixWhileAnySeqCRangeIterLazy 90 90 +0.0% 1.00x
PrefixWhileAnySeqCntRange 164 164 +0.0% 1.00x
PrefixWhileAnySeqCntRangeLazy 108 108 +0.0% 1.00x
PrefixWhileAnySequence 10885 10944 +0.5% 0.99x (?)
PrefixWhileAnySequenceLazy 1393 1393 +0.0% 1.00x
PrefixWhileArrayLazy 70 70 +0.0% 1.00x
PrefixWhileCountableRangeLazy 35 35 +0.0% 1.00x
PrefixWhileSequence 380 380 +0.0% 1.00x
PrefixWhileSequenceLazy 52 52 +0.0% 1.00x
QueueConcrete 1308 1307 -0.1% 1.00x (?)
QueueGeneric 1118 1119 +0.1% 1.00x (?)
RC4 171 176 +2.9% 0.97x
RangeAssignment 350 351 +0.3% 1.00x (?)
RangeIterationSigned 200 200 +0.0% 1.00x
RangeIterationSigned64 200 200 +0.0% 1.00x
RangeIterationUnsigned 200 200 +0.0% 1.00x
RangeReplaceableCollectionPlusDefault 982 978 -0.4% 1.00x (?)
RecursiveOwnedParameter 2323 2322 -0.0% 1.00x (?)
RemoveWhereFilterInts 45 43 -4.4% 1.05x
RemoveWhereFilterString 296 293 -1.0% 1.01x (?)
RemoveWhereFilterStrings 433 433 +0.0% 1.00x
RemoveWhereMoveInts 17 17 +0.0% 1.00x
RemoveWhereMoveStrings 519 520 +0.2% 1.00x (?)
RemoveWhereQuadraticInts 1285 1286 +0.1% 1.00x (?)
RemoveWhereQuadraticString 209 205 -1.9% 1.02x (?)
RemoveWhereQuadraticStrings 2755 2764 +0.3% 1.00x (?)
RemoveWhereSwapStrings 848 851 +0.4% 1.00x (?)
ReversedArray 57 57 +0.0% 1.00x
ReversedBidirectional 17466 17327 -0.8% 1.01x (?)
RomanNumbers 112636 112177 -0.4% 1.00x (?)
SequenceAlgosAnySequence 10982 10895 -0.8% 1.01x (?)
SequenceAlgosArray 1565 1579 +0.9% 0.99x (?)
SequenceAlgosContiguousArray 1579 1578 -0.1% 1.00x (?)
SequenceAlgosList 1353 1349 -0.3% 1.00x (?)
SequenceAlgosRange 4294 4295 +0.0% 1.00x (?)
SequenceAlgosUnfoldSequence 1079 1079 +0.0% 1.00x
SevenBoom 1501 1489 -0.8% 1.01x (?)
SortLargeExistentials 6751 6719 -0.5% 1.00x (?)
SortLettersInPlace 1121 1121 +0.0% 1.00x
SortSortedStrings 997 1029 +3.2% 0.97x (?)
SortStrings 1783 1838 +3.1% 0.97x
SortStringsUnicode 2537 2507 -1.2% 1.01x
StackPromo 22368 21964 -1.8% 1.02x
StaticArray 9 9 +0.0% 1.00x
StrComplexWalk 1563 1559 -0.3% 1.00x (?)
StrToInt 2175 2072 -4.7% 1.05x
StringAdder 4207 4233 +0.6% 0.99x (?)
StringBuilder 1388 1391 +0.2% 1.00x (?)
StringBuilderLong 1071 1061 -0.9% 1.01x (?)
StringBuilderWithLongSubstring 1175 1211 +3.1% 0.97x (?)
StringComparison_ascii 1023 1024 +0.1% 1.00x (?)
StringComparison_emoji 803 782 -2.6% 1.03x
StringComparison_fastPrenormal 756 739 -2.2% 1.02x
StringComparison_longSharedPrefix 898 898 +0.0% 1.00x
StringComparison_nonBMPSlowestPrenormal 1574 1533 -2.6% 1.03x
StringComparison_slowerPrenormal 1686 1649 -2.2% 1.02x
StringComparison_zalgo 114212 114287 +0.1% 1.00x (?)
StringEdits 116732 121515 +4.1% 0.96x (?)
StringEqualPointerComparison 315 314 -0.3% 1.00x (?)
StringFromLongWholeSubstring 21 21 +0.0% 1.00x
StringFromLongWholeSubstringGeneric 10 10 +0.0% 1.00x
StringHasPrefixAscii 1346 1345 -0.1% 1.00x (?)
StringHasPrefixUnicode 27340 27516 +0.6% 0.99x (?)
StringHasSuffixAscii 1460 1460 +0.0% 1.00x
StringHasSuffixUnicode 84426 84776 +0.4% 1.00x (?)
StringInterpolation 11017 11048 +0.3% 1.00x (?)
StringInterpolationManySmallSegments 16485 16530 +0.3% 1.00x (?)
StringInterpolationSmall 8596 8544 -0.6% 1.01x (?)
StringMatch 7621 7344 -3.6% 1.04x
StringRemoveDupes 1193 1245 +4.4% 0.96x
StringUTF16Builder 2402 2383 -0.8% 1.01x (?)
StringUTF16SubstringBuilder 4855 4885 +0.6% 0.99x (?)
StringWalk 1472 1457 -1.0% 1.01x (?)
StringWithCString 43169 43179 +0.0% 1.00x (?)
StringWordBuilder 1750 1732 -1.0% 1.01x (?)
StringWordBuilderReservingCapacity 1302 1283 -1.5% 1.01x (?)
SubstringComparable 41 41 +0.0% 1.00x
SubstringEqualString 539 518 -3.9% 1.04x
SubstringEquatable 1348 1343 -0.4% 1.00x (?)
SubstringFromLongString 10 10 +0.0% 1.00x
SubstringFromLongStringGeneric 69 69 +0.0% 1.00x
SuffixAnyCollection 43 42 -2.3% 1.02x
SuffixAnyCollectionLazy 22502 22361 -0.6% 1.01x (?)
SuffixAnySeqCRangeIter 4119 4153 +0.8% 0.99x (?)
SuffixAnySeqCRangeIterLazy 4105 4146 +1.0% 0.99x (?)
SuffixAnySeqCntRange 35 35 +0.0% 1.00x
SuffixAnySeqCntRangeLazy 35 35 +0.0% 1.00x
SuffixAnySequence 5208 5298 +1.7% 0.98x
SuffixAnySequenceLazy 5333 5428 +1.8% 0.98x
SuffixCountableRange 11 11 +0.0% 1.00x
SuffixSequence 3873 3893 +0.5% 0.99x (?)
SuffixSequenceLazy 3869 3902 +0.9% 0.99x (?)
SumUsingReduce 97 97 +0.0% 1.00x
SumUsingReduceInto 97 97 +0.0% 1.00x
SuperChars 41246 39963 -3.1% 1.03x (?)
TypeFlood 0 0 +0.0% 1.00x
UTF8Decode 327 327 +0.0% 1.00x
Walsh 410 416 +1.5% 0.99x (?)
WordCountHistogramASCII 7458 7154 -4.1% 1.04x (?)
WordCountHistogramUTF16 23057 23410 +1.5% 0.98x (?)
XorLoop 394 393 -0.3% 1.00x (?)

Unoptimized (Onone)

Regression (44)
TEST OLD NEW DELTA SPEEDUP
StringRemoveDupes 1428 1699 +19.0% 0.84x
Dictionary4OfObjects 1897 2166 +14.2% 0.88x
CharIndexing_tweet_unicodeScalars 715945 816288 +14.0% 0.88x (?)
CharIndexing_russian_unicodeScalars 301084 342779 +13.8% 0.88x (?)
CharIndexing_chinese_unicodeScalars 273925 311327 +13.7% 0.88x
SetIntersect_OfObjects 12779 14516 +13.6% 0.88x
CharIndexing_ascii_unicodeScalars 362968 411621 +13.4% 0.88x
CharIndexing_korean_unicodeScalars 353013 398858 +13.0% 0.89x
CharIndexing_punctuatedJapanese_unicodeScalars 63985 71938 +12.4% 0.89x
ObjectiveCBridgeFromNSSetAnyObjectToString 77574 87187 +12.4% 0.89x
Dictionary4 1248 1398 +12.0% 0.89x
TwoSum 4253 4757 +11.9% 0.89x
CharIndexing_japanese_unicodeScalars 439329 490646 +11.7% 0.90x
ArrayOfPOD 757 844 +11.5% 0.90x
SetUnion 12215 13607 +11.4% 0.90x
ObjectiveCBridgeFromNSSetAnyObjectForced 6628 7372 +11.2% 0.90x (?)
SetIsSubsetOf_OfObjects 1666 1849 +11.0% 0.90x
XorLoop 24950 27595 +10.6% 0.90x (?)
CharIndexing_utf16_unicodeScalars 309918 342579 +10.5% 0.90x (?)
SetExclusiveOr 18040 19940 +10.5% 0.90x
SetExclusiveOr_OfObjects 42756 47245 +10.5% 0.90x
CharIndexing_punctuated_unicodeScalars 82010 90539 +10.4% 0.91x (?)
SetUnion_OfObjects 29666 32689 +10.2% 0.91x
CharacterPropertiesPrecomputed 4299 4703 +9.4% 0.91x
Dictionary2 2964 3242 +9.4% 0.91x (?)
CharacterPropertiesStashedMemo 5130 5556 +8.3% 0.92x
DictionaryRemoveOfObjects 51873 56063 +8.1% 0.93x (?)
StringComparison_abnormal 1404 1513 +7.8% 0.93x (?)
StringEdits 324777 349618 +7.6% 0.93x (?)
DropFirstAnyCollectionLazy 105019 112191 +6.8% 0.94x (?)
StringUTF16SubstringBuilder 20687 22032 +6.5% 0.94x (?)
StringBuilderWithLongSubstring 4474 4763 +6.5% 0.94x (?)
Dictionary3OfObjects 2327 2471 +6.2% 0.94x (?)
DropLastAnyCollectionLazy 33709 35776 +6.1% 0.94x (?)
ObjectiveCBridgeToNSSet 42554 45089 +6.0% 0.94x
ObjectiveCBridgeStubToNSDate 15956 16899 +5.9% 0.94x (?)
WordCountUniqueUTF16 27633 29265 +5.9% 0.94x (?)
CharIndexing_punctuatedJapanese_unicodeScalars_Backwards 77907 82483 +5.9% 0.94x (?)
RGBHistogramOfObjects 96002 101638 +5.9% 0.94x
DictOfArraysToArrayOfDicts 3415 3615 +5.9% 0.94x
StringInterpolation 13316 14066 +5.6% 0.95x (?)
DropLastAnySeqCRangeIter 38489 40623 +5.5% 0.95x
CharIndexing_russian_unicodeScalars_Backwards 368728 388934 +5.5% 0.95x (?)
StringBuilder 6870 7242 +5.4% 0.95x (?)
Improvement (16)
TEST OLD NEW DELTA SPEEDUP
WordSplitASCII 26563 10697 -59.7% 2.48x
WordSplitUTF16 27441 15792 -42.5% 1.74x
DictionarySwapOfObjects 24873 21412 -13.9% 1.16x (?)
PrefixWhileArray 12301 10917 -11.3% 1.13x
StringEqualPointerComparison 3692 3352 -9.2% 1.10x
LuhnAlgoLazy 5234 4764 -9.0% 1.10x (?)
StringInterpolationSmall 11975 10994 -8.2% 1.09x
CharIteration_punctuatedJapanese_unicodeScalars_Backwards 58696 53962 -8.1% 1.09x
RemoveWhereSwapStrings 7228 6683 -7.5% 1.08x
WordCountHistogramASCII 47520 44043 -7.3% 1.08x (?)
ObjectiveCBridgeStubURLAppendPath 346085 321884 -7.0% 1.08x (?)
BinaryFloatingPointPropertiesNextUp 146 137 -6.2% 1.07x
Chars 43093 40515 -6.0% 1.06x
EqualStringSubstring 96 91 -5.2% 1.05x
Calculator 1554 1474 -5.1% 1.05x
CStringLongNonAscii 2222 2116 -4.8% 1.05x
No Changes (325)
TEST OLD NEW DELTA SPEEDUP
AngryPhonebook 5246 5132 -2.2% 1.02x (?)
AnyHashableWithAClass 89735 90687 +1.1% 0.99x (?)
Array2D 632892 632782 -0.0% 1.00x (?)
ArrayAppend 4556 4557 +0.0% 1.00x (?)
ArrayAppendArrayOfInt 865 848 -2.0% 1.02x (?)
ArrayAppendAscii 40943 40751 -0.5% 1.00x (?)
ArrayAppendFromGeneric 874 871 -0.3% 1.00x (?)
ArrayAppendGenericStructs 1505 1506 +0.1% 1.00x (?)
ArrayAppendLatin1 64385 64376 -0.0% 1.00x (?)
ArrayAppendLazyMap 175175 175359 +0.1% 1.00x (?)
ArrayAppendOptionals 1506 1506 +0.0% 1.00x
ArrayAppendRepeatCol 181978 182687 +0.4% 1.00x (?)
ArrayAppendReserved 4167 4168 +0.0% 1.00x (?)
ArrayAppendSequence 156088 159917 +2.5% 0.98x
ArrayAppendStrings 15329 15375 +0.3% 1.00x (?)
ArrayAppendToFromGeneric 868 851 -2.0% 1.02x (?)
ArrayAppendToGeneric 871 874 +0.3% 1.00x
ArrayAppendUTF16 64110 64739 +1.0% 0.99x
ArrayInClass 6194 6214 +0.3% 1.00x (?)
ArrayLiteral 1815 1812 -0.2% 1.00x (?)
ArrayOfGenericPOD2 1128 1127 -0.1% 1.00x (?)
ArrayOfGenericRef 10200 10184 -0.2% 1.00x (?)
ArrayOfRef 9395 9349 -0.5% 1.00x (?)
ArrayPlusEqualArrayOfInt 868 866 -0.2% 1.00x (?)
ArrayPlusEqualFiveElementCollection 239059 238444 -0.3% 1.00x (?)
ArrayPlusEqualSingleElementCollection 235798 237229 +0.6% 0.99x (?)
ArrayPlusEqualThreeElements 9395 9345 -0.5% 1.01x (?)
ArraySubscript 116671 116131 -0.5% 1.00x (?)
ArrayValueProp 3670 3719 +1.3% 0.99x (?)
ArrayValueProp2 16641 16605 -0.2% 1.00x (?)
ArrayValueProp3 4178 4197 +0.5% 1.00x (?)
ArrayValueProp4 4121 4174 +1.3% 0.99x
BinaryFloatingPointConversionFromBinaryInteger 6224 6231 +0.1% 1.00x (?)
BinaryFloatingPointPropertiesBinade 83 83 +0.0% 1.00x
BinaryFloatingPointPropertiesUlp 143 137 -4.2% 1.04x
BitCount 7881 7660 -2.8% 1.03x
ByteSwap 9218 9193 -0.3% 1.00x (?)
COWTree 11655 11537 -1.0% 1.01x (?)
CSVParsing 2534317 2571409 +1.5% 0.99x
CSVParsingAlt 1295881 1314790 +1.5% 0.99x
CSVParsingAltIndices 2235731 2316794 +3.6% 0.97x (?)
CStringLongAscii 4760 4828 +1.4% 0.99x
CStringShortAscii 7543 7687 +1.9% 0.98x (?)
CaptureProp 267229 268570 +0.5% 1.00x
CharIndexing_ascii_unicodeScalars_Backwards 443729 464596 +4.7% 0.96x (?)
CharIndexing_chinese_unicodeScalars_Backwards 337358 352861 +4.6% 0.96x (?)
CharIndexing_japanese_unicodeScalars_Backwards 532740 558604 +4.9% 0.95x (?)
CharIndexing_korean_unicodeScalars_Backwards 439603 454671 +3.4% 0.97x (?)
CharIndexing_punctuated_unicodeScalars_Backwards 99150 101823 +2.7% 0.97x (?)
CharIndexing_tweet_unicodeScalars_Backwards 886777 923790 +4.2% 0.96x (?)
CharIndexing_utf16_unicodeScalars_Backwards 364340 375752 +3.1% 0.97x (?)
CharIteration_ascii_unicodeScalars 156743 157338 +0.4% 1.00x (?)
CharIteration_ascii_unicodeScalars_Backwards 307927 309252 +0.4% 1.00x (?)
CharIteration_chinese_unicodeScalars 118499 119506 +0.8% 0.99x (?)
CharIteration_chinese_unicodeScalars_Backwards 230333 231694 +0.6% 0.99x (?)
CharIteration_japanese_unicodeScalars 187636 188707 +0.6% 0.99x (?)
CharIteration_japanese_unicodeScalars_Backwards 369712 370050 +0.1% 1.00x (?)
CharIteration_korean_unicodeScalars 151280 152993 +1.1% 0.99x (?)
CharIteration_korean_unicodeScalars_Backwards 298088 295657 -0.8% 1.01x (?)
CharIteration_punctuatedJapanese_unicodeScalars 28154 28403 +0.9% 0.99x (?)
CharIteration_punctuated_unicodeScalars 35286 35598 +0.9% 0.99x (?)
CharIteration_punctuated_unicodeScalars_Backwards 67763 68369 +0.9% 0.99x (?)
CharIteration_russian_unicodeScalars 129989 131249 +1.0% 0.99x (?)
CharIteration_russian_unicodeScalars_Backwards 257826 254814 -1.2% 1.01x (?)
CharIteration_tweet_unicodeScalars 309040 311216 +0.7% 0.99x (?)
CharIteration_tweet_unicodeScalars_Backwards 604960 607103 +0.4% 1.00x (?)
CharIteration_utf16_unicodeScalars 132068 132734 +0.5% 0.99x (?)
CharIteration_utf16_unicodeScalars_Backwards 259616 260697 +0.4% 1.00x (?)
CharacterLiteralsLarge 5916 5986 +1.2% 0.99x
CharacterLiteralsSmall 684 665 -2.8% 1.03x
CharacterPropertiesFetch 5443 5673 +4.2% 0.96x (?)
CharacterPropertiesStashed 2349 2397 +2.0% 0.98x (?)
ClassArrayGetter 988 986 -0.2% 1.00x (?)
Combos 2185 2228 +2.0% 0.98x (?)
Dictionary 2672 2781 +4.1% 0.96x (?)
Dictionary2OfObjects 5681 5961 +4.9% 0.95x (?)
Dictionary3 1372 1397 +1.8% 0.98x (?)
DictionaryBridge 2143 2117 -1.2% 1.01x (?)
DictionaryGroup 4253 4350 +2.3% 0.98x
DictionaryGroupOfObjects 7448 7577 +1.7% 0.98x (?)
DictionaryLiteral 8835 9051 +2.4% 0.98x (?)
DictionaryOfObjects 6264 6497 +3.7% 0.96x (?)
DictionaryRemove 19307 19947 +3.3% 0.97x
DictionarySubscriptDefaultMutation 2123 2228 +4.9% 0.95x (?)
DictionarySubscriptDefaultMutationArray 2334 2426 +3.9% 0.96x
DictionarySubscriptDefaultMutationArrayOfObjects 9110 9456 +3.8% 0.96x (?)
DictionarySubscriptDefaultMutationOfObjects 5668 5841 +3.1% 0.97x (?)
DictionarySwap 5837 6107 +4.6% 0.96x
DoubleWidthDivision 0 0 +0.0% 1.00x
DropFirstAnyCollection 14252 14249 -0.0% 1.00x (?)
DropFirstAnySeqCRangeIter 21878 21851 -0.1% 1.00x (?)
DropFirstAnySeqCRangeIterLazy 21579 21740 +0.7% 0.99x
DropFirstAnySeqCntRange 14171 14319 +1.0% 0.99x
DropFirstAnySeqCntRangeLazy 14200 14211 +0.1% 1.00x (?)
DropFirstAnySequence 11669 11753 +0.7% 0.99x
DropFirstAnySequenceLazy 11806 11823 +0.1% 1.00x (?)
DropFirstArray 4096 4065 -0.8% 1.01x
DropFirstArrayLazy 26382 26357 -0.1% 1.00x (?)
DropFirstCountableRange 328 326 -0.6% 1.01x
DropFirstCountableRangeLazy 27904 27992 +0.3% 1.00x (?)
DropFirstSequence 11414 11320 -0.8% 1.01x
DropFirstSequenceLazy 11360 11517 +1.4% 0.99x
DropLastAnyCollection 4765 4768 +0.1% 1.00x (?)
DropLastAnySeqCRangeIterLazy 38515 39488 +2.5% 0.98x
DropLastAnySeqCntRange 4752 4763 +0.2% 1.00x (?)
DropLastAnySeqCntRangeLazy 4736 4757 +0.4% 1.00x
DropLastAnySequence 29894 29717 -0.6% 1.01x (?)
DropLastAnySequenceLazy 30055 29687 -1.2% 1.01x (?)
DropLastCountableRange 113 113 +0.0% 1.00x
DropLastCountableRangeLazy 9339 9341 +0.0% 1.00x (?)
DropLastSequence 29712 29653 -0.2% 1.00x (?)
DropLastSequenceLazy 29607 29762 +0.5% 0.99x
DropWhileAnyCollection 17903 17989 +0.5% 1.00x (?)
DropWhileAnyCollectionLazy 20453 20833 +1.9% 0.98x
DropWhileAnySeqCRangeIter 23339 23192 -0.6% 1.01x
DropWhileAnySeqCRangeIterLazy 20562 20877 +1.5% 0.98x
DropWhileAnySeqCntRange 17867 17972 +0.6% 0.99x
DropWhileAnySeqCntRangeLazy 20394 20915 +2.6% 0.98x
DropWhileAnySequence 13447 13529 +0.6% 0.99x (?)
DropWhileAnySequenceLazy 11436 11496 +0.5% 0.99x (?)
DropWhileArrayLazy 14620 14639 +0.1% 1.00x (?)
DropWhileCountableRange 4109 4148 +0.9% 0.99x
DropWhileCountableRangeLazy 20069 20223 +0.8% 0.99x
DropWhileSequence 13139 13223 +0.6% 0.99x
DropWhileSequenceLazy 10943 11311 +3.4% 0.97x
EqualSubstringString 96 96 +0.0% 1.00x
EqualSubstringSubstring 91 91 +0.0% 1.00x
EqualSubstringSubstringGenericEquatable 98 97 -1.0% 1.01x
ErrorHandling 6988 7111 +1.8% 0.98x (?)
ExclusivityGlobal 183 186 +1.6% 0.98x
ExclusivityIndependent 68 70 +2.9% 0.97x (?)
FilterEvenUsingReduce 3661 3683 +0.6% 0.99x (?)
FilterEvenUsingReduceInto 1954 1958 +0.2% 1.00x (?)
FrequenciesUsingReduce 10524 10832 +2.9% 0.97x (?)
FrequenciesUsingReduceInto 5406 5665 +4.8% 0.95x (?)
Hanoi 20600 20459 -0.7% 1.01x (?)
HashTest 21639 22061 +2.0% 0.98x (?)
Histogram 6792 7053 +3.8% 0.96x
Integrate 848 838 -1.2% 1.01x (?)
IterateData 6027 5833 -3.2% 1.03x (?)
Join 1140 1128 -1.1% 1.01x (?)
LazilyFilteredArrayContains 797807 801388 +0.4% 1.00x
LazilyFilteredArrays 1479181 1471996 -0.5% 1.00x (?)
LazilyFilteredRange 485741 495742 +2.1% 0.98x
LessSubstringSubstring 89 92 +3.4% 0.97x (?)
LessSubstringSubstringGenericComparable 93 96 +3.2% 0.97x (?)
LinkedList 31960 31910 -0.2% 1.00x
LuhnAlgoEager 5031 5107 +1.5% 0.99x (?)
MapReduce 26268 26804 +2.0% 0.98x (?)
MapReduceAnyCollection 25915 25942 +0.1% 1.00x (?)
MapReduceAnyCollectionShort 36745 36402 -0.9% 1.01x (?)
MapReduceClass 31349 30397 -3.0% 1.03x (?)
MapReduceClassShort 40631 42027 +3.4% 0.97x (?)
MapReduceLazyCollection 23261 23164 -0.4% 1.00x (?)
MapReduceLazyCollectionShort 33709 33724 +0.0% 1.00x (?)
MapReduceLazySequence 19052 18830 -1.2% 1.01x
MapReduceSequence 30430 30452 +0.1% 1.00x (?)
MapReduceShort 37943 37917 -0.1% 1.00x (?)
MapReduceShortString 232 223 -3.9% 1.04x (?)
MapReduceString 1836 1813 -1.3% 1.01x
Memset 44717 44703 -0.0% 1.00x (?)
MonteCarloE 1243100 1236647 -0.5% 1.01x (?)
MonteCarloPi 5664991 5618878 -0.8% 1.01x
NSDictionaryCastToSwift 6617 6693 +1.1% 0.99x (?)
NSError 745 714 -4.2% 1.04x (?)
NSStringConversion 326 338 +3.7% 0.96x
NibbleSort 434123 435902 +0.4% 1.00x (?)
NopDeinit 166502 169183 +1.6% 0.98x (?)
ObjectAllocation 1392 1378 -1.0% 1.01x (?)
ObjectiveCBridgeFromNSArrayAnyObject 23421 23307 -0.5% 1.00x (?)
ObjectiveCBridgeFromNSArrayAnyObjectForced 8810 8679 -1.5% 1.02x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToString 41113 40918 -0.5% 1.00x (?)
ObjectiveCBridgeFromNSArrayAnyObjectToStringForced 36131 35326 -2.2% 1.02x (?)
ObjectiveCBridgeFromNSDictionaryAnyObject 132355 128381 -3.0% 1.03x (?)
ObjectiveCBridgeFromNSSetAnyObject 63229 61156 -3.3% 1.03x (?)
ObjectiveCBridgeFromNSString 3125 3142 +0.5% 0.99x (?)
ObjectiveCBridgeFromNSStringForced 2773 2737 -1.3% 1.01x (?)
ObjectiveCBridgeStubDataAppend 4453 4333 -2.7% 1.03x (?)
ObjectiveCBridgeStubDateMutation 601 605 +0.7% 0.99x
ObjectiveCBridgeStubFromArrayOfNSString 27794 26514 -4.6% 1.05x (?)
ObjectiveCBridgeStubFromNSDate 4824 4913 +1.8% 0.98x (?)
ObjectiveCBridgeStubFromNSString 915 888 -3.0% 1.03x (?)
ObjectiveCBridgeStubFromNSStringRef 204 196 -3.9% 1.04x
ObjectiveCBridgeStubNSDataAppend 2956 2942 -0.5% 1.00x (?)
ObjectiveCBridgeStubNSDateMutationRef 14903 15614 +4.8% 0.95x (?)
ObjectiveCBridgeStubToArrayOfNSString 28885 28853 -0.1% 1.00x (?)
ObjectiveCBridgeStubToNSDateRef 3481 3475 -0.2% 1.00x (?)
ObjectiveCBridgeStubToNSString 1573 1558 -1.0% 1.01x (?)
ObjectiveCBridgeStubToNSStringRef 153 153 +0.0% 1.00x
ObjectiveCBridgeStubURLAppendPathRef 335213 325137 -3.0% 1.03x (?)
ObjectiveCBridgeToNSArray 29813 29306 -1.7% 1.02x (?)
ObjectiveCBridgeToNSDictionary 54223 52686 -2.8% 1.03x
ObjectiveCBridgeToNSString 1351 1347 -0.3% 1.00x (?)
ObserverClosure 6357 6345 -0.2% 1.00x (?)
ObserverForwarderStruct 4435 4440 +0.1% 1.00x (?)
ObserverPartiallyAppliedMethod 7912 7858 -0.7% 1.01x (?)
ObserverUnappliedMethod 8095 8084 -0.1% 1.00x (?)
OpenClose 547 545 -0.4% 1.00x
PartialApplyDynamicType 40696 41402 +1.7% 0.98x
Phonebook 20114 20091 -0.1% 1.00x (?)
PointerArithmetics 117411 112192 -4.4% 1.05x
PolymorphicCalls 6257 6343 +1.4% 0.99x (?)
PopFrontArray 4709 4612 -2.1% 1.02x (?)
PopFrontArrayGeneric 5854 5754 -1.7% 1.02x
PopFrontUnsafePointer 11050 11063 +0.1% 1.00x (?)
PrefixAnyCollection 14257 14223 -0.2% 1.00x
PrefixAnyCollectionLazy 102270 104798 +2.5% 0.98x (?)
PrefixAnySeqCRangeIter 17509 17528 +0.1% 1.00x (?)
PrefixAnySeqCRangeIterLazy 17405 17566 +0.9% 0.99x (?)
PrefixAnySeqCntRange 14231 14192 -0.3% 1.00x
PrefixAnySeqCntRangeLazy 14221 14182 -0.3% 1.00x (?)
PrefixAnySequence 9804 9796 -0.1% 1.00x (?)
PrefixAnySequenceLazy 9800 9861 +0.6% 0.99x
PrefixArray 4252 4067 -4.4% 1.05x
PrefixArrayLazy 26282 26803 +2.0% 0.98x
PrefixCountableRange 326 332 +1.8% 0.98x
PrefixCountableRangeLazy 27967 27948 -0.1% 1.00x (?)
PrefixSequence 9509 9544 +0.4% 1.00x (?)
PrefixSequenceLazy 9507 9583 +0.8% 0.99x
PrefixWhileAnyCollection 25262 25495 +0.9% 0.99x
PrefixWhileAnyCollectionLazy 17067 17180 +0.7% 0.99x
PrefixWhileAnySeqCRangeIter 34576 35251 +2.0% 0.98x
PrefixWhileAnySeqCRangeIterLazy 17086 17378 +1.7% 0.98x
PrefixWhileAnySeqCntRange 25314 25469 +0.6% 0.99x (?)
PrefixWhileAnySeqCntRangeLazy 16933 17414 +2.8% 0.97x
PrefixWhileAnySequence 27028 27060 +0.1% 1.00x (?)
PrefixWhileAnySequenceLazy 10360 10346 -0.1% 1.00x (?)
PrefixWhileArrayLazy 13732 13711 -0.2% 1.00x (?)
PrefixWhileCountableRange 11587 11732 +1.3% 0.99x (?)
PrefixWhileCountableRangeLazy 17131 17333 +1.2% 0.99x (?)
PrefixWhileSequence 26717 26748 +0.1% 1.00x (?)
PrefixWhileSequenceLazy 10099 10092 -0.1% 1.00x (?)
Prims 9659 10167 +5.3% 0.95x
PrimsSplit 9709 10061 +3.6% 0.97x
QueueConcrete 15200 15111 -0.6% 1.01x (?)
QueueGeneric 19418 19380 -0.2% 1.00x (?)
RC4 17057 16683 -2.2% 1.02x
RGBHistogram 26280 27427 +4.4% 0.96x
RangeAssignment 2273 2216 -2.5% 1.03x
RangeIterationSigned 16378 16711 +2.0% 0.98x (?)
RangeIterationSigned64 39954 40052 +0.2% 1.00x (?)
RangeIterationUnsigned 35744 35764 +0.1% 1.00x (?)
RangeReplaceableCollectionPlusDefault 7875 8084 +2.7% 0.97x (?)
RecursiveOwnedParameter 7948 7873 -0.9% 1.01x
RemoveWhereFilterInts 2130 2134 +0.2% 1.00x (?)
RemoveWhereFilterString 1511 1523 +0.8% 0.99x (?)
RemoveWhereFilterStrings 2991 2998 +0.2% 1.00x
RemoveWhereMoveInts 3332 3330 -0.1% 1.00x (?)
RemoveWhereMoveStrings 4036 4037 +0.0% 1.00x (?)
RemoveWhereQuadraticInts 7812 7864 +0.7% 0.99x
RemoveWhereQuadraticString 2342 2354 +0.5% 0.99x (?)
RemoveWhereQuadraticStrings 9473 9525 +0.5% 0.99x
RemoveWhereSwapInts 5988 5978 -0.2% 1.00x
ReversedArray 13645 13791 +1.1% 0.99x (?)
ReversedBidirectional 43911 44127 +0.5% 1.00x (?)
ReversedDictionary 23542 24668 +4.8% 0.95x
RomanNumbers 1170521 1183834 +1.1% 0.99x (?)
SequenceAlgosAnySequence 11488 11576 +0.8% 0.99x (?)
SequenceAlgosArray 802813 801156 -0.2% 1.00x
SequenceAlgosContiguousArray 346440 348788 +0.7% 0.99x (?)
SequenceAlgosList 8350 8383 +0.4% 1.00x
SequenceAlgosRange 1117537 1129160 +1.0% 0.99x
SequenceAlgosUnfoldSequence 6065 6117 +0.9% 0.99x
SetIntersect 9246 9674 +4.6% 0.96x
SetIsSubsetOf 1479 1530 +3.4% 0.97x (?)
SevenBoom 1639 1658 +1.2% 0.99x (?)
Sim2DArray 43597 43625 +0.1% 1.00x (?)
SortLargeExistentials 15434 15452 +0.1% 1.00x (?)
SortLettersInPlace 2671 2718 +1.8% 0.98x (?)
SortSortedStrings 1069 1050 -1.8% 1.02x
SortStrings 2066 2023 -2.1% 1.02x
SortStringsUnicode 2873 2774 -3.4% 1.04x
StackPromo 92080 91422 -0.7% 1.01x (?)
StaticArray 2601 2599 -0.1% 1.00x (?)
StrComplexWalk 6226 6234 +0.1% 1.00x (?)
StrToInt 57646 58476 +1.4% 0.99x (?)
StringAdder 4716 4718 +0.0% 1.00x (?)
StringBuilderLong 2762 2773 +0.4% 1.00x (?)
StringComparison_ascii 9827 9786 -0.4% 1.00x
StringComparison_emoji 2137 2122 -0.7% 1.01x (?)
StringComparison_fastPrenormal 5372 5354 -0.3% 1.00x (?)
StringComparison_latin1 4163 4164 +0.0% 1.00x (?)
StringComparison_longSharedPrefix 2520 2510 -0.4% 1.00x (?)
StringComparison_nonBMPSlowestPrenormal 3924 3900 -0.6% 1.01x
StringComparison_slowerPrenormal 4440 4404 -0.8% 1.01x (?)
StringComparison_zalgo 116043 117044 +0.9% 0.99x
StringEnumRawValueInitialization 18202 18092 -0.6% 1.01x (?)
StringFromLongWholeSubstring 22 22 +0.0% 1.00x
StringFromLongWholeSubstringGeneric 199 200 +0.5% 1.00x
StringHasPrefixAscii 3152 3027 -4.0% 1.04x
StringHasPrefixUnicode 29168 29291 +0.4% 1.00x (?)
StringHasSuffixAscii 3202 3095 -3.3% 1.03x
StringHasSuffixUnicode 86382 86606 +0.3% 1.00x (?)
StringInterpolationManySmallSegments 19733 19656 -0.4% 1.00x (?)
StringMatch 33544 33545 +0.0% 1.00x (?)
StringUTF16Builder 7616 7639 +0.3% 1.00x (?)
StringWalk 12578 12820 +1.9% 0.98x
StringWithCString 39451 39487 +0.1% 1.00x (?)
StringWordBuilder 2550 2535 -0.6% 1.01x (?)
StringWordBuilderReservingCapacity 2235 2220 -0.7% 1.01x
SubstringComparable 2091 2109 +0.9% 0.99x (?)
SubstringEqualString 1918 1925 +0.4% 1.00x (?)
SubstringEquatable 6088 6079 -0.1% 1.00x (?)
SubstringFromLongString 24 24 +0.0% 1.00x
SubstringFromLongStringGeneric 103 104 +1.0% 0.99x
SuffixAnyCollection 4776 4762 -0.3% 1.00x (?)
SuffixAnyCollectionLazy 34564 35377 +2.4% 0.98x (?)
SuffixAnySeqCRangeIter 34197 34826 +1.8% 0.98x
SuffixAnySeqCRangeIterLazy 34255 34571 +0.9% 0.99x
SuffixAnySeqCntRange 4757 4743 -0.3% 1.00x
SuffixAnySeqCntRangeLazy 4749 4752 +0.1% 1.00x (?)
SuffixAnySequence 25561 25592 +0.1% 1.00x (?)
SuffixAnySequenceLazy 25570 25662 +0.4% 1.00x (?)
SuffixCountableRange 112 115 +2.7% 0.97x
SuffixCountableRangeLazy 9323 9326 +0.0% 1.00x (?)
SuffixSequence 25510 25538 +0.1% 1.00x (?)
SuffixSequenceLazy 25511 26196 +2.7% 0.97x (?)
SumUsingReduce 167647 169209 +0.9% 0.99x (?)
SumUsingReduceInto 163701 163416 -0.2% 1.00x (?)
SuperChars 129808 126734 -2.4% 1.02x (?)
TypeFlood 156 162 +3.8% 0.96x (?)
UTF8Decode 30896 30929 +0.1% 1.00x (?)
Walsh 12029 12043 +0.1% 1.00x (?)
WordCountHistogramUTF16 71961 73351 +1.9% 0.98x (?)
WordCountUniqueASCII 8151 8547 +4.9% 0.95x
Hardware Overview
  Model Name: Mac Pro
  Model Identifier: MacPro6,1
  Processor Name: 12-Core Intel Xeon E5
  Processor Speed: 2.7 GHz
  Number of Processors: 1
  Total Number of Cores: 12
  L2 Cache (per Core): 256 KB
  L3 Cache: 30 MB
  Memory: 64 GB

@hartbit
Copy link
Contributor

hartbit commented Mar 8, 2018

@lorentey I'd really love having Hasher and hash(into:) become public. It's a much better API for getting hashing correct.

@lorentey
Copy link
Member Author

lorentey commented Mar 8, 2018

@swift-ci please smoke test

@lorentey
Copy link
Member Author

lorentey commented Mar 9, 2018

OK, the Linux failure uncovered an issue with my synthesizing _hash(into:) into classes. I need more time to investigate it, so I'll take out the synthesizer part for now. It'll return in a followup PR.

Landing the rest of this change will unblock some stdlib work, so it seems worth doing.

lorentey added 3 commits March 9, 2018 14:34
Introduce _Hasher, representing an opaque hash compression function.

Add the method _hash(into:) as a Hashable requirement, decoupling the choice of hash function from Hashable's implementation. The default implementation of _hash(into:) has a default implementation that simply feeds hashValue to the hasher.

Add _hash(into:) implementations for the default integer types. Note that Int.hashValue does not return self anymore.

Add struct _LegacyHasher, emulating Swift 4.1 hashes in the new interface.
This switches the primary hashing interface from hashValue to _hash(into:).
@lorentey lorentey force-pushed the resilient-hashing branch from 64679fb to 233beb0 Compare March 9, 2018 14:37
@lorentey
Copy link
Member Author

lorentey commented Mar 9, 2018

@swift-ci please smoke test

lorentey added 2 commits March 9, 2018 14:48
Beyond switching hashing algorithms, this also enables per-execution hash seeds, fulfilling a long-standing prophecy in Hashable’s documentation.

To reduce the possibility of random test failures, StdlibUnittest’s TestSuite overrides the random hash seed on initialization.

rdar://problem/24109692
rdar://problem/35052153
@lorentey lorentey force-pushed the resilient-hashing branch from 233beb0 to e03cb13 Compare March 9, 2018 15:11
@lorentey
Copy link
Member Author

lorentey commented Mar 9, 2018

@swift-ci please smoke test

@lorentey
Copy link
Member Author

lorentey commented Mar 9, 2018

@swift-ci please test

@lorentey
Copy link
Member Author

lorentey commented Mar 9, 2018

Compiler support is blocked by https://bugs.swift.org/browse/SR-7156 -- synthesizing _hash(into:) into swift-corelibs-foundation's NSObject currently breaks all of its subclasses in Foundation. 😢

However, I believe the stdlib changes are ready to merge now.

@lorentey lorentey merged commit ab0c74b into swiftlang:master Mar 9, 2018
@milseman
Copy link
Member

milseman commented Mar 9, 2018

@hartbit sounds like a good pitch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants