stub_impl.hpp 12.9 KB
Newer Older
W
wangguibao 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once
#include <string>
W
sdk-cpp  
wangguibao 已提交
17 18 19 20
namespace baidu {
namespace paddle_serving {
namespace sdk_cpp {

W
wangguibao 已提交
21 22 23 24 25 26 27 28 29 30 31
template <typename T, typename C, typename R, typename I, typename O>
int StubImpl<T, C, R, I, O>::initialize(const VariantInfo& var,
                                        const std::string& ep,
                                        const std::string* tag,
                                        const std::string* tag_value) {
  if (tag != NULL && tag_value != NULL) {
    TagFilter* filter = new (std::nothrow) TagFilter(*tag, *tag_value);
    if (!filter) {
      LOG(FATAL) << "Failed create tag filter, key: " << tag
                 << ", value: " << tag_value;
      return -1;
W
sdk-cpp  
wangguibao 已提交
32 33
    }

W
wangguibao 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
    _gchannel = init_channel(var, filter);
    LOG(INFO) << "Create stub with tag: " << *tag << ", " << *tag_value
              << ", ep: " << ep;
  } else {
    _gchannel = init_channel(var, NULL);
    LOG(INFO) << "Create stub without tag, ep " << ep;
  }

  if (!_gchannel) {
    LOG(FATAL) << "Failed init channel via var_info";
    return -1;
  }

  _service_stub = new (std::nothrow) T(_gchannel);
  if (!_service_stub) {
    LOG(FATAL) << "Failed create stub with channel";
    return -1;
  }

  _infer =
      _service_stub->GetDescriptor()->FindMethodByName(INFERENCE_METHOD_NAME);
  if (!_infer) {
    LOG(FATAL) << "Failed get inference method, "
               << "method name: " << INFERENCE_METHOD_NAME;
    return -1;
  }

  _debug = _service_stub->GetDescriptor()->FindMethodByName(DEBUG_METHOD_NAME);
  if (!_debug) {
    LOG(FATAL) << "Failed get debug method, "
               << "method name: " << DEBUG_METHOD_NAME;
    return -1;
  }

  _endpoint = ep;

  if (bthread_key_create(&_bthread_key, NULL) != 0) {
    LOG(FATAL) << "Failed create key for stub tls";
    return -1;
  }

  const std::string& name = _endpoint + "_" +
                            _service_stub->GetDescriptor()->full_name() + "_" +
                            _tag;

  _ltc_bvars.clear();
  _avg_bvars.clear();
  BAIDU_SCOPED_LOCK(_bvar_mutex);
W
sdk-cpp  
wangguibao 已提交
82 83

#ifndef DEFINE_LATENCY
W
wangguibao 已提交
84 85 86 87 88 89 90 91 92
#define DEFINE_LATENCY(item)                                               \
  do {                                                                     \
    _ltc_##item = new (std::nothrow) LatencyWrapper(name + "_" #item);     \
    if (!_ltc_##item) {                                                    \
      LOG(FATAL) << "Failed create latency recorder:" << name + "_" #item; \
      return -1;                                                           \
    }                                                                      \
    _ltc_bvars["ltc_" #item] = _ltc_##item;                                \
  } while (0)
W
sdk-cpp  
wangguibao 已提交
93 94
#endif

W
wangguibao 已提交
95 96 97 98 99 100 101 102 103 104
  DEFINE_LATENCY(infer_sync);
  DEFINE_LATENCY(infer_async);
  DEFINE_LATENCY(infer_send);
  DEFINE_LATENCY(infer_recv);
  DEFINE_LATENCY(infer_cancel);
  DEFINE_LATENCY(debug);
  DEFINE_LATENCY(rpc_init);
  DEFINE_LATENCY(thrd_clear);
  DEFINE_LATENCY(pack_map);
  DEFINE_LATENCY(pack_merge);
W
sdk-cpp  
wangguibao 已提交
105 106 107 108

#undef DEFINE_LATENCY

#ifndef DEFINE_AVERAGE
W
wangguibao 已提交
109 110 111 112 113 114 115 116 117
#define DEFINE_AVERAGE(item)                                               \
  do {                                                                     \
    _avg_##item = new (std::nothrow) AverageWrapper(name + "_" #item);     \
    if (!_avg_##item) {                                                    \
      LOG(FATAL) << "Failed create average recorder:" << name + "_" #item; \
      return -1;                                                           \
    }                                                                      \
    _avg_bvars["avg_" #item] = _avg_##item;                                \
  } while (0)
W
sdk-cpp  
wangguibao 已提交
118 119
#endif

W
wangguibao 已提交
120 121 122 123
  DEFINE_AVERAGE(failure);
  DEFINE_AVERAGE(pack);
  DEFINE_AVERAGE(item_size);
  DEFINE_AVERAGE(pack_fail);
W
sdk-cpp  
wangguibao 已提交
124 125 126

#undef DEFINE_AVERAGE

W
wangguibao 已提交
127
  return 0;
W
sdk-cpp  
wangguibao 已提交
128 129
}

W
wangguibao 已提交
130
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
131
int StubImpl<T, C, R, I, O>::thrd_initialize() {
W
wangguibao 已提交
132 133 134 135
  if (bthread_getspecific(_bthread_key) != NULL) {
    LOG(WARNING) << "Already thread initialized for stub";
    return 0;
  }
W
sdk-cpp  
wangguibao 已提交
136

W
wangguibao 已提交
137 138 139 140 141
  StubTLS* tls = new (std::nothrow) StubTLS();
  if (!tls || bthread_setspecific(_bthread_key, tls) != 0) {
    LOG(FATAL) << "Failed binding tls data to bthread_key";
    return -1;
  }
W
sdk-cpp  
wangguibao 已提交
142

W
wangguibao 已提交
143
  LOG(WARNING) << "Succ thread initialize stub impl!";
W
sdk-cpp  
wangguibao 已提交
144

W
wangguibao 已提交
145
  return 0;
W
sdk-cpp  
wangguibao 已提交
146 147
}

W
wangguibao 已提交
148
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
149
int StubImpl<T, C, R, I, O>::thrd_clear() {
W
wangguibao 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163
  MetricScope metric(this, "thrd_clear");
  StubTLS* tls = get_tls();
  if (!tls) {
    LOG(FATAL) << "Failed get tls stub object";
    return -1;
  }

  // clear predictor
  size_t ps = tls->predictor_pools.size();
  for (size_t pi = 0; pi < ps; ++pi) {
    Predictor* p = tls->predictor_pools[pi];
    if (p && p->is_inited() && return_predictor(p) != 0) {
      LOG(FATAL) << "Failed return predictor: " << pi;
      return -1;
W
sdk-cpp  
wangguibao 已提交
164
    }
W
wangguibao 已提交
165 166 167 168 169 170 171 172 173
  }
  tls->predictor_pools.clear();

  // clear request
  size_t is = tls->request_pools.size();
  for (size_t ii = 0; ii < is; ++ii) {
    if (return_request(tls->request_pools[ii]) != 0) {
      LOG(FATAL) << "Failed return request: " << ii;
      return -1;
W
sdk-cpp  
wangguibao 已提交
174
    }
W
wangguibao 已提交
175 176 177 178 179 180 181 182 183
  }
  tls->request_pools.clear();

  // clear response
  size_t os = tls->response_pools.size();
  for (size_t oi = 0; oi < os; ++oi) {
    if (return_response(tls->response_pools[oi]) != 0) {
      LOG(FATAL) << "Failed return response: " << oi;
      return -1;
W
sdk-cpp  
wangguibao 已提交
184
    }
W
wangguibao 已提交
185 186 187
  }
  tls->response_pools.clear();
  return 0;
W
sdk-cpp  
wangguibao 已提交
188 189
}

W
wangguibao 已提交
190
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
191
int StubImpl<T, C, R, I, O>::thrd_finalize() {
W
wangguibao 已提交
192 193 194 195 196 197 198 199
  StubTLS* tls = get_tls();
  if (!tls || thrd_clear() != 0) {
    LOG(FATAL) << "Failed clreate tls in thrd finalize";
    return -1;
  }

  delete tls;
  return 0;
W
sdk-cpp  
wangguibao 已提交
200 201
}

W
wangguibao 已提交
202
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
203
Predictor* StubImpl<T, C, R, I, O>::fetch_predictor() {
W
wangguibao 已提交
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
  StubTLS* tls = get_tls();
  if (!tls) {
    LOG(FATAL) << "Failed get tls data when fetching predictor";
    return NULL;
  }

  PredictorImpl<T>* predictor = butil::get_object<PredictorImpl<T>>();
  if (!predictor) {
    LOG(FATAL) << "Failed fetch predictor";
    return NULL;
  }

  if (predictor->init(
          _gchannel, _service_stub, _infer, _debug, _options, this, _tag) !=
      0) {
    LOG(FATAL) << "Failed init fetched predictor";
    return NULL;
  }

  tls->predictor_pools.push_back(predictor);
  return predictor;
W
sdk-cpp  
wangguibao 已提交
225 226
}

W
wangguibao 已提交
227
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
228
int StubImpl<T, C, R, I, O>::return_predictor(Predictor* predictor) {
W
wangguibao 已提交
229 230 231 232 233 234
  if ((dynamic_cast<PredictorImpl<T>*>(predictor))->deinit() != 0) {
    LOG(FATAL) << "Failed deinit fetched predictor";
    return -1;
  }
  butil::return_object(dynamic_cast<PredictorImpl<T>*>(predictor));
  return 0;
W
sdk-cpp  
wangguibao 已提交
235 236
}

W
wangguibao 已提交
237
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
238
int StubImpl<T, C, R, I, O>::return_predictor(Predictor* predictor) const {
W
wangguibao 已提交
239 240 241 242 243 244
  if ((dynamic_cast<PredictorImpl<T>*>(predictor))->deinit() != 0) {
    LOG(FATAL) << "Failed deinit fetched predictor";
    return -1;
  }
  butil::return_object(dynamic_cast<PredictorImpl<T>*>(predictor));
  return 0;
W
sdk-cpp  
wangguibao 已提交
245 246
}

W
wangguibao 已提交
247
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
248
google::protobuf::Message* StubImpl<T, C, R, I, O>::fetch_request() {
W
wangguibao 已提交
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
  StubTLS* tls = get_tls();
  if (!tls) {
    LOG(FATAL) << "Failed get tls data when fetching request";
    return NULL;
  }

  I* req = butil::get_object<I>();
  if (!req) {
    LOG(FATAL) << "Failed get tls request item, type: " << typeid(I).name();
    return NULL;
  }

  req->Clear();
  tls->request_pools.push_back(req);
  return req;
W
sdk-cpp  
wangguibao 已提交
264 265
}

W
wangguibao 已提交
266
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
267
int StubImpl<T, C, R, I, O>::return_request(
W
wangguibao 已提交
268 269 270 271
    google::protobuf::Message* request) const {
  request->Clear();
  butil::return_object(dynamic_cast<I*>(request));
  return 0;
W
sdk-cpp  
wangguibao 已提交
272 273
}

W
wangguibao 已提交
274
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
275
int StubImpl<T, C, R, I, O>::return_request(
W
wangguibao 已提交
276 277 278 279
    google::protobuf::Message* request) {
  request->Clear();
  butil::return_object(dynamic_cast<I*>(request));
  return 0;
W
sdk-cpp  
wangguibao 已提交
280 281
}

W
wangguibao 已提交
282
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
283
google::protobuf::Message* StubImpl<T, C, R, I, O>::fetch_response() {
W
wangguibao 已提交
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
  StubTLS* tls = get_tls();
  if (!tls) {
    LOG(FATAL) << "Failed get tls data when fetching response";
    return NULL;
  }

  O* res = butil::get_object<O>();
  if (!res) {
    LOG(FATAL) << "Failed get tls response item, type: " << typeid(O).name();
    return NULL;
  }

  res->Clear();
  tls->response_pools.push_back(res);
  return res;
W
sdk-cpp  
wangguibao 已提交
299 300
}

W
wangguibao 已提交
301
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
302
int StubImpl<T, C, R, I, O>::return_response(
W
wangguibao 已提交
303 304 305 306
    google::protobuf::Message* response) const {
  response->Clear();
  butil::return_object(dynamic_cast<O*>(response));
  return 0;
W
sdk-cpp  
wangguibao 已提交
307 308
}

W
wangguibao 已提交
309
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
310
int StubImpl<T, C, R, I, O>::return_response(
W
wangguibao 已提交
311 312 313 314
    google::protobuf::Message* response) {
  response->Clear();
  butil::return_object(dynamic_cast<O*>(response));
  return 0;
W
sdk-cpp  
wangguibao 已提交
315 316
}

W
wangguibao 已提交
317
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
318
google::protobuf::RpcChannel* StubImpl<T, C, R, I, O>::init_channel(
W
wangguibao 已提交
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
    const VariantInfo& var, brpc::NamingServiceFilter* filter) {
  brpc::ChannelOptions chn_options;
  chn_options.ns_filter = filter;

  // parameters
  ASSIGN_CONF_ITEM(chn_options.protocol, var.parameters.protocol, NULL);
  ASSIGN_CONF_ITEM(_tag, var.parameters.route_tag, NULL);
  ASSIGN_CONF_ITEM(_max_channel, var.parameters.max_channel, NULL);
  ASSIGN_CONF_ITEM(_package_size, var.parameters.package_size, NULL);

  if (_max_channel < 1) {
    LOG(ERROR) << "Invalid MaxChannelPerRequest: " << _max_channel;
    return NULL;
  }

  // connection
  ASSIGN_CONF_ITEM(chn_options.max_retry, var.connection.cnt_retry_conn, NULL);
  ASSIGN_CONF_ITEM(
      chn_options.connect_timeout_ms, var.connection.tmo_conn, NULL);
  ASSIGN_CONF_ITEM(chn_options.timeout_ms, var.connection.tmo_rpc, NULL);
  ASSIGN_CONF_ITEM(
      chn_options.backup_request_ms, var.connection.tmo_hedge, NULL);

  // connection type
  std::string conn_type_str;
  ASSIGN_CONF_ITEM(conn_type_str, var.connection.type_conn, NULL);
  chn_options.connection_type = brpc::StringToConnectionType(conn_type_str);

  // naminginfo
  std::string cluster_naming_info;
  std::string cluster_loadbalancer;
  ASSIGN_CONF_ITEM(cluster_naming_info, var.naminginfo.cluster_naming, NULL);
  ASSIGN_CONF_ITEM(cluster_loadbalancer, var.naminginfo.load_balancer, NULL);

  // brpc single channel
  _channel = butil::get_object<brpc::Channel>();
  if (!_channel) {
    LOG(FATAL) << "Failed get channel object from butil::pool";
    return NULL;
  }

  if (_channel->Init(cluster_naming_info.c_str(),
                     cluster_loadbalancer.c_str(),
                     &chn_options) != 0) {
    LOG(ERROR) << "Failed to initialize channel, path: " << cluster_naming_info;
    return NULL;
  }

  // brpc parallel channel
  _pchannel = init_pchannel(_channel, _max_channel, _package_size, chn_options);
  if (_pchannel) {
    LOG(INFO) << "Succ create parallel channel, count: " << _max_channel;
    return _pchannel;
  }
W
sdk-cpp  
wangguibao 已提交
373

W
wangguibao 已提交
374
  return _channel;
W
sdk-cpp  
wangguibao 已提交
375 376
}

W
wangguibao 已提交
377
template <typename T, typename C, typename R, typename I, typename O>
W
sdk-cpp  
wangguibao 已提交
378
brpc::ParallelChannel* StubImpl<T, C, R, I, O>::init_pchannel(
W
wangguibao 已提交
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
    brpc::Channel* sub_channel,
    uint32_t channel_count,
    uint32_t package_size,
    const brpc::ChannelOptions& options) {
  if (channel_count <= 1) {  // noneed use parallel channel
    LOG(INFO) << "channel count <= 1, noneed use pchannel.";
    return NULL;
  }

  _pchannel = butil::get_object<brpc::ParallelChannel>();
  if (!_pchannel) {
    LOG(FATAL) << "Failed get pchannel from object pool";
    return NULL;
  }

  brpc::ParallelChannelOptions pchan_options;
  pchan_options.timeout_ms = options.timeout_ms;
  if (_pchannel->Init(&pchan_options) != 0) {
    LOG(FATAL) << "Failed init parallel channel with tmo_us: "
               << pchan_options.timeout_ms;
    return NULL;
  }

  for (uint32_t si = 0; si < channel_count; ++si) {
    if (_pchannel->AddChannel(sub_channel,
                              brpc::DOESNT_OWN_CHANNEL,
                              new C(package_size, this),
                              new R(package_size, this)) != 0) {
      LOG(FATAL) << "Failed add channel at: " << si
                 << ", package_size:" << package_size;
      return NULL;
W
sdk-cpp  
wangguibao 已提交
410
    }
W
wangguibao 已提交
411
  }
W
sdk-cpp  
wangguibao 已提交
412

W
wangguibao 已提交
413
  return _pchannel;
W
sdk-cpp  
wangguibao 已提交
414 415
}

W
wangguibao 已提交
416 417 418
}  // namespace sdk_cpp
}  // namespace paddle_serving
}  // namespace baidu