main.swift 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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 EchoImplementation
  17. import EchoModel
  18. import Foundation
  19. import GRPC
  20. import Logging
  21. import NIO
  22. import NIOSSL
  23. // Add benchmarks here!
  24. func runBenchmarks(spec: TestSpec) {
  25. let smallRequest = String(repeating: "x", count: 8)
  26. let largeRequest = String(repeating: "x", count: 1 << 16) // 65k
  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: EmbeddedServerUnaryBenchmark(count: 10000, text: smallRequest),
  74. spec: spec
  75. )
  76. measureAndPrint(
  77. description: "percent_encode_decode_10k_status_messages",
  78. benchmark: PercentEncoding(iterations: 10000, requiresEncoding: true),
  79. spec: spec
  80. )
  81. measureAndPrint(
  82. description: "percent_encode_decode_10k_ascii_status_messages",
  83. benchmark: PercentEncoding(iterations: 10000, requiresEncoding: false),
  84. spec: spec
  85. )
  86. }
  87. struct TestSpec {
  88. var action: Action
  89. var repeats: Int
  90. init(action: Action, repeats: Int = 10) {
  91. self.action = action
  92. self.repeats = repeats
  93. }
  94. enum Action {
  95. /// Run the benchmark with the given filter.
  96. case run(Filter)
  97. /// List all benchmarks.
  98. case list
  99. }
  100. enum Filter {
  101. /// Run all tests.
  102. case all
  103. /// Run the tests which match the given descriptions.
  104. case some([String])
  105. func shouldRun(_ description: String) -> Bool {
  106. switch self {
  107. case .all:
  108. return true
  109. case let .some(selectedTests):
  110. return selectedTests.contains(description)
  111. }
  112. }
  113. }
  114. }
  115. func usage(program: String) -> String {
  116. return """
  117. USAGE: \(program) [-alh] [BENCHMARK ...]
  118. OPTIONS:
  119. The following options are available:
  120. -a Run all benchmarks. (Also: '--all')
  121. -l List all benchmarks. (Also: '--list')
  122. -h Prints this message. (Also: '--help')
  123. """
  124. }
  125. func main(args: [String]) {
  126. // Quieten the logs.
  127. LoggingSystem.bootstrap {
  128. var handler = StreamLogHandler.standardOutput(label: $0)
  129. handler.logLevel = .critical
  130. return handler
  131. }
  132. let program = args.first!
  133. let arg0 = args.dropFirst().first
  134. switch arg0 {
  135. case "-h", "--help":
  136. print(usage(program: program))
  137. case "-l", "--list":
  138. runBenchmarks(spec: TestSpec(action: .list))
  139. case "-a", "-all":
  140. runBenchmarks(spec: TestSpec(action: .run(.all)))
  141. default:
  142. // This must be a list of benchmarks to run.
  143. let tests = Array(args.dropFirst())
  144. if tests.isEmpty {
  145. print(usage(program: program))
  146. } else {
  147. runBenchmarks(spec: TestSpec(action: .run(.some(tests))))
  148. }
  149. }
  150. }
  151. assert({
  152. print("⚠️ WARNING: YOU ARE RUNNING IN DEBUG MODE ⚠️")
  153. return true
  154. }())
  155. main(args: CommandLine.arguments)