main.swift 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Copyright 2019, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import ArgumentParser
  17. import GRPC
  18. import Logging
  19. let smallRequest = String(repeating: "x", count: 8)
  20. let largeRequest = String(repeating: "x", count: 1 << 16) // 65k
  21. // Add benchmarks here!
  22. func runBenchmarks(spec: TestSpec) {
  23. measureAndPrint(
  24. description: "unary_10k_small_requests",
  25. benchmark: Unary(requests: 10000, text: smallRequest),
  26. spec: spec
  27. )
  28. measureAndPrint(
  29. description: "unary_10k_long_requests",
  30. benchmark: Unary(requests: 10000, text: largeRequest),
  31. spec: spec
  32. )
  33. measureAndPrint(
  34. description: "bidi_10k_small_requests_in_batches_of_1",
  35. benchmark: Bidi(requests: 10000, text: smallRequest, batchSize: 1),
  36. spec: spec
  37. )
  38. measureAndPrint(
  39. description: "bidi_10k_small_requests_in_batches_of_5",
  40. benchmark: Bidi(requests: 10000, text: smallRequest, batchSize: 5),
  41. spec: spec
  42. )
  43. measureAndPrint(
  44. description: "bidi_1k_large_requests_in_batches_of_5",
  45. benchmark: Bidi(requests: 1000, text: largeRequest, batchSize: 1),
  46. spec: spec
  47. )
  48. measureAndPrint(
  49. description: "embedded_client_unary_10k_small_requests",
  50. benchmark: EmbeddedClientThroughput(requests: 10000, text: smallRequest),
  51. spec: spec
  52. )
  53. measureAndPrint(
  54. description: "embedded_client_unary_1k_large_requests",
  55. benchmark: EmbeddedClientThroughput(requests: 1000, text: largeRequest),
  56. spec: spec
  57. )
  58. measureAndPrint(
  59. description: "embedded_client_unary_1k_large_requests_1k_frames",
  60. benchmark: EmbeddedClientThroughput(
  61. requests: 1000,
  62. text: largeRequest,
  63. maxResponseFrameSize: 1024
  64. ),
  65. spec: spec
  66. )
  67. measureAndPrint(
  68. description: "embedded_server_unary_10k_small_requests",
  69. benchmark: EmbeddedServerChildChannelBenchmark(
  70. mode: .unary(rpcs: 10000),
  71. text: smallRequest
  72. ),
  73. spec: spec
  74. )
  75. measureAndPrint(
  76. description: "embedded_server_client_streaming_1_rpc_10k_small_requests",
  77. benchmark: EmbeddedServerChildChannelBenchmark(
  78. mode: .clientStreaming(rpcs: 1, requestsPerRPC: 10000),
  79. text: smallRequest
  80. ),
  81. spec: spec
  82. )
  83. measureAndPrint(
  84. description: "embedded_server_client_streaming_10k_rpcs_1_small_requests",
  85. benchmark: EmbeddedServerChildChannelBenchmark(
  86. mode: .clientStreaming(rpcs: 10000, requestsPerRPC: 1),
  87. text: smallRequest
  88. ),
  89. spec: spec
  90. )
  91. measureAndPrint(
  92. description: "embedded_server_server_streaming_1_rpc_10k_small_responses",
  93. benchmark: EmbeddedServerChildChannelBenchmark(
  94. mode: .serverStreaming(rpcs: 1, responsesPerRPC: 10000),
  95. text: smallRequest
  96. ),
  97. spec: spec
  98. )
  99. measureAndPrint(
  100. description: "embedded_server_server_streaming_10k_rpcs_1_small_response",
  101. benchmark: EmbeddedServerChildChannelBenchmark(
  102. mode: .serverStreaming(rpcs: 10000, responsesPerRPC: 1),
  103. text: smallRequest
  104. ),
  105. spec: spec
  106. )
  107. measureAndPrint(
  108. description: "embedded_server_bidi_1_rpc_10k_small_requests",
  109. benchmark: EmbeddedServerChildChannelBenchmark(
  110. mode: .bidirectional(rpcs: 1, requestsPerRPC: 10000),
  111. text: smallRequest
  112. ),
  113. spec: spec
  114. )
  115. measureAndPrint(
  116. description: "embedded_server_bidi_10k_rpcs_1_small_request",
  117. benchmark: EmbeddedServerChildChannelBenchmark(
  118. mode: .bidirectional(rpcs: 10000, requestsPerRPC: 1),
  119. text: smallRequest
  120. ),
  121. spec: spec
  122. )
  123. measureAndPrint(
  124. description: "percent_encode_decode_10k_status_messages",
  125. benchmark: PercentEncoding(iterations: 10000, requiresEncoding: true),
  126. spec: spec
  127. )
  128. measureAndPrint(
  129. description: "percent_encode_decode_10k_ascii_status_messages",
  130. benchmark: PercentEncoding(iterations: 10000, requiresEncoding: false),
  131. spec: spec
  132. )
  133. }
  134. struct TestSpec {
  135. var action: Action
  136. var repeats: Int
  137. init(action: Action, repeats: Int = 10) {
  138. self.action = action
  139. self.repeats = repeats
  140. }
  141. enum Action {
  142. /// Run the benchmark with the given filter.
  143. case run(Filter)
  144. /// List all benchmarks.
  145. case list
  146. }
  147. enum Filter {
  148. /// Run all tests.
  149. case all
  150. /// Run the tests which match the given descriptions.
  151. case some([String])
  152. func shouldRun(_ description: String) -> Bool {
  153. switch self {
  154. case .all:
  155. return true
  156. case let .some(selectedTests):
  157. return selectedTests.contains(description)
  158. }
  159. }
  160. }
  161. }
  162. struct PerformanceTests: ParsableCommand {
  163. @Flag(name: .shortAndLong, help: "List all available tests")
  164. var list: Bool = false
  165. @Flag(name: .shortAndLong, help: "Run all tests")
  166. var all: Bool = false
  167. @Argument(help: "The tests to run")
  168. var tests: [String] = []
  169. func run() throws {
  170. let spec: TestSpec
  171. if self.list {
  172. spec = TestSpec(action: .list)
  173. } else if self.all {
  174. spec = TestSpec(action: .run(.all))
  175. } else {
  176. spec = TestSpec(action: .run(.some(self.tests)))
  177. }
  178. runBenchmarks(spec: spec)
  179. }
  180. }
  181. assert({
  182. print("⚠️ WARNING: YOU ARE RUNNING IN DEBUG MODE ⚠️")
  183. return true
  184. }())
  185. PerformanceTests.main()