main.swift 5.6 KB

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