TensorFlow Serving C++ API Documentation
servable_id.h
1 /* Copyright 2016 Google Inc. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7  http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #ifndef TENSORFLOW_SERVING_CORE_SERVABLE_ID_H_
17 #define TENSORFLOW_SERVING_CORE_SERVABLE_ID_H_
18 
19 #include <iosfwd>
20 #include <string>
21 #include <unordered_map>
22 
23 #include "tensorflow/core/lib/strings/strcat.h"
24 #include "tensorflow/core/platform/types.h"
25 #include "tensorflow_serving/util/hash.h"
26 
27 namespace tensorflow {
28 namespace serving {
29 
30 // An identifier for a Servable. Two Servable objects with the
31 // same identifier are considered semantically equivalent (modulo its loaded-
32 // ness state).
33 struct ServableId {
34  // The name of the servable stream to which this servable object belongs.
35  string name;
36 
37  // The sequence number of this servable object in its stream. The primary
38  // purpose of 'version' is to uniquely identify a servable object. A
39  // secondary purpose is to support inbound requests that identify just a
40  // servable stream name but not a specific version; those are routed to the
41  // active servable with the largest version number.
42  //
43  // Must be non-negative.
44  int64_t version;
45 
46  // Returns a string representation of this object. Useful in logging.
47  string DebugString() const {
48  return strings::StrCat("{name: ", name, " version: ", version, "}");
49  }
50 };
51 
53  uint64_t operator()(const ServableId& id) const {
54  // Hash codes for many common types are remarkably bad, often clustering
55  // around the same values of the low and/or high bits for linear
56  // sequences of inputs such as 1, 2, 3; or addresses of consecutively
57  // allocated objects. For these cases the default hash function is the
58  // identity function on the bit patterns.
59  //
60  // So we apply a one-to-one mapping to the resulting bit patterns to
61  // make the high bits contain more entropy from the entire hash code.
62  // It's based on Fibonacci hashing from Knuth's Art of Computer
63  // Programming volume 3, section 6.4.
64  const uint64_t version_hash = [&]() -> uint64_t {
65  if (id.version >= 0) {
66  return std::hash<int64_t>()(id.version) *
67  0x9E3779B97F4A7C13; // (sqrt(5) - 1)/2 as a binary fraction.
68  } else {
69  return 0xDECAFCAFFE;
70  }
71  }();
72  // Using version_hash as the seed here to combine the hashes.
73  return HashCombine(version_hash, std::hash<string>()(id.name));
74  }
75 };
76 
77 inline bool operator==(const ServableId& a, const ServableId& b) {
78  return a.version == b.version && a.name == b.name;
79 }
80 
81 inline bool operator!=(const ServableId& a, const ServableId& b) {
82  return !(a == b);
83 }
84 
85 inline bool operator<(const ServableId& a, const ServableId& b) {
86  const int strcmp_result = a.name.compare(b.name);
87  if (strcmp_result != 0) {
88  return strcmp_result < 0;
89  }
90  return a.version < b.version;
91 }
92 
93 inline std::ostream& operator<<(std::ostream& out, const ServableId& id) {
94  return out << id.DebugString();
95 }
96 
97 } // namespace serving
98 } // namespace tensorflow
99 
100 #endif // TENSORFLOW_SERVING_CORE_SERVABLE_ID_H_