• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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