|
| 1 | +# Naming Convention |
| 2 | + |
| 3 | +Historically, benchmark names in the Swift Benchmark Suite were derived from the |
| 4 | +name of the `runFunction`, which by convention started with prefix `run_`, |
| 5 | +followed by the benchmark name. Therefore most of the legacy benchmark names |
| 6 | +conform to the [`UpperCamelCase`](http://bit.ly/UpperCamelCase) convention. |
| 7 | +After introduction of |
| 8 | +[`BenchmarkInfo`](https://github.com/apple/swift/pull/12048) |
| 9 | +to describe the benchmark metadata, names can be any string. To create more |
| 10 | +cohesive and well structured system, names of newly added benchmarks should meet |
| 11 | +the following set of requirements: |
| 12 | + |
| 13 | +<ul> |
| 14 | +<li> |
| 15 | +<!-- The <li> content with <details> is pre-formatted as HTML, to work around |
| 16 | +Markdown renderer interrupting the paragraph, which creates an ugly gap. --> |
| 17 | +<strong>Letters, numbers and dots.</strong> Start with short unique name in |
| 18 | +<code>UpperCamelCase</code>. |
| 19 | +For a family of benchmarks, separate the name components with periods. |
| 20 | +<details> |
| 21 | + |
| 22 | +Very long compound names using `UpperCamelCase` are hard to read. Use `.` to |
| 23 | +increase readability and structure. |
| 24 | + |
| 25 | +Prefer unique and creative name to nondescript generic term, unless the |
| 26 | +benchmark is testing individual method on a concrete type. |
| 27 | + |
| 28 | +```` |
| 29 | +⛔️ Dictionary2 |
| 30 | +✅ AngryPhonebook |
| 31 | +✅ Dictionary.AnyHashable.String.update |
| 32 | +✅ Array.append.Array.Int |
| 33 | +```` |
| 34 | + |
| 35 | +Benchmark names are used to run individual tests when passed as command line |
| 36 | +arguments to the benchmark driver. Stick to ASCII letters, numbers and period. |
| 37 | +Exceptionally: |
| 38 | + |
| 39 | +* Use **`-`** only to denote control flow constructs like `for-in` or `if-let`. |
| 40 | +* Use **`!`** and **`?`** for optional types, conditional or forced downcasting, |
| 41 | +optional chaining etc. |
| 42 | + |
| 43 | +```` |
| 44 | +✅ Array.append.Array.Int? |
| 45 | +✅ Flatten.Array.Tuple4.for-in.reserved |
| 46 | +✅ Bridging.NSArray.as!.Array.NSString |
| 47 | +```` |
| 48 | + |
| 49 | +Note: Special characters that could be interpreted by the shell require escaping |
| 50 | +(`\!`) or quoting the name, when running such benchmarks individually. |
| 51 | + |
| 52 | +</details><p><!-- spacer --></p></li> |
| 53 | +<li> |
| 54 | +<strong>Use groups and variants</strong> to structure the benchmark family by |
| 55 | +degrees of freedom (e.g. different types implementing a protocol, value vs. |
| 56 | +reference types etc.). Use <strong>numbered suffixes</strong> to denote |
| 57 | +differently sized variants. |
| 58 | +<details> |
| 59 | + |
| 60 | +Benchmarks in a family can be grouped by the tested operation, method or varied |
| 61 | +by types and different workload sizes. It might be necessary to abbreviate some |
| 62 | +names to fit the size limit, based on the longest combination. Choose consistent |
| 63 | +names for the components throughout all members in the family, to allow for |
| 64 | +relative comparison across the different axis of variation. |
| 65 | + |
| 66 | +```` |
| 67 | +✅ Seq.dropFirst.Array |
| 68 | +✅ Seq.dropLast.Range.lazy |
| 69 | +✅ Seq.dropWhile.UnfoldSeq |
| 70 | +✅ Seq.prefix.AnySeq.RangeIter.lazy |
| 71 | +✅ Seq.prefixWhile.AnyCol.Array |
| 72 | +✅ Seq.suffix.AnySeq.UnfoldSeq.lazy |
| 73 | +
|
| 74 | +✅ Existential.Array.ConditionalShift.Ref1 |
| 75 | +✅ Existential.Array.Mutating.Ref2 |
| 76 | +✅ Existential.Array.method.1x.Ref3 |
| 77 | +✅ Existential.Array.method.2x.Ref4 |
| 78 | +✅ Existential.Array.Shift.Val0 |
| 79 | +✅ Existential.MutatingAndNonMutating.Val1 |
| 80 | +✅ Existential.Mutating.Val2 |
| 81 | +✅ Existential.method.1x.Val3 |
| 82 | +✅ Existential.method.2x.Val4 |
| 83 | +✅ Existential.Pass2.method.1x.Ref1 |
| 84 | +✅ Existential.Pass2.method.2x.Ref2 |
| 85 | +
|
| 86 | +✅ Set.isSubset.Int25 |
| 87 | +✅ Set.symmetricDifference.Int50 |
| 88 | +```` |
| 89 | + |
| 90 | +</details><p><!-- spacer --></p></li> |
| 91 | +<li> |
| 92 | +<strong>Groups and types are <code>UpperCase</code>, methods are |
| 93 | +<code>lowerCase</code>.</strong> |
| 94 | +<details> |
| 95 | + |
| 96 | +Use periods to separate the name components in variants derived from specialised |
| 97 | +generic types or significant method chains. |
| 98 | + |
| 99 | +```` |
| 100 | +⛔️ InsertCharacterTowardsEndIndexNonASCII |
| 101 | +```` |
| 102 | + |
| 103 | +There's no need to be literal with type names. **Be descriptive**: |
| 104 | + |
| 105 | +```` |
| 106 | +✅ String.insert.EmojiChar.NearEnd |
| 107 | +✅ String.insert.ASCIIChar.StartIndex |
| 108 | +✅ Flatten.Array.Tuple4.lazy.flatMap |
| 109 | +```` |
| 110 | + |
| 111 | +</details><p><!-- spacer --></p></li> |
| 112 | +<li> |
| 113 | +<strong>Keep it short.</strong> 40 characters at most. Abbreviate if necessary. |
| 114 | +<details> |
| 115 | + |
| 116 | +Benchmarking results are reported on GitHub and very long names are causing |
| 117 | +horizontal table scrolling which unfortunately obscures the columns with actual |
| 118 | +measurements. Fixed upper size limit also helps with the formatted console |
| 119 | +output, when measuring locally. *It is more important for benchmark's name to be |
| 120 | +unique and short, than overly descriptive.* |
| 121 | + |
| 122 | +Prefer concise names for potential benchmark family extensions. Leave out the |
| 123 | +nested types from variants if they aren't strictly necessary for disambiguation. |
| 124 | +If there's potentially valuable future variant, like testing `ContiguousArray`, |
| 125 | +keep the `Array` now, allowing for addition of `ContArr` variants later. |
| 126 | + |
| 127 | +Use **`Val`** and **`Ref`** as short descriptors for variants that compare value |
| 128 | +types (`struct`, `Int`) with reference types (often named with `Class` in the |
| 129 | +legacy-style). |
| 130 | +Prefer **`Char`** to `Character`, which can be combined with codepage or |
| 131 | +language prefix/suffix when necessary (`EmojiChar`, `ASCIIChar`). For benchmarks |
| 132 | +that measure `String`'s Unicode performance for various languages, use |
| 133 | +the [three letter codes](https://en.wikipedia.org/wiki/ISO_639-3) instead of |
| 134 | +spelling out the whole language names. |
| 135 | + |
| 136 | +When necessary, use *consistent* abbreviations like `Str` and `Arr` within the |
| 137 | +benchmark family, to fit a system with descriptive names into 40 characters: |
| 138 | + |
| 139 | +```` |
| 140 | +✅ Bridging.NSDict.as!.Dict.NSString.NSNum |
| 141 | +✅ Seq.prefixWhile.AnySeq.UnfoldSeq.lazy |
| 142 | +```` |
| 143 | + |
| 144 | +As a last resort, use *numbered suffixes* to disambiguate between benchmarks |
| 145 | +with minor implementation variations. |
| 146 | + |
| 147 | +</details></li> |
| 148 | +</ul> |
| 149 | + |
| 150 | +Technically, the benchmark's name must match the following regular expression: |
| 151 | +`[A-Z][a-zA-Z0-9\-.!?]+` |
0 commit comments