main.swift 4.4 KB

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