main.swift 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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 EchoModel
  17. import Foundation
  18. import GRPC
  19. import Logging
  20. import NIO
  21. import NIOSSL
  22. let smallRequest = String(repeating: "x", count: 8)
  23. let largeRequest = String(repeating: "x", count: 1 << 16) // 65k
  24. // Add benchmarks here!
  25. func runBenchmarks(spec: TestSpec) {
  26. measureAndPrint(
  27. description: "unary_10k_small_requests",
  28. benchmark: Unary(requests: 10000, text: smallRequest),
  29. spec: spec
  30. )
  31. measureAndPrint(
  32. description: "unary_10k_long_requests",
  33. benchmark: Unary(requests: 10000, text: largeRequest),
  34. spec: spec
  35. )
  36. measureAndPrint(
  37. description: "bidi_10k_small_requests_in_batches_of_1",
  38. benchmark: Bidi(requests: 10000, text: smallRequest, batchSize: 1),
  39. spec: spec
  40. )
  41. measureAndPrint(
  42. description: "bidi_10k_small_requests_in_batches_of_5",
  43. benchmark: Bidi(requests: 10000, text: smallRequest, batchSize: 5),
  44. spec: spec
  45. )
  46. measureAndPrint(
  47. description: "bidi_1k_large_requests_in_batches_of_5",
  48. benchmark: Bidi(requests: 1000, text: largeRequest, batchSize: 1),
  49. spec: spec
  50. )
  51. measureAndPrint(
  52. description: "embedded_client_unary_10k_small_requests",
  53. benchmark: EmbeddedClientThroughput(requests: 10000, text: smallRequest),
  54. spec: spec
  55. )
  56. measureAndPrint(
  57. description: "embedded_client_unary_1k_large_requests",
  58. benchmark: EmbeddedClientThroughput(requests: 1000, text: largeRequest),
  59. spec: spec
  60. )
  61. measureAndPrint(
  62. description: "embedded_client_unary_1k_large_requests_1k_frames",
  63. benchmark: EmbeddedClientThroughput(
  64. requests: 1000,
  65. text: largeRequest,
  66. maxResponseFrameSize: 1024
  67. ),
  68. spec: spec
  69. )
  70. measureAndPrint(
  71. description: "embedded_server_unary_10k_small_requests",
  72. benchmark: EmbeddedServerChildChannelBenchmark(
  73. mode: .unary(rpcs: 10000),
  74. text: smallRequest
  75. ),
  76. spec: spec
  77. )
  78. measureAndPrint(
  79. description: "embedded_server_client_streaming_1_rpc_10k_small_requests",
  80. benchmark: EmbeddedServerChildChannelBenchmark(
  81. mode: .clientStreaming(rpcs: 1, requestsPerRPC: 10000),
  82. text: smallRequest
  83. ),
  84. spec: spec
  85. )
  86. measureAndPrint(
  87. description: "embedded_server_client_streaming_10k_rpcs_1_small_requests",
  88. benchmark: EmbeddedServerChildChannelBenchmark(
  89. mode: .clientStreaming(rpcs: 10000, requestsPerRPC: 1),
  90. text: smallRequest
  91. ),
  92. spec: spec
  93. )
  94. measureAndPrint(
  95. description: "embedded_server_server_streaming_1_rpc_10k_small_responses",
  96. benchmark: EmbeddedServerChildChannelBenchmark(
  97. mode: .serverStreaming(rpcs: 1, responsesPerRPC: 10000),
  98. text: smallRequest
  99. ),
  100. spec: spec
  101. )
  102. measureAndPrint(
  103. description: "embedded_server_server_streaming_10k_rpcs_1_small_response",
  104. benchmark: EmbeddedServerChildChannelBenchmark(
  105. mode: .serverStreaming(rpcs: 10000, responsesPerRPC: 1),
  106. text: smallRequest
  107. ),
  108. spec: spec
  109. )
  110. measureAndPrint(
  111. description: "embedded_server_bidi_1_rpc_10k_small_requests",
  112. benchmark: EmbeddedServerChildChannelBenchmark(
  113. mode: .bidirectional(rpcs: 1, requestsPerRPC: 10000),
  114. text: smallRequest
  115. ),
  116. spec: spec
  117. )
  118. measureAndPrint(
  119. description: "embedded_server_bidi_10k_rpcs_1_small_request",
  120. benchmark: EmbeddedServerChildChannelBenchmark(
  121. mode: .bidirectional(rpcs: 10000, requestsPerRPC: 1),
  122. text: smallRequest
  123. ),
  124. spec: spec
  125. )
  126. measureAndPrint(
  127. description: "percent_encode_decode_10k_status_messages",
  128. benchmark: PercentEncoding(iterations: 10000, requiresEncoding: true),
  129. spec: spec
  130. )
  131. measureAndPrint(
  132. description: "percent_encode_decode_10k_ascii_status_messages",
  133. benchmark: PercentEncoding(iterations: 10000, requiresEncoding: false),
  134. spec: spec
  135. )
  136. }
  137. struct TestSpec {
  138. var action: Action
  139. var repeats: Int
  140. init(action: Action, repeats: Int = 10) {
  141. self.action = action
  142. self.repeats = repeats
  143. }
  144. enum Action {
  145. /// Run the benchmark with the given filter.
  146. case run(Filter)
  147. /// List all benchmarks.
  148. case list
  149. }
  150. enum Filter {
  151. /// Run all tests.
  152. case all
  153. /// Run the tests which match the given descriptions.
  154. case some([String])
  155. func shouldRun(_ description: String) -> Bool {
  156. switch self {
  157. case .all:
  158. return true
  159. case let .some(selectedTests):
  160. return selectedTests.contains(description)
  161. }
  162. }
  163. }
  164. }
  165. func usage(program: String) -> String {
  166. return """
  167. USAGE: \(program) [-alh] [BENCHMARK ...]
  168. OPTIONS:
  169. The following options are available:
  170. -a Run all benchmarks. (Also: '--all')
  171. -l List all benchmarks. (Also: '--list')
  172. -h Prints this message. (Also: '--help')
  173. """
  174. }
  175. func main(args: [String]) {
  176. // Quieten the logs.
  177. LoggingSystem.bootstrap {
  178. var handler = StreamLogHandler.standardOutput(label: $0)
  179. handler.logLevel = .critical
  180. return handler
  181. }
  182. let program = args.first!
  183. let arg0 = args.dropFirst().first
  184. switch arg0 {
  185. case "-h", "--help":
  186. print(usage(program: program))
  187. case "-l", "--list":
  188. runBenchmarks(spec: TestSpec(action: .list))
  189. case "-a", "-all":
  190. runBenchmarks(spec: TestSpec(action: .run(.all)))
  191. default:
  192. // This must be a list of benchmarks to run.
  193. let tests = Array(args.dropFirst())
  194. if tests.isEmpty {
  195. print(usage(program: program))
  196. } else {
  197. runBenchmarks(spec: TestSpec(action: .run(.some(tests))))
  198. }
  199. }
  200. }
  201. assert({
  202. print("⚠️ WARNING: YOU ARE RUNNING IN DEBUG MODE ⚠️")
  203. return true
  204. }())
  205. main(args: CommandLine.arguments)