1<?php 2/* 3 * 4 * Copyright 2017 gRPC authors. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 */ 19 20/* 21 * PHP client for QPS testing works as follows: 22 * 1. Gets initiated by a call from a proxy that implements the worker service. The 23 * argument to this client is the proxy connection information 24 * 2. Initiate an RPC to the proxy to get ClientConfig 25 * 3. Initiate a client-side telemetry RPC to the proxy 26 * 4. Parse the client config, which includes server target information and then start 27 * a unary or streaming test as appropriate. 28 * 5. After each completed RPC, send its timing to the proxy. The proxy does all histogramming 29 * 6. Proxy will respond on the timing channel when it's time to complete. Our 30 * next timing write will fail and we know that it's time to stop 31 * The above complex dance is since threading and async are not idiomatic and we 32 * shouldn't ever be waiting to read a mark 33 * 34 * This test only supports a single channel since threading/async is not idiomatic 35 * This test supports unary or streaming ping-pongs, as well as open-loop 36 * 37 */ 38 39require dirname(__FILE__).'/vendor/autoload.php'; 40require dirname(__FILE__).'/histogram.php'; 41 42/** 43 * Assertion function that always exits with an error code if the assertion is 44 * falsy. 45 * 46 * @param $value Assertion value. Should be true. 47 * @param $error_message Message to display if the assertion is false 48 */ 49function hardAssert($value, $error_message) 50{ 51 if (!$value) { 52 echo $error_message."\n"; 53 exit(1); 54 } 55} 56 57function hardAssertIfStatusOk($status) 58{ 59 if ($status->code !== Grpc\STATUS_OK) { 60 echo "Call did not complete successfully. Status object:\n"; 61 var_dump($status); 62 exit(1); 63 } 64} 65 66/* Start the actual client */ 67function qps_client_main($proxy_address, $server_ind) { 68 echo "[php-client] Initiating php client\n"; 69 70 $proxystubopts = []; 71 $proxystubopts['credentials'] = Grpc\ChannelCredentials::createInsecure(); 72 $proxystub = new Grpc\Testing\ProxyClientServiceClient($proxy_address, $proxystubopts); 73 list($config, $status) = $proxystub->GetConfig(new Grpc\Testing\PBVoid())->wait(); 74 hardAssertIfStatusOk($status); 75 hardAssert($config->getOutstandingRpcsPerChannel() == 1, "Only 1 outstanding RPC supported"); 76 77 echo "[php-client] Got configuration from proxy, target is '$server_ind'th server" . $config->getServerTargets()[$server_ind] . "\n"; 78 $histres = $config->getHistogramParams()->getResolution(); 79 $histmax = $config->getHistogramParams()->getMaxPossible(); 80 81 $stubopts = []; 82 if ($config->getSecurityParams()) { 83 if ($config->getSecurityParams()->getUseTestCa()) { 84 $stubopts['credentials'] = Grpc\ChannelCredentials::createSsl( 85 file_get_contents(dirname(__FILE__).'/../data/ca.pem')); 86 } else { 87 $stubopts['credentials'] = Grpc\ChannelCredentials::createSsl(null); 88 } 89 $override = $config->getSecurityParams()->getServerHostOverride(); 90 if ($override) { 91 $stubopts['grpc.ssl_target_name_override'] = $override; 92 $stubopts['grpc.default_authority'] = $override; 93 } 94 } else { 95 $stubopts['credentials'] = Grpc\ChannelCredentials::createInsecure(); 96 } 97 echo "[php-client] Initiating php benchmarking client\n"; 98 99 $stub = new Grpc\Testing\BenchmarkServiceClient( 100 $config->getServerTargets()[$server_ind], $stubopts); 101 $req = new Grpc\Testing\SimpleRequest(); 102 103 $req->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE); 104 $req->setResponseSize($config->getPayloadConfig()->getSimpleParams()->getRespSize()); 105 $payload = new Grpc\Testing\Payload(); 106 $payload->setType(Grpc\Testing\PayloadType::COMPRESSABLE); 107 $payload->setBody(str_repeat("\0", $config->getPayloadConfig()->getSimpleParams()->getReqSize())); 108 $req->setPayload($payload); 109 110 /* TODO(stanley-cheung): Enable the following by removing the 0&& once protobuf 111 * properly supports oneof in PHP */ 112 if (0 && $config->getLoadParams()->getLoad() == "poisson") { 113 $poisson = true; 114 $lamrecip = 1.0/($config->getLoadParams()->getPoisson()->getOfferedLoad()); 115 $issue = microtime(true) + $lamrecip * -log(1.0-rand()/(getrandmax()+1)); 116 } else { 117 $poisson = false; 118 } 119 $histogram = new Histogram($histres, $histmax); 120 $histogram->clean(); 121 $count = 0; 122 $histogram_result = new Grpc\Testing\HistogramData; 123 $telehist = $proxystub->ReportHist(); 124 if ($config->getRpcType() == Grpc\Testing\RpcType::UNARY) { 125 while (1) { 126 if ($poisson) { 127 time_sleep_until($issue); 128 $issue = $issue + $lamrecip * -log(1.0-rand()/(getrandmax()+1)); 129 } 130 $startreq = microtime(true); 131 list($resp,$status) = $stub->UnaryCall($req)->wait(); 132 hardAssertIfStatusOk($status); 133 $histogram->add((microtime(true)-$startreq)*1e9); 134 $count += 1; 135 if ($count == 2000) { 136 $contents = $histogram->contents(); 137 $histogram_result->setBucket($contents); 138 $histogram_result->setMinSeen($histogram->minimum()); 139 $histogram_result->setMaxSeen($histogram->maximum()); 140 $histogram_result->setSum($histogram->sum()); 141 $histogram_result->setSumOfSquares($histogram->sum_of_squares()); 142 $histogram_result->setCount($histogram->count()); 143 $telehist->write($histogram_result); 144 $histogram->clean(); 145 $count = 0; 146 } 147 } 148 } else { 149 $stream = $stub->StreamingCall(); 150 while (1) { 151 if ($poisson) { 152 time_sleep_until($issue); 153 $issue = $issue + $lamrecip * -log(1.0-rand()/(getrandmax()+1)); 154 } 155 $startreq = microtime(true); 156 $stream->write($req); 157 $resp = $stream->read(); 158 $histogram->add((microtime(true)-$startreq)*1e9); 159 $count += 1; 160 if ($count == 2000) { 161 $contents = $histogram->contents(); 162 $histogram_result->setBucket($contents); 163 $histogram_result->setMinSeen($histogram->minimum()); 164 $histogram_result->setMaxSeen($histogram->maximum()); 165 $histogram_result->setSum($histogram->sum()); 166 $histogram_result->setSumOfSquares($histogram->sum_of_squares()); 167 $histogram_result->setCount($histogram->count()); 168 $telehist->write($histogram_result); 169 $histogram->clean(); 170 $count = 0; 171 } 172 } 173 } 174} 175 176ini_set('display_startup_errors', 1); 177ini_set('display_errors', 1); 178error_reporting(-1); 179qps_client_main($argv[1], $argv[2]); 180