Home | History | Annotate | Download | only in qps
      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 
     39 require dirname(__FILE__).'/vendor/autoload.php';
     40 require 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  */
     49 function hardAssert($value, $error_message)
     50 {
     51     if (!$value) {
     52         echo $error_message."\n";
     53         exit(1);
     54     }
     55 }
     56 
     57 function 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 */
     67 function 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 
    176 ini_set('display_startup_errors', 1);
    177 ini_set('display_errors', 1);
    178 error_reporting(-1);
    179 qps_client_main($argv[1], $argv[2]);
    180