You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by GitBox <gi...@apache.org> on 2022/04/11 22:09:50 UTC

[GitHub] [tvm] mkatanbaf opened a new pull request, #10967: [rpc] Implemented rpc logging

mkatanbaf opened a new pull request, #10967:
URL: https://github.com/apache/tvm/pull/10967

   Thanks for contributing to TVM!   Please refer to guideline https://tvm.apache.org/docs/contribute/ for useful information and tips. After the pull request is submitted, please request code reviews from [Reviewers](https://github.com/apache/incubator-tvm/blob/master/CONTRIBUTORS.md#reviewers) by @ them in the pull request thread.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861413876


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void ProcessValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void ResetCurrHandleName(RPCCode code);
+
+  void UpdateCurrHandleName(const char* name);
+
+  void GetHandleName(void* handle);
+
+  void ReleaseHandleName(void* handle);
+
+  Logger* GetLogger() { return &logger_; }
+
+ private:
+  void RegisterHandleName(void* handle);
+
+  ReturnInterface* next_;
+  std::string curr_handle_name_;
+  std::unordered_map<void*, std::string> array_tracker_;
+  RPCCode code_;
+  Logger logger_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCExecute object, that also logs the responses.
+ *
+ * \tparam RExecInterface* underlying MinRPCExecute that processes the packets.
+ */
+class MinRPCExecuteWithLog : public ExecInterface {
+ public:
+  explicit MinRPCExecuteWithLog(ExecInterface* next) : next_(next) {
+    ret_handler_ = reinterpret_cast<MinRPCReturnsWithLog*>(next_->GetReturnInterface());

Review Comment:
   done, but I still need to keep the reinterpret_cast, to access functions such as GetHandleName, UpdateHandleName, ...



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861414004


##########
src/runtime/minrpc/minrpc_interfaces.h:
##########
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief Return interface used in ExecInterface to generate and sent the responses.
+ */
+class ReturnInterface {

Review Comment:
   I added the MinRPC to the interface names.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r854274054


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -524,94 +523,249 @@ class MinRPCServer {
     int call_ecode = TVMSetStream(dev.device_type, dev.device_id, handle);
 
     if (call_ecode == 0) {
-      this->ReturnVoid();
+      ret_handler_->ReturnVoid();
     } else {
-      this->ReturnLastTVMError();
+      ret_handler_->ReturnLastTVMError();
     }
   }
 
   void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone) {
-    io_->Exit(static_cast<int>(code));
+    ret_handler_->ThrowError(code, info);
   }
 
+  ReturnInterface* GetReturnInterface() { return ret_handler_; }
+
+ private:
   template <typename T>
-  T* ArenaAlloc(int count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return arena_.template allocate_<T>(count);
+  int ReadArray(T* data, size_t count) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    return ReadRawBytes(data, sizeof(T) * count);
   }
 
-  template <typename T>
-  void Read(T* data) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    this->ReadRawBytes(data, sizeof(T));
+  int ReadRawBytes(void* data, size_t size) {
+    uint8_t* buf = reinterpret_cast<uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixRead(buf, size - ndone);
+      if (ret <= 0) return ret;
+      ndone += ret;
+      buf += ret;
+    }
+    return 1;
   }
 
-  template <typename T>
-  void ReadArray(T* data, size_t count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return this->ReadRawBytes(data, sizeof(T) * count);
+  TIOHandler* io_;
+  ReturnInterface* ret_handler_;
+};
+
+/*!
+ * \brief A minimum RPC server that only depends on the tvm C runtime..
+ *
+ *  All the dependencies are provided by the io arguments.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ *         An IOHandler needs to provide the following functions:
+ *         - PosixWrite, PosixRead, Close: posix style, read, write, close API.
+ *         - MessageStart(num_bytes), MessageDone(): framing APIs.
+ *         - Exit: exit with status code.
+ */
+template <typename TIOHandler, template <typename> class Allocator = detail::PageAllocator>
+class MinRPCServer {
+ public:
+  using PageAllocator = Allocator<TIOHandler>;
+
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  MinRPCServer(TIOHandler* io, ExecInterface* exec_handler)
+      : io_(io), arena_(PageAllocator(io_)), exec_handler_(exec_handler) {}
+
+  explicit MinRPCServer(TIOHandler* io)
+      : io_(io),
+        arena_(PageAllocator(io)),
+        ret_handler_(new MinRPCReturns<TIOHandler>(io_)),
+        exec_handler_(new MinRPCExecute<TIOHandler>(io_, ret_handler_)) {}

Review Comment:
   Thank you very much for taking the time to read through the code, and for valuable comments.
   Initially, I wanted to address this using unique_ptrs, but including "memory" generates the "redefinition of operator new" error in rpc_server.cc. So, I simply use the "ret_handler_" variable as a flag to infer which constructor is used, and delete the allocated variables when needed.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r852333108


##########
src/runtime/minrpc/minrpc_server_logging.h:
##########
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+
+#include "minrpc_logger.h"
+#include "minrpc_server.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief A minimum RPC server that logs the received commands.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCServerWithLog {
+ public:
+  explicit MinRPCServerWithLog(TIOHandler* io)
+      : ret_handler_(io),
+        ret_handler_WLog_(&ret_handler_),
+        exec_handler_(io, &ret_handler_WLog_),
+        exec_handler_WLog_(&exec_handler_),
+        next_(io, &exec_handler_WLog_) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+ private:
+  MinRPCReturns<TIOHandler> ret_handler_;
+  MinRPCExecute<TIOHandler> exec_handler_;
+  MinRPCReturnsWithLog ret_handler_WLog_;
+  MinRPCExecuteWithLog exec_handler_WLog_;
+  MinRPCServer<TIOHandler> next_;
+};
+
+/*!
+ * \brief A minimum RPC server that only logs the outgoing commands and received responses.
+ * (Does not process the packets or respond to them.)
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCSniffer {
+ public:
+  explicit MinRPCSniffer(TIOHandler* io)
+      : io_(io),
+        ret_handler_(io_),
+        ret_handler_WLog_(&ret_handler_),
+        exec_handler_(&ret_handler_WLog_),
+        exec_handler_WLog_(&exec_handler_),
+        next_(io_, &exec_handler_WLog_) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+  void ProcessOneResponse() {
+    RPCCode code;
+    uint64_t packet_len = 0;
+
+    this->Read(&packet_len);
+    if (packet_len == 0) OutputLog();
+    this->Read(&code);
+    switch (code) {
+      case RPCCode::kReturn: {
+        HandleReturn();
+        break;
+      }
+      case RPCCode::kException: {
+        ret_handler_WLog_.ReturnException("");
+        break;
+      }
+      default: {
+        OutputLog();
+        break;
+      }
+    }
+  }
+
+ private:
+  void HandleReturn() {
+    int32_t num_args;
+    int32_t tcode;
+
+    this->Read(&num_args);
+    if (num_args == 1) {
+      this->Read(&tcode);
+      if (tcode == kTVMNullptr) {
+        ret_handler_WLog_.ReturnVoid();
+        return;
+      }
+      if (tcode == kTVMOpaqueHandle) {
+        uint64_t handle;
+        this->Read(&handle);
+        ret_handler_WLog_.ReturnHandle(reinterpret_cast<void*>(handle));
+        return;
+      }
+    }
+    OutputLog();
+  }
+
+  void OutputLog() { ret_handler_WLog_.getLogger()->OutputLog(); }
+
+  template <typename T>
+  void Read(T* data) {
+    static_assert(std::is_pod<T>::value, "need to be trival");

Review Comment:
   Thanks, and done!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861414747


##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      LogString("\"");
+      LogString(value.v_str);
+      LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        LogString(", [Values]:");
+        LogString(" { ");
+        if (len > 0) {
+          LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  LogString("; ");
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (code_ == RPCCode::kGetGlobalFunc) {
+    RegisterHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  ProcessValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnLastTVMError() {
+  const char* err = TVMGetLastError();
+  ReturnException(err);
+}
+
+void MinRPCReturnsWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  next_->ThrowError(code, info);
+  logger_.LogString("-> ERROR");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ProcessValues(const TVMValue** values, const int** tcodes,
+                                         int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_.LogString("-> [");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_.LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMOpaqueHandle) {
+        RegisterHandleName((*values)[i].v_handle);
+      }
+    }
+    logger_.LogString("]");
+  }
+}
+
+void MinRPCReturnsWithLog::ResetCurrHandleName(RPCCode code) {
+  code_ = code;
+  logger_.LogString(RPCCodeToString(code));
+  logger_.LogString(", ");
+  curr_handle_name_.clear();
+}
+
+void MinRPCReturnsWithLog::UpdateCurrHandleName(const char* name) {
+  if (curr_handle_name_.length() != 0) {
+    curr_handle_name_.append("::");
+  }
+  curr_handle_name_.append(name);
+}
+
+void MinRPCReturnsWithLog::GetHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    curr_handle_name_.append(array_tracker_[handle]);
+    logger_.LogHandleName(curr_handle_name_);
+  }
+}
+
+void MinRPCReturnsWithLog::ReleaseHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    logger_.LogHandleName(array_tracker_[handle]);
+    array_tracker_.erase(handle);
+  }
+}
+
+void MinRPCReturnsWithLog::RegisterHandleName(void* handle) {
+  array_tracker_[handle] = curr_handle_name_;
+}
+
+void MinRPCExecuteWithLog::ExecInitServer(int* num_args) {
+  SetRPCCode(RPCCode::kInitServer);
+  logger_->LogString("Init Server");
+  next_->ExecInitServer(num_args);
+}
+
+void MinRPCExecuteWithLog::ExecNormalCallFunc(uint64_t* call_handle, TVMValue** values,
+                                              int** tcodes, int* num_args) {
+  SetRPCCode(RPCCode::kCallFunc);
+  logger_->LogVal<void*>("call_handle: ", reinterpret_cast<void*>(*call_handle));
+  ret_handler_->GetHandleName(reinterpret_cast<void*>(*call_handle));
+  if (*num_args > 0) {
+    logger_->LogString(", ");
+  }
+  ProcessValues(values, tcodes, num_args);
+  next_->ExecNormalCallFunc(call_handle, values, tcodes, num_args);
+}
+
+void MinRPCExecuteWithLog::ExecCopyFromRemote(DLTensor** arr, uint64_t* num_bytes,
+                                              uint8_t** temp_data) {
+  SetRPCCode(RPCCode::kCopyFromRemote);
+  logger_->LogVal<void*>("data_handle: ", reinterpret_cast<void*>((*arr)->data));
+  logger_->LogDLDevice(", DLDevice(type,id):", &(*arr)->device);
+  logger_->LogVal<int64_t>(", ndim: ", (*arr)->ndim);
+  logger_->LogDLData(", DLDataType(code,bits,lane): ", &(*arr)->dtype);
+  logger_->LogVal<uint64_t>(", num_bytes:", *num_bytes);
+  next_->ExecCopyFromRemote(arr, num_bytes, temp_data);
+}
+
+int MinRPCExecuteWithLog::ExecCopyToRemote(DLTensor** arr, uint64_t* num_bytes,
+                                           uint8_t** data_ptr) {
+  SetRPCCode(RPCCode::kCopyToRemote);
+  logger_->LogVal<void*>("data_handle: ", reinterpret_cast<void*>((*arr)->data));
+  logger_->LogDLDevice(", DLDevice(type,id):", &(*arr)->device);
+  logger_->LogVal<int64_t>(", ndim: ", (*arr)->ndim);
+  logger_->LogDLData(", DLDataType(code,bits,lane): ", &(*arr)->dtype);
+  logger_->LogVal<uint64_t>(", byte_offset: ", (*arr)->byte_offset);
+  return next_->ExecCopyToRemote(arr, num_bytes, data_ptr);
+}
+
+void MinRPCExecuteWithLog::ExecSyscallFunc(RPCCode* code, TVMValue** values, int** tcodes,
+                                           int* num_args) {
+  SetRPCCode(*code);
+  if ((*code) == RPCCode::kFreeHandle) {
+    if (((*num_args) == 2) && ((*tcodes)[0] == kTVMOpaqueHandle) && ((*tcodes)[1] == kDLInt)) {
+      logger_->LogVal<void*>("handle: ", reinterpret_cast<void*>((*values)[0].v_handle));
+      if ((*values)[1].v_int64 == kTVMModuleHandle ||
+          (*values)[1].v_int64 == kTVMPackedFuncHandle) {
+        ret_handler_->ReleaseHandleName(reinterpret_cast<void*>((*values)[0].v_handle));
+      }
+    }
+  } else {
+    ProcessValues(values, tcodes, num_args);
+  }
+  next_->ExecSyscallFunc(code, values, tcodes, num_args);
+}
+
+void MinRPCExecuteWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  logger_->LogString("-> Error\n");
+  next_->ThrowError(code, info);
+}
+
+void MinRPCExecuteWithLog::ProcessValues(TVMValue** values, int** tcodes, int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_->LogString("[");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_->LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMStr) {
+        if (strlen((*values)[i].v_str) > 0) {
+          ret_handler_->UpdateCurrHandleName((*values)[i].v_str);

Review Comment:
   As we talked, I keep the code as is for the moment (i.e. it adds all the strings in parameters to the handle name). In future we can change it once we had a better vision of what should or should not be logged.



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void ProcessValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void ResetCurrHandleName(RPCCode code);
+
+  void UpdateCurrHandleName(const char* name);
+
+  void GetHandleName(void* handle);
+
+  void ReleaseHandleName(void* handle);
+
+  Logger* GetLogger() { return &logger_; }
+
+ private:
+  void RegisterHandleName(void* handle);
+
+  ReturnInterface* next_;
+  std::string curr_handle_name_;
+  std::unordered_map<void*, std::string> array_tracker_;
+  RPCCode code_;
+  Logger logger_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCExecute object, that also logs the responses.
+ *
+ * \tparam RExecInterface* underlying MinRPCExecute that processes the packets.
+ */
+class MinRPCExecuteWithLog : public ExecInterface {
+ public:
+  explicit MinRPCExecuteWithLog(ExecInterface* next) : next_(next) {
+    ret_handler_ = reinterpret_cast<MinRPCReturnsWithLog*>(next_->GetReturnInterface());
+    logger_ = ret_handler_->GetLogger();
+  }
+
+  ~MinRPCExecuteWithLog() {}
+
+  void ExecInitServer(int* num_args);
+
+  void ExecNormalCallFunc(uint64_t* call_handle, TVMValue** values, int** tcodes, int* num_args);

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r864279096


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -28,14 +28,23 @@
 #ifndef TVM_RUNTIME_MINRPC_MINRPC_SERVER_H_
 #define TVM_RUNTIME_MINRPC_MINRPC_SERVER_H_
 
+#ifndef DMLC_LITTLE_ENDIAN
 #define DMLC_LITTLE_ENDIAN 1
+#endif
+
 #include <string.h>
 #include <tvm/runtime/c_runtime_api.h>
 
+#include <memory>
+#include <utility>
+
 #include "../../support/generic_arena.h"
+#include "minrpc_interfaces.h"
 #include "rpc_reference.h"
 
 /*! \brief Whether or not to enable glog style DLOG */
+#define TVM_MINRPC_ENABLE_LOGGING 1
+
 #ifndef TVM_MINRPC_ENABLE_LOGGING
 #define TVM_MINRPC_ENABLE_LOGGING 0

Review Comment:
   Thanks for the comment. it's fixed.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r852330859


##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,307 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      this->LogVal<int64_t>("(int64)", value.v_int64);

Review Comment:
   fixed!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861413426


##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      LogString("\"");
+      LogString(value.v_str);
+      LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        LogString(", [Values]:");
+        LogString(" { ");
+        if (len > 0) {
+          LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  LogString("; ");
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (code_ == RPCCode::kGetGlobalFunc) {
+    RegisterHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  ProcessValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnLastTVMError() {
+  const char* err = TVMGetLastError();
+  ReturnException(err);
+}
+
+void MinRPCReturnsWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  next_->ThrowError(code, info);
+  logger_.LogString("-> ERROR");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ProcessValues(const TVMValue** values, const int** tcodes,
+                                         int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_.LogString("-> [");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_.LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMOpaqueHandle) {
+        RegisterHandleName((*values)[i].v_handle);
+      }
+    }
+    logger_.LogString("]");
+  }
+}
+
+void MinRPCReturnsWithLog::ResetCurrHandleName(RPCCode code) {
+  code_ = code;
+  logger_.LogString(RPCCodeToString(code));
+  logger_.LogString(", ");
+  curr_handle_name_.clear();
+}
+
+void MinRPCReturnsWithLog::UpdateCurrHandleName(const char* name) {
+  if (curr_handle_name_.length() != 0) {
+    curr_handle_name_.append("::");
+  }
+  curr_handle_name_.append(name);
+}
+
+void MinRPCReturnsWithLog::GetHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    curr_handle_name_.append(array_tracker_[handle]);
+    logger_.LogHandleName(curr_handle_name_);
+  }
+}
+
+void MinRPCReturnsWithLog::ReleaseHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    logger_.LogHandleName(array_tracker_[handle]);

Review Comment:
   ReleaseHandleName is called when we receive the FreeHandle SysCall. In that case, I check if the name is registered, print it if it is, and remove it from the map of registered names.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861415661


##########
python/tvm/rpc/client.py:
##########
@@ -505,7 +508,7 @@ def connect(url, port, key="", session_timeout=0, session_constructor_args=None)
         client_via_proxy = rpc.connect(
             proxy_server_url, proxy_server_port, proxy_server_key,
             session_constructor_args=[
-                "rpc.Connect", internal_url, internal_port, internal_key])
+                "rpc.Connect", internal_url, internal_port, internal_key, enable_logging])

Review Comment:
   Not sure if I understand your comment. This is not a function call, it's a list of parameters that would later pass to rpc.Connect on the device. so, I believe we cannot write down the param_name=value, it only has to be the value.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r850736863


##########
src/runtime/minrpc/minrpc_server_logging.h:
##########
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+
+#include "minrpc_logger.h"
+#include "minrpc_server.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief A minimum RPC server that logs the received commands.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCServerWithLog {
+ public:
+  explicit MinRPCServerWithLog(TIOHandler* io)
+      : ret(io), retWLog(&ret), exec(io, &retWLog), execWLog(&exec), next_(io, &execWLog) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+ private:
+  MinRPCReturns<TIOHandler> ret;
+  MinRPCExecute<TIOHandler> exec;
+  MinRPCReturnsWithLog retWLog;
+  MinRPCExecuteWithLog execWLog;
+  MinRPCServer<TIOHandler> next_;
+};
+
+/*!
+ * \brief A minimum RPC server that only logs the outgoing commands and received responses.
+ * (Does not process the packets or respond to them.)
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCSniffer {
+ public:
+  explicit MinRPCSniffer(TIOHandler* io)
+      : io_(io), ret(io), retWLog(&ret), exec(&retWLog), execWLog(&exec), next_(io, &execWLog) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+  void ProcessOneResponse() {
+    RPCCode code;
+    uint64_t packet_len = 0;
+
+    this->Read(&packet_len);
+    if (packet_len == 0) OutputLog();
+    this->Read(&code);
+    switch (code) {
+      case RPCCode::kReturn: {
+        HandleReturn();
+        break;
+      }
+      case RPCCode::kException: {
+        retWLog.ReturnException("");
+        break;
+      }
+      default: {
+        OutputLog();
+        break;
+      }
+    }
+  }
+
+ private:
+  void HandleReturn() {
+    int32_t num_args;
+    int32_t tcode;
+
+    this->Read(&num_args);
+    if (num_args == 1) {
+      this->Read(&tcode);
+      if (tcode == kTVMNullptr) {
+        retWLog.ReturnVoid();
+        return;
+      }
+      if (tcode == kTVMOpaqueHandle) {
+        uint64_t handle;
+        this->Read(&handle);
+        retWLog.ReturnHandle(reinterpret_cast<void*>(handle));
+        return;
+      }
+    }
+    OutputLog();
+  }
+
+  void OutputLog() { retWLog.getLogger()->OutputLog(); }
+
+  template <typename T>
+  void Read(T* data) {
+    static_assert(std::is_pod<T>::value, "need to be trival");
+    ReadRawBytes(data, sizeof(T));
+  }
+
+  void ReadRawBytes(void* data, size_t size) {
+    uint8_t* buf = reinterpret_cast<uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixRead(buf, size - ndone);
+      if (ret <= 0) {
+        retWLog.getLogger()->LogString("-> No Response Received.");
+        break;
+      }
+      ndone += ret;
+      buf += ret;
+    }
+  }
+
+  TIOHandler* io_;

Review Comment:
   thanks, fixed it!



##########
src/runtime/rpc/rpc_channel_logger.h:
##########
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+/*!
+ * \file rpc_channel_logger.h
+ * \brief A wrapper for RPCChannel with a NanoRPCListener for logging the commands.
+ */
+#ifndef TVM_RUNTIME_RPC_RPC_CHANNEL_LOGGER_H_
+#define TVM_RUNTIME_RPC_RPC_CHANNEL_LOGGER_H_
+
+#include <memory>
+#include <utility>
+
+#include "../minrpc/minrpc_server_logging.h"
+#include "rpc_channel.h"
+
+#define RX_BUFFER_SIZE 65536
+
+namespace tvm {
+namespace runtime {
+
+class Buffer {
+ public:
+  Buffer(uint8_t* data, size_t data_size_bytes)
+      : data_{data}, capacity_{data_size_bytes}, num_valid_bytes_{0}, read_cursor_{0} {}
+
+  size_t Write(const uint8_t* data, size_t data_size_bytes) {
+    size_t num_bytes_available = capacity_ - num_valid_bytes_;
+    size_t num_bytes_to_copy = data_size_bytes;
+    if (num_bytes_available < num_bytes_to_copy) {
+      num_bytes_to_copy = num_bytes_available;
+    }
+
+    memcpy(&data_[num_valid_bytes_], data, num_bytes_to_copy);
+    num_valid_bytes_ += num_bytes_to_copy;
+    return num_bytes_to_copy;
+  }
+
+  size_t Read(uint8_t* data, size_t data_size_bytes) {
+    size_t num_bytes_to_copy = data_size_bytes;
+    size_t num_bytes_available = num_valid_bytes_ - read_cursor_;
+    if (num_bytes_available < num_bytes_to_copy) {
+      num_bytes_to_copy = num_bytes_available;
+    }
+
+    memcpy(data, &data_[read_cursor_], num_bytes_to_copy);
+    read_cursor_ += num_bytes_to_copy;
+    return num_bytes_to_copy;
+  }
+
+  void Clear() {
+    num_valid_bytes_ = 0;
+    read_cursor_ = 0;
+  }
+
+  size_t ReadAvailable() const { return num_valid_bytes_ - read_cursor_; }
+
+  size_t Size() const { return num_valid_bytes_; }
+
+ private:
+  /*! \brief pointer to data buffer. */
+  uint8_t* data_;
+
+  /*! \brief The total number of bytes available in data_. Always a power of 2. */
+  size_t capacity_;
+
+  /*! \brief index into data_ of the next potentially-available byte in the buffer.
+   * The byte is available when tail_ != data_ + capacity_.
+   */
+  size_t num_valid_bytes_;
+
+  /*! \brief Read cursor position. */
+  size_t read_cursor_;
+};
+
+/*!
+ * \brief A simple IO handler for MinRPCSniffer.
+ *
+ * \tparam micro_rpc::FrameBuffer* buffer to store received data.
+ */
+class SnifferIOHandler {
+ public:
+  explicit SnifferIOHandler(Buffer* receive_buffer) : receive_buffer_(receive_buffer) {}
+
+  void MessageStart(size_t message_size_bytes) {}
+
+  ssize_t PosixWrite(const uint8_t* buf, size_t buf_size_bytes) { return 0; }
+
+  void MessageDone() {}
+
+  ssize_t PosixRead(uint8_t* buf, size_t buf_size_bytes) {
+    return receive_buffer_->Read(buf, buf_size_bytes);
+  }
+
+  void Close() {}
+
+  void Exit(int code) {}
+
+ private:
+  Buffer* receive_buffer_;
+};
+
+/*!
+ * \brief A simple rpc session that logs the received commands.
+ */
+class NanoRPCListener {
+ public:
+  NanoRPCListener()
+      : receive_buffer_(receive_storage, receive_storage_size_bytes),
+        io_(&receive_buffer_),
+        rpc_server_(&io_) {}
+
+  void Listen(const uint8_t* data, size_t size) { receive_buffer_.Write(data, size); }
+
+  void ProcessTxPacket() {
+    rpc_server_.ProcessOnePacket();
+    ClearBuffer();
+  }
+
+  void ProcessRxPacket() {
+    rpc_server_.ProcessOneResponse();
+    ClearBuffer();
+  }
+
+ private:
+  void ClearBuffer() { receive_buffer_.Clear(); }
+
+ private:
+  size_t receive_storage_size_bytes = RX_BUFFER_SIZE;

Review Comment:
   thanks, fixed it!



##########
src/runtime/rpc/rpc_channel_logger.h:
##########
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+/*!
+ * \file rpc_channel_logger.h
+ * \brief A wrapper for RPCChannel with a NanoRPCListener for logging the commands.
+ */
+#ifndef TVM_RUNTIME_RPC_RPC_CHANNEL_LOGGER_H_
+#define TVM_RUNTIME_RPC_RPC_CHANNEL_LOGGER_H_
+
+#include <memory>
+#include <utility>
+
+#include "../minrpc/minrpc_server_logging.h"
+#include "rpc_channel.h"
+
+#define RX_BUFFER_SIZE 65536
+
+namespace tvm {
+namespace runtime {
+
+class Buffer {
+ public:
+  Buffer(uint8_t* data, size_t data_size_bytes)
+      : data_{data}, capacity_{data_size_bytes}, num_valid_bytes_{0}, read_cursor_{0} {}
+
+  size_t Write(const uint8_t* data, size_t data_size_bytes) {
+    size_t num_bytes_available = capacity_ - num_valid_bytes_;
+    size_t num_bytes_to_copy = data_size_bytes;
+    if (num_bytes_available < num_bytes_to_copy) {
+      num_bytes_to_copy = num_bytes_available;
+    }
+
+    memcpy(&data_[num_valid_bytes_], data, num_bytes_to_copy);
+    num_valid_bytes_ += num_bytes_to_copy;
+    return num_bytes_to_copy;
+  }
+
+  size_t Read(uint8_t* data, size_t data_size_bytes) {
+    size_t num_bytes_to_copy = data_size_bytes;
+    size_t num_bytes_available = num_valid_bytes_ - read_cursor_;
+    if (num_bytes_available < num_bytes_to_copy) {
+      num_bytes_to_copy = num_bytes_available;
+    }
+
+    memcpy(data, &data_[read_cursor_], num_bytes_to_copy);
+    read_cursor_ += num_bytes_to_copy;
+    return num_bytes_to_copy;
+  }
+
+  void Clear() {
+    num_valid_bytes_ = 0;
+    read_cursor_ = 0;
+  }
+
+  size_t ReadAvailable() const { return num_valid_bytes_ - read_cursor_; }
+
+  size_t Size() const { return num_valid_bytes_; }
+
+ private:
+  /*! \brief pointer to data buffer. */
+  uint8_t* data_;
+
+  /*! \brief The total number of bytes available in data_. Always a power of 2. */
+  size_t capacity_;
+
+  /*! \brief index into data_ of the next potentially-available byte in the buffer.
+   * The byte is available when tail_ != data_ + capacity_.

Review Comment:
   thanks, fixed it!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r852332133


##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,307 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      this->LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      this->LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      this->LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      this->LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      this->LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      this->LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      this->LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      this->LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      this->LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      this->LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      this->LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      this->LogString("\"");
+      this->LogString(value.v_str);
+      this->LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      this->LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        this->LogString(", [Values]:");
+        this->LogString(" { ");
+        if (len > 0) {
+          this->LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) this->LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        this->LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      this->LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  this->LogString("; ");
+}
+
+std::stringstream Logger::LogTime() {
+  char buf[100];
+  time_t t;
+  struct tm *timeptr, result, temp;
+  std::stringstream ss;
+
+  t = time(NULL);
+  timeptr = localtime_r(&t, &temp);
+  strftime(buf, sizeof(buf), "%a %m/%d/%Y %r", timeptr);
+
+  if (strptime(buf, "%a %m/%d/%Y %r", &result) == NULL) {
+    ss << "TIME UNKNOWN, ";
+  } else {
+    ss << result.tm_hour << ":" << result.tm_min << ":" << result.tm_sec << ", ";
+  }
+  return ss;
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  this->os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (this->code_ == RPCCode::kGetGlobalFunc) {
+    this->registerHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  processValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnLastTVMError() {
+  const char* err = TVMGetLastError();
+  this->ReturnException(err);
+}
+
+void MinRPCReturnsWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  next_->ThrowError(code, info);
+  logger_.LogString("-> ERROR");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::processValues(const TVMValue** values, const int** tcodes,
+                                         int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_.LogString("-> [");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_.LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMOpaqueHandle) {
+        this->registerHandleName((*values)[i].v_handle);
+      }
+    }
+    logger_.LogString("]");
+  }
+}
+
+void MinRPCReturnsWithLog::resetCurrHandleName(RPCCode code) {
+  this->code_ = code;
+  logger_.LogString(RPCCodeToString(code));
+  logger_.LogString(", ");
+  this->CurrHandleName_.clear();
+}
+
+void MinRPCReturnsWithLog::updateCurrHandleName(const char* name) {
+  if (this->CurrHandleName_.length() != 0) {
+    this->CurrHandleName_.append("::");
+  }
+  this->CurrHandleName_.append(name);
+}
+
+void MinRPCReturnsWithLog::getHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    CurrHandleName_.append(array_tracker_[handle]);
+    logger_.LogHandleName(CurrHandleName_);
+  }
+}
+
+void MinRPCReturnsWithLog::releaseHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    logger_.LogHandleName(array_tracker_[handle]);
+    array_tracker_.erase(handle);
+  }
+}
+
+void MinRPCReturnsWithLog::registerHandleName(void* handle) {
+  const std::string newString = CurrHandleName_;
+  array_tracker_[handle] = newString;

Review Comment:
   Thank you, fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r852332550


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  std::stringstream LogTime();
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void processValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void resetCurrHandleName(RPCCode code);
+
+  void updateCurrHandleName(const char* name);
+
+  void getHandleName(void* handle);
+
+  void releaseHandleName(void* handle);
+
+  Logger* getLogger() { return &logger_; }
+
+ private:
+  void registerHandleName(void* handle);

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r852330594


##########
src/runtime/minrpc/minrpc_intrfc.h:
##########
@@ -0,0 +1,63 @@
+/*

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] kparzysz-quic commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
kparzysz-quic commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r851657346


##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,307 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      this->LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      this->LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      this->LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      this->LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      this->LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      this->LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      this->LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      this->LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      this->LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      this->LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      this->LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      this->LogString("\"");
+      this->LogString(value.v_str);
+      this->LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      this->LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        this->LogString(", [Values]:");
+        this->LogString(" { ");
+        if (len > 0) {
+          this->LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) this->LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        this->LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      this->LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  this->LogString("; ");
+}
+
+std::stringstream Logger::LogTime() {
+  char buf[100];
+  time_t t;
+  struct tm *timeptr, result, temp;
+  std::stringstream ss;
+
+  t = time(NULL);
+  timeptr = localtime_r(&t, &temp);
+  strftime(buf, sizeof(buf), "%a %m/%d/%Y %r", timeptr);
+
+  if (strptime(buf, "%a %m/%d/%Y %r", &result) == NULL) {
+    ss << "TIME UNKNOWN, ";
+  } else {
+    ss << result.tm_hour << ":" << result.tm_min << ":" << result.tm_sec << ", ";
+  }
+  return ss;
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  this->os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (this->code_ == RPCCode::kGetGlobalFunc) {
+    this->registerHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  processValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnLastTVMError() {
+  const char* err = TVMGetLastError();
+  this->ReturnException(err);
+}
+
+void MinRPCReturnsWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  next_->ThrowError(code, info);
+  logger_.LogString("-> ERROR");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::processValues(const TVMValue** values, const int** tcodes,
+                                         int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_.LogString("-> [");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_.LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMOpaqueHandle) {
+        this->registerHandleName((*values)[i].v_handle);
+      }
+    }
+    logger_.LogString("]");
+  }
+}
+
+void MinRPCReturnsWithLog::resetCurrHandleName(RPCCode code) {
+  this->code_ = code;
+  logger_.LogString(RPCCodeToString(code));
+  logger_.LogString(", ");
+  this->CurrHandleName_.clear();
+}
+
+void MinRPCReturnsWithLog::updateCurrHandleName(const char* name) {
+  if (this->CurrHandleName_.length() != 0) {
+    this->CurrHandleName_.append("::");
+  }
+  this->CurrHandleName_.append(name);
+}
+
+void MinRPCReturnsWithLog::getHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    CurrHandleName_.append(array_tracker_[handle]);
+    logger_.LogHandleName(CurrHandleName_);
+  }
+}
+
+void MinRPCReturnsWithLog::releaseHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    logger_.LogHandleName(array_tracker_[handle]);
+    array_tracker_.erase(handle);
+  }
+}
+
+void MinRPCReturnsWithLog::registerHandleName(void* handle) {
+  const std::string newString = CurrHandleName_;
+  array_tracker_[handle] = newString;

Review Comment:
   ```
   array_tracker_[handle] = CurrHandleName_;
   ```



##########
src/runtime/minrpc/minrpc_server_logging.h:
##########
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+
+#include "minrpc_logger.h"
+#include "minrpc_server.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief A minimum RPC server that logs the received commands.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCServerWithLog {
+ public:
+  explicit MinRPCServerWithLog(TIOHandler* io)
+      : ret_handler_(io),
+        ret_handler_WLog_(&ret_handler_),
+        exec_handler_(io, &ret_handler_WLog_),
+        exec_handler_WLog_(&exec_handler_),
+        next_(io, &exec_handler_WLog_) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+ private:
+  MinRPCReturns<TIOHandler> ret_handler_;
+  MinRPCExecute<TIOHandler> exec_handler_;
+  MinRPCReturnsWithLog ret_handler_WLog_;
+  MinRPCExecuteWithLog exec_handler_WLog_;
+  MinRPCServer<TIOHandler> next_;
+};
+
+/*!
+ * \brief A minimum RPC server that only logs the outgoing commands and received responses.
+ * (Does not process the packets or respond to them.)
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCSniffer {
+ public:
+  explicit MinRPCSniffer(TIOHandler* io)
+      : io_(io),
+        ret_handler_(io_),
+        ret_handler_WLog_(&ret_handler_),
+        exec_handler_(&ret_handler_WLog_),
+        exec_handler_WLog_(&exec_handler_),
+        next_(io_, &exec_handler_WLog_) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+  void ProcessOneResponse() {
+    RPCCode code;
+    uint64_t packet_len = 0;
+
+    this->Read(&packet_len);
+    if (packet_len == 0) OutputLog();
+    this->Read(&code);
+    switch (code) {
+      case RPCCode::kReturn: {
+        HandleReturn();
+        break;
+      }
+      case RPCCode::kException: {
+        ret_handler_WLog_.ReturnException("");
+        break;
+      }
+      default: {
+        OutputLog();
+        break;
+      }
+    }
+  }
+
+ private:
+  void HandleReturn() {
+    int32_t num_args;
+    int32_t tcode;
+
+    this->Read(&num_args);
+    if (num_args == 1) {
+      this->Read(&tcode);
+      if (tcode == kTVMNullptr) {
+        ret_handler_WLog_.ReturnVoid();
+        return;
+      }
+      if (tcode == kTVMOpaqueHandle) {
+        uint64_t handle;
+        this->Read(&handle);
+        ret_handler_WLog_.ReturnHandle(reinterpret_cast<void*>(handle));
+        return;
+      }
+    }
+    OutputLog();
+  }
+
+  void OutputLog() { ret_handler_WLog_.getLogger()->OutputLog(); }
+
+  template <typename T>
+  void Read(T* data) {
+    static_assert(std::is_pod<T>::value, "need to be trival");

Review Comment:
   Please use `is_trivial && is_standard_layout` instead of `is_pod`.  `is_pod` is deprecated (in C++20 onwards).



##########
src/runtime/minrpc/minrpc_intrfc.h:
##########
@@ -0,0 +1,63 @@
+/*

Review Comment:
   Could you spell out the full name, i.e. make the file name `minrpc_interface.h`?



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  std::stringstream LogTime();
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void processValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void resetCurrHandleName(RPCCode code);
+
+  void updateCurrHandleName(const char* name);
+
+  void getHandleName(void* handle);
+
+  void releaseHandleName(void* handle);
+
+  Logger* getLogger() { return &logger_; }
+
+ private:
+  void registerHandleName(void* handle);
+
+  ReturnInterface* next_;
+  std::string CurrHandleName_;
+  std::unordered_map<void*, std::string> array_tracker_;
+  RPCCode code_;
+  Logger logger_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCExecute object, that also logs the responses.
+ *
+ * \tparam RExecInterface* underlying MinRPCExecute that processes the packets.
+ */
+class MinRPCExecuteWithLog : public ExecInterface {
+ public:
+  explicit MinRPCExecuteWithLog(ExecInterface* next) : next_(next) {
+    this->ret_handler_ = reinterpret_cast<MinRPCReturnsWithLog*>(next_->getReturnInterface());
+    this->logger_ = ret_handler_->getLogger();
+  }
+
+  ~MinRPCExecuteWithLog() {}
+
+  void ExecInitServer(int* _num_args);

Review Comment:
   No names with leading `_`, please.



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  std::stringstream LogTime();
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void processValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void resetCurrHandleName(RPCCode code);
+
+  void updateCurrHandleName(const char* name);
+
+  void getHandleName(void* handle);
+
+  void releaseHandleName(void* handle);
+
+  Logger* getLogger() { return &logger_; }

Review Comment:
   Function names should start with capital letters (TVM uses Google's naming conventions).



##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,307 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      this->LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      this->LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      this->LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      this->LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      this->LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      this->LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      this->LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      this->LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      this->LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      this->LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      this->LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      this->LogString("\"");
+      this->LogString(value.v_str);
+      this->LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      this->LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        this->LogString(", [Values]:");
+        this->LogString(" { ");
+        if (len > 0) {
+          this->LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) this->LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        this->LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      this->LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  this->LogString("; ");
+}
+
+std::stringstream Logger::LogTime() {
+  char buf[100];
+  time_t t;
+  struct tm *timeptr, result, temp;
+  std::stringstream ss;
+
+  t = time(NULL);
+  timeptr = localtime_r(&t, &temp);
+  strftime(buf, sizeof(buf), "%a %m/%d/%Y %r", timeptr);
+
+  if (strptime(buf, "%a %m/%d/%Y %r", &result) == NULL) {

Review Comment:
   Please use `std::put_time` and `std::localtime` instead to get formatted time string.



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  std::stringstream LogTime();
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void processValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void resetCurrHandleName(RPCCode code);
+
+  void updateCurrHandleName(const char* name);
+
+  void getHandleName(void* handle);
+
+  void releaseHandleName(void* handle);
+
+  Logger* getLogger() { return &logger_; }
+
+ private:
+  void registerHandleName(void* handle);

Review Comment:
   Same here.



##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,307 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      this->LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      this->LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      this->LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      this->LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      this->LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      this->LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      this->LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      this->LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      this->LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      this->LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      this->LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      this->LogString("\"");
+      this->LogString(value.v_str);
+      this->LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      this->LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        this->LogString(", [Values]:");
+        this->LogString(" { ");
+        if (len > 0) {
+          this->LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) this->LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        this->LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      this->LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  this->LogString("; ");
+}
+
+std::stringstream Logger::LogTime() {
+  char buf[100];
+  time_t t;
+  struct tm *timeptr, result, temp;
+  std::stringstream ss;
+
+  t = time(NULL);
+  timeptr = localtime_r(&t, &temp);
+  strftime(buf, sizeof(buf), "%a %m/%d/%Y %r", timeptr);
+
+  if (strptime(buf, "%a %m/%d/%Y %r", &result) == NULL) {
+    ss << "TIME UNKNOWN, ";
+  } else {
+    ss << result.tm_hour << ":" << result.tm_min << ":" << result.tm_sec << ", ";
+  }
+  return ss;
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  this->os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (this->code_ == RPCCode::kGetGlobalFunc) {
+    this->registerHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  processValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnLastTVMError() {
+  const char* err = TVMGetLastError();
+  this->ReturnException(err);
+}
+
+void MinRPCReturnsWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  next_->ThrowError(code, info);
+  logger_.LogString("-> ERROR");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::processValues(const TVMValue** values, const int** tcodes,
+                                         int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_.LogString("-> [");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_.LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMOpaqueHandle) {
+        this->registerHandleName((*values)[i].v_handle);
+      }
+    }
+    logger_.LogString("]");
+  }
+}
+
+void MinRPCReturnsWithLog::resetCurrHandleName(RPCCode code) {
+  this->code_ = code;
+  logger_.LogString(RPCCodeToString(code));
+  logger_.LogString(", ");
+  this->CurrHandleName_.clear();
+}
+
+void MinRPCReturnsWithLog::updateCurrHandleName(const char* name) {
+  if (this->CurrHandleName_.length() != 0) {
+    this->CurrHandleName_.append("::");
+  }
+  this->CurrHandleName_.append(name);
+}
+
+void MinRPCReturnsWithLog::getHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    CurrHandleName_.append(array_tracker_[handle]);
+    logger_.LogHandleName(CurrHandleName_);
+  }
+}
+
+void MinRPCReturnsWithLog::releaseHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    logger_.LogHandleName(array_tracker_[handle]);
+    array_tracker_.erase(handle);
+  }
+}
+
+void MinRPCReturnsWithLog::registerHandleName(void* handle) {
+  const std::string newString = CurrHandleName_;
+  array_tracker_[handle] = newString;
+}
+
+void MinRPCExecuteWithLog::ExecInitServer(int* _num_args) {
+  setRPCCode(RPCCode::kInitServer);
+  logger_->LogString("Init Server");
+  next_->ExecInitServer(_num_args);
+}
+
+void MinRPCExecuteWithLog::ExecNormalCallFunc(uint64_t* call_handle, TVMValue** values,
+                                              int** tcodes, int* num_args) {
+  setRPCCode(RPCCode::kCallFunc);
+  logger_->LogVal<void*>("call_handle: ", reinterpret_cast<void*>(*call_handle));
+  ret_handler_->getHandleName(reinterpret_cast<void*>(*call_handle));
+  if (*num_args > 0) {
+    logger_->LogString(", ");
+  }
+  this->processValues(values, tcodes, num_args);
+  next_->ExecNormalCallFunc(call_handle, values, tcodes, num_args);
+}
+
+void MinRPCExecuteWithLog::ExecCopyFromRemote(DLTensor** arr, uint64_t* num_bytes,
+                                              uint8_t** temp_data) {
+  setRPCCode(RPCCode::kCopyFromRemote);
+  logger_->LogVal<void*>("data_handle: ", reinterpret_cast<void*>((*arr)->data));
+  logger_->LogDLDevice(", DLDevice(type,id):", &(*arr)->device);
+  logger_->LogVal<int64_t>(", ndim: ", (*arr)->ndim);
+  logger_->LogDLData(", DLDataType(code,bits,lane): ", &(*arr)->dtype);
+  logger_->LogVal<uint64_t>(", num_bytes:", *num_bytes);
+  next_->ExecCopyFromRemote(arr, num_bytes, temp_data);
+}
+
+int MinRPCExecuteWithLog::ExecCopyToRemote(DLTensor** arr, uint64_t* _num_bytes,
+                                           uint8_t** _data_ptr) {

Review Comment:
   Please don't use names that start with `_`.



##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,307 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      this->LogVal<int64_t>("(int64)", value.v_int64);

Review Comment:
   Please remove the `this->` from everywhere in this PR.  In a vast majority of cases it's unnecessary and only adds to the clutter.



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  std::stringstream LogTime();
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void processValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void resetCurrHandleName(RPCCode code);
+
+  void updateCurrHandleName(const char* name);
+
+  void getHandleName(void* handle);
+
+  void releaseHandleName(void* handle);
+
+  Logger* getLogger() { return &logger_; }
+
+ private:
+  void registerHandleName(void* handle);
+
+  ReturnInterface* next_;
+  std::string CurrHandleName_;

Review Comment:
   Use snake_case for variable names (i.e. curr_handle_name_).  At least be consistent within the same region of code.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r854274054


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -524,94 +523,249 @@ class MinRPCServer {
     int call_ecode = TVMSetStream(dev.device_type, dev.device_id, handle);
 
     if (call_ecode == 0) {
-      this->ReturnVoid();
+      ret_handler_->ReturnVoid();
     } else {
-      this->ReturnLastTVMError();
+      ret_handler_->ReturnLastTVMError();
     }
   }
 
   void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone) {
-    io_->Exit(static_cast<int>(code));
+    ret_handler_->ThrowError(code, info);
   }
 
+  ReturnInterface* GetReturnInterface() { return ret_handler_; }
+
+ private:
   template <typename T>
-  T* ArenaAlloc(int count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return arena_.template allocate_<T>(count);
+  int ReadArray(T* data, size_t count) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    return ReadRawBytes(data, sizeof(T) * count);
   }
 
-  template <typename T>
-  void Read(T* data) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    this->ReadRawBytes(data, sizeof(T));
+  int ReadRawBytes(void* data, size_t size) {
+    uint8_t* buf = reinterpret_cast<uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixRead(buf, size - ndone);
+      if (ret <= 0) return ret;
+      ndone += ret;
+      buf += ret;
+    }
+    return 1;
   }
 
-  template <typename T>
-  void ReadArray(T* data, size_t count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return this->ReadRawBytes(data, sizeof(T) * count);
+  TIOHandler* io_;
+  ReturnInterface* ret_handler_;
+};
+
+/*!
+ * \brief A minimum RPC server that only depends on the tvm C runtime..
+ *
+ *  All the dependencies are provided by the io arguments.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ *         An IOHandler needs to provide the following functions:
+ *         - PosixWrite, PosixRead, Close: posix style, read, write, close API.
+ *         - MessageStart(num_bytes), MessageDone(): framing APIs.
+ *         - Exit: exit with status code.
+ */
+template <typename TIOHandler, template <typename> class Allocator = detail::PageAllocator>
+class MinRPCServer {
+ public:
+  using PageAllocator = Allocator<TIOHandler>;
+
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  MinRPCServer(TIOHandler* io, ExecInterface* exec_handler)
+      : io_(io), arena_(PageAllocator(io_)), exec_handler_(exec_handler) {}
+
+  explicit MinRPCServer(TIOHandler* io)
+      : io_(io),
+        arena_(PageAllocator(io)),
+        ret_handler_(new MinRPCReturns<TIOHandler>(io_)),
+        exec_handler_(new MinRPCExecute<TIOHandler>(io_, ret_handler_)) {}

Review Comment:
   Thank you very much for taking the time to read through the code, and for valuable comments.
   Initially, I wanted to address this using unique_ptrs, but including <memory> generates the "redefinition of operator new" error in rpc_server.cc. So, I simply use the "ret_handler_" variable as a flag to infer which constructor is used, and delete the allocated variables when needed.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861411798


##########
src/runtime/minrpc/minrpc_interfaces.h:
##########
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief Return interface used in ExecInterface to generate and sent the responses.

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] alanmacd commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
alanmacd commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r864025221


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -28,14 +28,23 @@
 #ifndef TVM_RUNTIME_MINRPC_MINRPC_SERVER_H_
 #define TVM_RUNTIME_MINRPC_MINRPC_SERVER_H_
 
+#ifndef DMLC_LITTLE_ENDIAN
 #define DMLC_LITTLE_ENDIAN 1
+#endif
+
 #include <string.h>
 #include <tvm/runtime/c_runtime_api.h>
 
+#include <memory>
+#include <utility>
+
 #include "../../support/generic_arena.h"
+#include "minrpc_interfaces.h"
 #include "rpc_reference.h"
 
 /*! \brief Whether or not to enable glog style DLOG */
+#define TVM_MINRPC_ENABLE_LOGGING 1
+
 #ifndef TVM_MINRPC_ENABLE_LOGGING
 #define TVM_MINRPC_ENABLE_LOGGING 0

Review Comment:
   is this needed, since it's #define'd to 1 in previous line?



##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {

Review Comment:
   nit: switch cases braces style inconsistent



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] alanmacd commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
alanmacd commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r864025221


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -28,14 +28,23 @@
 #ifndef TVM_RUNTIME_MINRPC_MINRPC_SERVER_H_
 #define TVM_RUNTIME_MINRPC_MINRPC_SERVER_H_
 
+#ifndef DMLC_LITTLE_ENDIAN
 #define DMLC_LITTLE_ENDIAN 1
+#endif
+
 #include <string.h>
 #include <tvm/runtime/c_runtime_api.h>
 
+#include <memory>
+#include <utility>
+
 #include "../../support/generic_arena.h"
+#include "minrpc_interfaces.h"
 #include "rpc_reference.h"
 
 /*! \brief Whether or not to enable glog style DLOG */
+#define TVM_MINRPC_ENABLE_LOGGING 1
+
 #ifndef TVM_MINRPC_ENABLE_LOGGING
 #define TVM_MINRPC_ENABLE_LOGGING 0

Review Comment:
   is #ifndef TVM_MINRPC_ENABLE_LOGGING needed, since it's #define'd to 1 in previous line?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] alanmacd commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
alanmacd commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r849974287


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogTVMValue(int tcode, TVMValue value) {
+    switch (tcode) {
+      case kDLInt:
+        this->LogVal<int64_t>("(int64)", value.v_int64);
+        break;
+      case kDLUInt:
+        this->LogVal<uint64_t>("(uint64)", value.v_int64);
+        break;
+      case kDLFloat: {
+        this->LogVal<float>("(float)", value.v_float64);
+        break;
+      }
+      case kTVMDataType: {
+        this->LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+        break;
+      }
+      case kDLDevice: {
+        this->LogDLDevice("DLDevice(type,id)", &value.v_device);
+        break;
+      }
+      case kTVMPackedFuncHandle: {
+        this->LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+        break;
+      }
+      case kTVMModuleHandle: {
+        this->LogVal<void*>("(ModuleHandle)", value.v_handle);
+        break;
+      }
+      case kTVMOpaqueHandle: {
+        this->LogVal<void*>("(OpaqueHandle)", value.v_handle);
+        break;
+      }
+      case kTVMDLTensorHandle: {
+        this->LogVal<void*>("(TensorHandle)", value.v_handle);
+        break;
+      }
+      case kTVMNDArrayHandle: {
+        this->LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+        break;
+      }
+      case kTVMNullptr:
+        this->LogString("Nullptr");
+        break;
+      case kTVMStr: {
+        this->LogString("\"");
+        this->LogString(value.v_str);
+        this->LogString("\"");
+        break;
+      }
+      case kTVMBytes: {
+        TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+        int len = bytes->size;
+        this->LogVal<int64_t>("(Bytes) [size]: ", len);
+        if (PRINT_BYTES) {
+          this->LogString(", [Values]:");
+          this->LogString(" { ");
+          if (len > 0) {
+            this->LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+          }
+          for (int j = 1; j < len; j++) this->LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+          this->LogString(" } ");
+        }
+        break;
+      }
+      default: {
+        this->LogString("ERROR-kUnknownTypeCode)");
+        break;
+      }
+    }
+    this->LogString("; ");
+  }
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  std::stringstream LogTime();
+
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next);
+  ~MinRPCReturnsWithLog();
+  void ReturnVoid();
+  void ReturnHandle(void* handle);
+  void ReturnException(const char* msg);
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+  void ReturnLastTVMError();
+  void ThrowError(RPCServerStatus code, RPCCode info);
+  void processValues(const TVMValue** values, const int** tcodes, int* num_args);
+  void resetCurrHandleName(RPCCode code);
+  void updateCurrHandleName(const char* name);
+  void getHandleName(void* handle);
+  void releaseHandleName(void* handle);
+  Logger* getLogger();
+
+ private:
+  void registerHandleName(void* handle);
+  ReturnInterface* next_;
+  std::string CurrHandleName;
+  std::unordered_map<void*, std::string> array_tracker;
+  RPCCode code;
+  Logger logger_;
+  Logger* logger = &logger_;

Review Comment:
   Is this needed? I feel like it adds a bit of confusion when reading implementation.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] alanmacd commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
alanmacd commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r849970761


##########
src/runtime/minrpc/minrpc_server_logging.h:
##########
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+
+#include "minrpc_logger.h"
+#include "minrpc_server.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief A minimum RPC server that logs the received commands.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCServerWithLog {
+ public:
+  explicit MinRPCServerWithLog(TIOHandler* io)
+      : ret(io), retWLog(&ret), exec(io, &retWLog), execWLog(&exec), next_(io, &execWLog) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+ private:
+  MinRPCReturns<TIOHandler> ret;

Review Comment:
   I believe the style is trailing '_' on all member variables



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] alanmacd commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
alanmacd commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r849982204


##########
src/runtime/rpc/rpc_channel_logger.h:
##########
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+/*!
+ * \file rpc_channel_logger.h
+ * \brief A wrapper for RPCChannel with a NanoRPCListener for logging the commands.
+ */
+#ifndef TVM_RUNTIME_RPC_RPC_CHANNEL_LOGGER_H_
+#define TVM_RUNTIME_RPC_RPC_CHANNEL_LOGGER_H_
+
+#include <memory>
+#include <utility>
+
+#include "../minrpc/minrpc_server_logging.h"
+#include "rpc_channel.h"
+
+#define RX_BUFFER_SIZE 65536
+
+namespace tvm {
+namespace runtime {
+
+class Buffer {
+ public:
+  Buffer(uint8_t* data, size_t data_size_bytes)
+      : data_{data}, capacity_{data_size_bytes}, num_valid_bytes_{0}, read_cursor_{0} {}
+
+  size_t Write(const uint8_t* data, size_t data_size_bytes) {
+    size_t num_bytes_available = capacity_ - num_valid_bytes_;
+    size_t num_bytes_to_copy = data_size_bytes;
+    if (num_bytes_available < num_bytes_to_copy) {
+      num_bytes_to_copy = num_bytes_available;
+    }
+
+    memcpy(&data_[num_valid_bytes_], data, num_bytes_to_copy);
+    num_valid_bytes_ += num_bytes_to_copy;
+    return num_bytes_to_copy;
+  }
+
+  size_t Read(uint8_t* data, size_t data_size_bytes) {
+    size_t num_bytes_to_copy = data_size_bytes;
+    size_t num_bytes_available = num_valid_bytes_ - read_cursor_;
+    if (num_bytes_available < num_bytes_to_copy) {
+      num_bytes_to_copy = num_bytes_available;
+    }
+
+    memcpy(data, &data_[read_cursor_], num_bytes_to_copy);
+    read_cursor_ += num_bytes_to_copy;
+    return num_bytes_to_copy;
+  }
+
+  void Clear() {
+    num_valid_bytes_ = 0;
+    read_cursor_ = 0;
+  }
+
+  size_t ReadAvailable() const { return num_valid_bytes_ - read_cursor_; }
+
+  size_t Size() const { return num_valid_bytes_; }
+
+ private:
+  /*! \brief pointer to data buffer. */
+  uint8_t* data_;
+
+  /*! \brief The total number of bytes available in data_. Always a power of 2. */
+  size_t capacity_;
+
+  /*! \brief index into data_ of the next potentially-available byte in the buffer.
+   * The byte is available when tail_ != data_ + capacity_.
+   */
+  size_t num_valid_bytes_;
+
+  /*! \brief Read cursor position. */
+  size_t read_cursor_;
+};
+
+/*!
+ * \brief A simple IO handler for MinRPCSniffer.
+ *
+ * \tparam micro_rpc::FrameBuffer* buffer to store received data.
+ */
+class SnifferIOHandler {
+ public:
+  explicit SnifferIOHandler(Buffer* receive_buffer) : receive_buffer_(receive_buffer) {}
+
+  void MessageStart(size_t message_size_bytes) {}
+
+  ssize_t PosixWrite(const uint8_t* buf, size_t buf_size_bytes) { return 0; }
+
+  void MessageDone() {}
+
+  ssize_t PosixRead(uint8_t* buf, size_t buf_size_bytes) {
+    return receive_buffer_->Read(buf, buf_size_bytes);
+  }
+
+  void Close() {}
+
+  void Exit(int code) {}
+
+ private:
+  Buffer* receive_buffer_;
+};
+
+/*!
+ * \brief A simple rpc session that logs the received commands.
+ */
+class NanoRPCListener {
+ public:
+  NanoRPCListener()
+      : receive_buffer_(receive_storage, receive_storage_size_bytes),
+        io_(&receive_buffer_),
+        rpc_server_(&io_) {}
+
+  void Listen(const uint8_t* data, size_t size) { receive_buffer_.Write(data, size); }
+
+  void ProcessTxPacket() {
+    rpc_server_.ProcessOnePacket();
+    ClearBuffer();
+  }
+
+  void ProcessRxPacket() {
+    rpc_server_.ProcessOneResponse();
+    ClearBuffer();
+  }
+
+ private:
+  void ClearBuffer() { receive_buffer_.Clear(); }
+
+ private:
+  size_t receive_storage_size_bytes = RX_BUFFER_SIZE;

Review Comment:
   Add trailing underscore



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861413477


##########
src/runtime/minrpc/minrpc_interfaces.h:
##########
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief Return interface used in ExecInterface to generate and sent the responses.
+ */
+class ReturnInterface {
+ public:
+  virtual ~ReturnInterface() {}
+  virtual void ReturnVoid() = 0;
+  virtual void ReturnHandle(void* handle) = 0;
+  virtual void ReturnException(const char* msg) = 0;
+  virtual void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args) = 0;
+  virtual void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) = 0;
+  virtual void ReturnLastTVMError() = 0;
+  virtual void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone) = 0;
+};
+
+/*!
+ * \brief Execute interface used in MinRPCServer to process different received commands
+ */
+class ExecInterface {
+ public:
+  virtual ~ExecInterface() {}
+  virtual void ExecInitServer(int* num_args) = 0;

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861412537


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] areusch commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
areusch commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r855393554


##########
python/tvm/rpc/client.py:
##########
@@ -514,7 +517,10 @@ def connect(url, port, key="", session_timeout=0, session_constructor_args=None)
         session_constructor_args = session_constructor_args if session_constructor_args else []
         if not isinstance(session_constructor_args, (list, tuple)):
             raise TypeError("Expect the session constructor to be a list or tuple")
-        sess = _ffi_api.Connect(url, port, key, *session_constructor_args)
+        enable_logging = False

Review Comment:
   since you just use this one kwarg and you aren't passing them en masse somewhere else, i think better function signature would be `connect(..., enable_logging=False)` rather than **kwargs. then you don't need this logic.



##########
python/tvm/rpc/client.py:
##########
@@ -505,7 +508,7 @@ def connect(url, port, key="", session_timeout=0, session_constructor_args=None)
         client_via_proxy = rpc.connect(
             proxy_server_url, proxy_server_port, proxy_server_key,
             session_constructor_args=[
-                "rpc.Connect", internal_url, internal_port, internal_key])
+                "rpc.Connect", internal_url, internal_port, internal_key, enable_logging])

Review Comment:
   i think here you mean
   ```suggestion
                   "rpc.Connect", internal_url, internal_port, internal_key],
                   enable_logging=True)
   ```



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.

Review Comment:
   params don't match the args



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {

Review Comment:
   expand the function name (e.g. `LogValue`). also, can you choose a better name for `s` and document its expected usage in a docstring?



##########
src/runtime/minrpc/minrpc_interfaces.h:
##########
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief Return interface used in ExecInterface to generate and sent the responses.

Review Comment:
   could you add similar docstrings for the functions here?



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void ProcessValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void ResetCurrHandleName(RPCCode code);

Review Comment:
   nit: expand Curr -> Current or just remove it.



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void ProcessValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void ResetCurrHandleName(RPCCode code);
+
+  void UpdateCurrHandleName(const char* name);
+
+  void GetHandleName(void* handle);
+
+  void ReleaseHandleName(void* handle);
+
+  Logger* GetLogger() { return &logger_; }
+
+ private:
+  void RegisterHandleName(void* handle);
+
+  ReturnInterface* next_;
+  std::string curr_handle_name_;
+  std::unordered_map<void*, std::string> array_tracker_;

Review Comment:
   suggest a name like `handle_descriptions_` or `handles_to_names_`



##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      LogString("\"");
+      LogString(value.v_str);
+      LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        LogString(", [Values]:");
+        LogString(" { ");
+        if (len > 0) {
+          LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  LogString("; ");
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (code_ == RPCCode::kGetGlobalFunc) {
+    RegisterHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  ProcessValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));

Review Comment:
   i think you can use static_cast<void*> here (and in general, try to use this instead of reinterpret_cast wherever possible)



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }

Review Comment:
   these two functions (LogString and LogStr) are confusingly-named--when would you use LogString vs LogStr?
   
   Based on the impl, i think the usage might be the same (print this string to the log)--so you could rely on c++ function overloading e.g.
   `void Log(const char* s) { os_ << s; }`
   and 
   `void Log(std::string s) { os_ << s; }`
   



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}

Review Comment:
   nit: remove `, logger_()` since it's implied



##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      LogString("\"");
+      LogString(value.v_str);
+      LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        LogString(", [Values]:");
+        LogString(" { ");
+        if (len > 0) {
+          LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  LogString("; ");
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (code_ == RPCCode::kGetGlobalFunc) {
+    RegisterHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  ProcessValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnLastTVMError() {
+  const char* err = TVMGetLastError();
+  ReturnException(err);
+}
+
+void MinRPCReturnsWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  next_->ThrowError(code, info);
+  logger_.LogString("-> ERROR");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ProcessValues(const TVMValue** values, const int** tcodes,
+                                         int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_.LogString("-> [");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_.LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMOpaqueHandle) {
+        RegisterHandleName((*values)[i].v_handle);
+      }
+    }
+    logger_.LogString("]");
+  }
+}
+
+void MinRPCReturnsWithLog::ResetCurrHandleName(RPCCode code) {
+  code_ = code;
+  logger_.LogString(RPCCodeToString(code));
+  logger_.LogString(", ");
+  curr_handle_name_.clear();
+}
+
+void MinRPCReturnsWithLog::UpdateCurrHandleName(const char* name) {
+  if (curr_handle_name_.length() != 0) {
+    curr_handle_name_.append("::");
+  }
+  curr_handle_name_.append(name);
+}
+
+void MinRPCReturnsWithLog::GetHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    curr_handle_name_.append(array_tracker_[handle]);
+    logger_.LogHandleName(curr_handle_name_);
+  }
+}
+
+void MinRPCReturnsWithLog::ReleaseHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    logger_.LogHandleName(array_tracker_[handle]);

Review Comment:
   wondering if we need to Log at the same time we register?



##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      LogString("\"");
+      LogString(value.v_str);
+      LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        LogString(", [Values]:");
+        LogString(" { ");
+        if (len > 0) {
+          LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  LogString("; ");
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (code_ == RPCCode::kGetGlobalFunc) {
+    RegisterHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  ProcessValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnLastTVMError() {
+  const char* err = TVMGetLastError();
+  ReturnException(err);
+}
+
+void MinRPCReturnsWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  next_->ThrowError(code, info);
+  logger_.LogString("-> ERROR");

Review Comment:
   worth logging the code?



##########
src/runtime/minrpc/minrpc_interfaces.h:
##########
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief Return interface used in ExecInterface to generate and sent the responses.
+ */
+class ReturnInterface {
+ public:
+  virtual ~ReturnInterface() {}
+  virtual void ReturnVoid() = 0;
+  virtual void ReturnHandle(void* handle) = 0;
+  virtual void ReturnException(const char* msg) = 0;
+  virtual void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args) = 0;
+  virtual void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) = 0;
+  virtual void ReturnLastTVMError() = 0;
+  virtual void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone) = 0;
+};
+
+/*!
+ * \brief Execute interface used in MinRPCServer to process different received commands
+ */
+class ExecInterface {
+ public:
+  virtual ~ExecInterface() {}
+  virtual void ExecInitServer(int* num_args) = 0;

Review Comment:
   since this is ExecInterface and calling this function implies execution, I'd suggest we could shorten the names by removing "Exec" prefix here



##########
src/runtime/minrpc/minrpc_interfaces.h:
##########
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_INTERFACES_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief Return interface used in ExecInterface to generate and sent the responses.
+ */
+class ReturnInterface {

Review Comment:
   it's a little odd that this is called ReturnInterface but all the impl are called MinRPCFoo. Suggest naming this MinRPCReturnInterface to keep with the pattern, or moving this all inside `namespace minrpc` and dropping MinRPC prefix everywhere.



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void ProcessValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void ResetCurrHandleName(RPCCode code);
+
+  void UpdateCurrHandleName(const char* name);
+
+  void GetHandleName(void* handle);
+
+  void ReleaseHandleName(void* handle);
+
+  Logger* GetLogger() { return &logger_; }
+
+ private:
+  void RegisterHandleName(void* handle);
+
+  ReturnInterface* next_;
+  std::string curr_handle_name_;
+  std::unordered_map<void*, std::string> array_tracker_;
+  RPCCode code_;
+  Logger logger_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCExecute object, that also logs the responses.
+ *
+ * \tparam RExecInterface* underlying MinRPCExecute that processes the packets.
+ */
+class MinRPCExecuteWithLog : public ExecInterface {
+ public:
+  explicit MinRPCExecuteWithLog(ExecInterface* next) : next_(next) {
+    ret_handler_ = reinterpret_cast<MinRPCReturnsWithLog*>(next_->GetReturnInterface());

Review Comment:
   since this is the logging version of the ExecInterface, it's reasonable that the constructor should explicitly take a `Logger*`. i think you could add that argument here and that would remove the need to reinterpret_cast here.



##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      LogString("\"");
+      LogString(value.v_str);
+      LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        LogString(", [Values]:");
+        LogString(" { ");
+        if (len > 0) {
+          LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  LogString("; ");
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (code_ == RPCCode::kGetGlobalFunc) {
+    RegisterHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  ProcessValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnLastTVMError() {
+  const char* err = TVMGetLastError();
+  ReturnException(err);
+}
+
+void MinRPCReturnsWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  next_->ThrowError(code, info);
+  logger_.LogString("-> ERROR");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ProcessValues(const TVMValue** values, const int** tcodes,
+                                         int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_.LogString("-> [");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_.LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMOpaqueHandle) {
+        RegisterHandleName((*values)[i].v_handle);
+      }
+    }
+    logger_.LogString("]");
+  }
+}
+
+void MinRPCReturnsWithLog::ResetCurrHandleName(RPCCode code) {
+  code_ = code;
+  logger_.LogString(RPCCodeToString(code));
+  logger_.LogString(", ");
+  curr_handle_name_.clear();
+}
+
+void MinRPCReturnsWithLog::UpdateCurrHandleName(const char* name) {
+  if (curr_handle_name_.length() != 0) {
+    curr_handle_name_.append("::");
+  }
+  curr_handle_name_.append(name);
+}
+
+void MinRPCReturnsWithLog::GetHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    curr_handle_name_.append(array_tracker_[handle]);
+    logger_.LogHandleName(curr_handle_name_);
+  }
+}
+
+void MinRPCReturnsWithLog::ReleaseHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    logger_.LogHandleName(array_tracker_[handle]);
+    array_tracker_.erase(handle);
+  }
+}
+
+void MinRPCReturnsWithLog::RegisterHandleName(void* handle) {
+  array_tracker_[handle] = curr_handle_name_;
+}
+
+void MinRPCExecuteWithLog::ExecInitServer(int* num_args) {
+  SetRPCCode(RPCCode::kInitServer);
+  logger_->LogString("Init Server");
+  next_->ExecInitServer(num_args);
+}
+
+void MinRPCExecuteWithLog::ExecNormalCallFunc(uint64_t* call_handle, TVMValue** values,
+                                              int** tcodes, int* num_args) {
+  SetRPCCode(RPCCode::kCallFunc);
+  logger_->LogVal<void*>("call_handle: ", reinterpret_cast<void*>(*call_handle));
+  ret_handler_->GetHandleName(reinterpret_cast<void*>(*call_handle));
+  if (*num_args > 0) {
+    logger_->LogString(", ");
+  }
+  ProcessValues(values, tcodes, num_args);
+  next_->ExecNormalCallFunc(call_handle, values, tcodes, num_args);
+}
+
+void MinRPCExecuteWithLog::ExecCopyFromRemote(DLTensor** arr, uint64_t* num_bytes,
+                                              uint8_t** temp_data) {
+  SetRPCCode(RPCCode::kCopyFromRemote);
+  logger_->LogVal<void*>("data_handle: ", reinterpret_cast<void*>((*arr)->data));
+  logger_->LogDLDevice(", DLDevice(type,id):", &(*arr)->device);
+  logger_->LogVal<int64_t>(", ndim: ", (*arr)->ndim);
+  logger_->LogDLData(", DLDataType(code,bits,lane): ", &(*arr)->dtype);
+  logger_->LogVal<uint64_t>(", num_bytes:", *num_bytes);
+  next_->ExecCopyFromRemote(arr, num_bytes, temp_data);
+}
+
+int MinRPCExecuteWithLog::ExecCopyToRemote(DLTensor** arr, uint64_t* num_bytes,
+                                           uint8_t** data_ptr) {
+  SetRPCCode(RPCCode::kCopyToRemote);
+  logger_->LogVal<void*>("data_handle: ", reinterpret_cast<void*>((*arr)->data));
+  logger_->LogDLDevice(", DLDevice(type,id):", &(*arr)->device);
+  logger_->LogVal<int64_t>(", ndim: ", (*arr)->ndim);
+  logger_->LogDLData(", DLDataType(code,bits,lane): ", &(*arr)->dtype);
+  logger_->LogVal<uint64_t>(", byte_offset: ", (*arr)->byte_offset);
+  return next_->ExecCopyToRemote(arr, num_bytes, data_ptr);
+}
+
+void MinRPCExecuteWithLog::ExecSyscallFunc(RPCCode* code, TVMValue** values, int** tcodes,
+                                           int* num_args) {
+  SetRPCCode(*code);
+  if ((*code) == RPCCode::kFreeHandle) {
+    if (((*num_args) == 2) && ((*tcodes)[0] == kTVMOpaqueHandle) && ((*tcodes)[1] == kDLInt)) {
+      logger_->LogVal<void*>("handle: ", reinterpret_cast<void*>((*values)[0].v_handle));
+      if ((*values)[1].v_int64 == kTVMModuleHandle ||
+          (*values)[1].v_int64 == kTVMPackedFuncHandle) {
+        ret_handler_->ReleaseHandleName(reinterpret_cast<void*>((*values)[0].v_handle));
+      }
+    }
+  } else {
+    ProcessValues(values, tcodes, num_args);
+  }
+  next_->ExecSyscallFunc(code, values, tcodes, num_args);
+}
+
+void MinRPCExecuteWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  logger_->LogString("-> Error\n");
+  next_->ThrowError(code, info);
+}
+
+void MinRPCExecuteWithLog::ProcessValues(TVMValue** values, int** tcodes, int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_->LogString("[");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_->LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMStr) {
+        if (strlen((*values)[i].v_str) > 0) {
+          ret_handler_->UpdateCurrHandleName((*values)[i].v_str);

Review Comment:
   i think this is specific to `ModuleGetFunction` and `GetGlobalFunc` and `CallFunc`, right?



##########
src/runtime/minrpc/minrpc_server_logging.h:
##########
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+
+#include "minrpc_logger.h"
+#include "minrpc_server.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief A minimum RPC server that logs the received commands.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCServerWithLog {
+ public:
+  explicit MinRPCServerWithLog(TIOHandler* io)
+      : ret_handler_(io),
+        ret_handler_WLog_(&ret_handler_),
+        exec_handler_(io, &ret_handler_WLog_),
+        exec_handler_WLog_(&exec_handler_),
+        next_(io, &exec_handler_WLog_) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+ private:
+  MinRPCReturns<TIOHandler> ret_handler_;
+  MinRPCExecute<TIOHandler> exec_handler_;
+  MinRPCReturnsWithLog ret_handler_WLog_;
+  MinRPCExecuteWithLog exec_handler_WLog_;
+  MinRPCServer<TIOHandler> next_;
+};
+
+/*!
+ * \brief A minimum RPC server that only logs the outgoing commands and received responses.
+ * (Does not process the packets or respond to them.)
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCSniffer {
+ public:
+  explicit MinRPCSniffer(TIOHandler* io)
+      : io_(io),
+        ret_handler_(io_),
+        ret_handler_WLog_(&ret_handler_),
+        exec_handler_(&ret_handler_WLog_),
+        exec_handler_WLog_(&exec_handler_),
+        next_(io_, &exec_handler_WLog_) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+  void ProcessOneResponse() {
+    RPCCode code;
+    uint64_t packet_len = 0;
+
+    Read(&packet_len);
+    if (packet_len == 0) OutputLog();
+    Read(&code);
+    switch (code) {
+      case RPCCode::kReturn: {
+        HandleReturn();
+        break;
+      }
+      case RPCCode::kException: {
+        ret_handler_WLog_.ReturnException("");
+        break;
+      }
+      default: {
+        OutputLog();
+        break;
+      }
+    }
+  }
+
+ private:
+  void HandleReturn() {
+    int32_t num_args;
+    int32_t tcode;
+
+    Read(&num_args);
+    if (num_args == 1) {
+      Read(&tcode);
+      if (tcode == kTVMNullptr) {
+        ret_handler_WLog_.ReturnVoid();
+        return;
+      }
+      if (tcode == kTVMOpaqueHandle) {
+        uint64_t handle;
+        Read(&handle);
+        ret_handler_WLog_.ReturnHandle(reinterpret_cast<void*>(handle));
+        return;
+      }
+    }
+    OutputLog();
+  }
+
+  void OutputLog() { ret_handler_WLog_.GetLogger()->OutputLog(); }
+
+  template <typename T>
+  void Read(T* data) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    ReadRawBytes(data, sizeof(T));
+  }
+
+  void ReadRawBytes(void* data, size_t size) {
+    uint8_t* buf = reinterpret_cast<uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixRead(buf, size - ndone);
+      if (ret <= 0) {
+        ret_handler_WLog_.GetLogger()->LogString("-> No Response Received.");
+        break;
+      }
+      ndone += ret;
+      buf += ret;
+    }
+  }
+
+  TIOHandler* io_;
+  MinRPCReturnsNoOp<TIOHandler> ret_handler_;
+  MinRPCReturnsWithLog ret_handler_WLog_;

Review Comment:
   nit: could you name this all lowercase per https://google.github.io/styleguide/cppguide.html#Variable_Names
   
   here and below



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console

Review Comment:
   could you add docstrings to all of the functions here?



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void ProcessValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void ResetCurrHandleName(RPCCode code);
+
+  void UpdateCurrHandleName(const char* name);
+
+  void GetHandleName(void* handle);
+
+  void ReleaseHandleName(void* handle);
+
+  Logger* GetLogger() { return &logger_; }
+
+ private:
+  void RegisterHandleName(void* handle);
+
+  ReturnInterface* next_;
+  std::string curr_handle_name_;
+  std::unordered_map<void*, std::string> array_tracker_;
+  RPCCode code_;
+  Logger logger_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCExecute object, that also logs the responses.
+ *
+ * \tparam RExecInterface* underlying MinRPCExecute that processes the packets.

Review Comment:
   i don't see this type param, can you remove?



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void ProcessValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void ResetCurrHandleName(RPCCode code);
+
+  void UpdateCurrHandleName(const char* name);
+
+  void GetHandleName(void* handle);
+
+  void ReleaseHandleName(void* handle);
+
+  Logger* GetLogger() { return &logger_; }
+
+ private:
+  void RegisterHandleName(void* handle);
+
+  ReturnInterface* next_;
+  std::string curr_handle_name_;
+  std::unordered_map<void*, std::string> array_tracker_;
+  RPCCode code_;
+  Logger logger_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCExecute object, that also logs the responses.
+ *
+ * \tparam RExecInterface* underlying MinRPCExecute that processes the packets.
+ */
+class MinRPCExecuteWithLog : public ExecInterface {
+ public:
+  explicit MinRPCExecuteWithLog(ExecInterface* next) : next_(next) {
+    ret_handler_ = reinterpret_cast<MinRPCReturnsWithLog*>(next_->GetReturnInterface());
+    logger_ = ret_handler_->GetLogger();
+  }
+
+  ~MinRPCExecuteWithLog() {}
+
+  void ExecInitServer(int* num_args);
+
+  void ExecNormalCallFunc(uint64_t* call_handle, TVMValue** values, int** tcodes, int* num_args);

Review Comment:
   i think all of these args are pass-by-pointer when they don't need to be, right? 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] kparzysz-quic commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
kparzysz-quic commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r852412804


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -524,94 +523,249 @@ class MinRPCServer {
     int call_ecode = TVMSetStream(dev.device_type, dev.device_id, handle);
 
     if (call_ecode == 0) {
-      this->ReturnVoid();
+      ret_handler_->ReturnVoid();
     } else {
-      this->ReturnLastTVMError();
+      ret_handler_->ReturnLastTVMError();
     }
   }
 
   void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone) {
-    io_->Exit(static_cast<int>(code));
+    ret_handler_->ThrowError(code, info);
   }
 
+  ReturnInterface* GetReturnInterface() { return ret_handler_; }
+
+ private:
   template <typename T>
-  T* ArenaAlloc(int count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return arena_.template allocate_<T>(count);
+  int ReadArray(T* data, size_t count) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    return ReadRawBytes(data, sizeof(T) * count);
   }
 
-  template <typename T>
-  void Read(T* data) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    this->ReadRawBytes(data, sizeof(T));
+  int ReadRawBytes(void* data, size_t size) {
+    uint8_t* buf = reinterpret_cast<uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixRead(buf, size - ndone);
+      if (ret <= 0) return ret;
+      ndone += ret;
+      buf += ret;
+    }
+    return 1;
   }
 
-  template <typename T>
-  void ReadArray(T* data, size_t count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return this->ReadRawBytes(data, sizeof(T) * count);
+  TIOHandler* io_;
+  ReturnInterface* ret_handler_;
+};
+
+/*!
+ * \brief A minimum RPC server that only depends on the tvm C runtime..
+ *
+ *  All the dependencies are provided by the io arguments.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ *         An IOHandler needs to provide the following functions:
+ *         - PosixWrite, PosixRead, Close: posix style, read, write, close API.
+ *         - MessageStart(num_bytes), MessageDone(): framing APIs.
+ *         - Exit: exit with status code.
+ */
+template <typename TIOHandler, template <typename> class Allocator = detail::PageAllocator>
+class MinRPCServer {
+ public:
+  using PageAllocator = Allocator<TIOHandler>;
+
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  MinRPCServer(TIOHandler* io, ExecInterface* exec_handler)
+      : io_(io), arena_(PageAllocator(io_)), exec_handler_(exec_handler) {}
+
+  explicit MinRPCServer(TIOHandler* io)
+      : io_(io),
+        arena_(PageAllocator(io)),
+        ret_handler_(new MinRPCReturns<TIOHandler>(io_)),
+        exec_handler_(new MinRPCExecute<TIOHandler>(io_, ret_handler_)) {}

Review Comment:
   These two members are allocated, but never deleted.  In the logging classes you pass addresses of members to the `MinRPCServer` constructor, so it doesn't have a way of knowing whether it should delete these objects or not.  This needs to be fixed or it will cause memory leaks.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] alanmacd commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
alanmacd commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r849989729


##########
src/runtime/minrpc/minrpc_server_logging.h:
##########
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+
+#include "minrpc_logger.h"
+#include "minrpc_server.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief A minimum RPC server that logs the received commands.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCServerWithLog {
+ public:
+  explicit MinRPCServerWithLog(TIOHandler* io)
+      : ret(io), retWLog(&ret), exec(io, &retWLog), execWLog(&exec), next_(io, &execWLog) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+ private:
+  MinRPCReturns<TIOHandler> ret;
+  MinRPCExecute<TIOHandler> exec;
+  MinRPCReturnsWithLog retWLog;
+  MinRPCExecuteWithLog execWLog;
+  MinRPCServer<TIOHandler> next_;
+};
+
+/*!
+ * \brief A minimum RPC server that only logs the outgoing commands and received responses.
+ * (Does not process the packets or respond to them.)
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCSniffer {
+ public:
+  explicit MinRPCSniffer(TIOHandler* io)
+      : io_(io), ret(io), retWLog(&ret), exec(&retWLog), execWLog(&exec), next_(io, &execWLog) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+  void ProcessOneResponse() {
+    RPCCode code;
+    uint64_t packet_len = 0;
+
+    this->Read(&packet_len);
+    if (packet_len == 0) OutputLog();
+    this->Read(&code);
+    switch (code) {
+      case RPCCode::kReturn: {
+        HandleReturn();
+        break;
+      }
+      case RPCCode::kException: {
+        retWLog.ReturnException("");
+        break;
+      }
+      default: {
+        OutputLog();
+        break;
+      }
+    }
+  }
+
+ private:
+  void HandleReturn() {
+    int32_t num_args;
+    int32_t tcode;
+
+    this->Read(&num_args);
+    if (num_args == 1) {
+      this->Read(&tcode);
+      if (tcode == kTVMNullptr) {
+        retWLog.ReturnVoid();
+        return;
+      }
+      if (tcode == kTVMOpaqueHandle) {
+        uint64_t handle;
+        this->Read(&handle);
+        retWLog.ReturnHandle(reinterpret_cast<void*>(handle));
+        return;
+      }
+    }
+    OutputLog();
+  }
+
+  void OutputLog() { retWLog.getLogger()->OutputLog(); }
+
+  template <typename T>
+  void Read(T* data) {
+    static_assert(std::is_pod<T>::value, "need to be trival");
+    ReadRawBytes(data, sizeof(T));
+  }
+
+  void ReadRawBytes(void* data, size_t size) {
+    uint8_t* buf = reinterpret_cast<uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixRead(buf, size - ndone);
+      if (ret <= 0) {
+        retWLog.getLogger()->LogString("-> No Response Received.");
+        break;
+      }
+      ndone += ret;
+      buf += ret;
+    }
+  }
+
+  TIOHandler* io_;

Review Comment:
   add trailing underscores



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r850737150


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogTVMValue(int tcode, TVMValue value) {

Review Comment:
   No, I didn't. I moved it to the .cc file.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] areusch commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
areusch commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r855392123


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -524,94 +523,249 @@ class MinRPCServer {
     int call_ecode = TVMSetStream(dev.device_type, dev.device_id, handle);
 
     if (call_ecode == 0) {
-      this->ReturnVoid();
+      ret_handler_->ReturnVoid();
     } else {
-      this->ReturnLastTVMError();
+      ret_handler_->ReturnLastTVMError();
     }
   }
 
   void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone) {
-    io_->Exit(static_cast<int>(code));
+    ret_handler_->ThrowError(code, info);
   }
 
+  ReturnInterface* GetReturnInterface() { return ret_handler_; }
+
+ private:
   template <typename T>
-  T* ArenaAlloc(int count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return arena_.template allocate_<T>(count);
+  int ReadArray(T* data, size_t count) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    return ReadRawBytes(data, sizeof(T) * count);
   }
 
-  template <typename T>
-  void Read(T* data) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    this->ReadRawBytes(data, sizeof(T));
+  int ReadRawBytes(void* data, size_t size) {
+    uint8_t* buf = reinterpret_cast<uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixRead(buf, size - ndone);
+      if (ret <= 0) return ret;
+      ndone += ret;
+      buf += ret;
+    }
+    return 1;
   }
 
-  template <typename T>
-  void ReadArray(T* data, size_t count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return this->ReadRawBytes(data, sizeof(T) * count);
+  TIOHandler* io_;
+  ReturnInterface* ret_handler_;
+};
+
+/*!
+ * \brief A minimum RPC server that only depends on the tvm C runtime..
+ *
+ *  All the dependencies are provided by the io arguments.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ *         An IOHandler needs to provide the following functions:
+ *         - PosixWrite, PosixRead, Close: posix style, read, write, close API.
+ *         - MessageStart(num_bytes), MessageDone(): framing APIs.
+ *         - Exit: exit with status code.
+ */
+template <typename TIOHandler, template <typename> class Allocator = detail::PageAllocator>
+class MinRPCServer {
+ public:
+  using PageAllocator = Allocator<TIOHandler>;
+
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  MinRPCServer(TIOHandler* io, ExecInterface* exec_handler)
+      : io_(io), arena_(PageAllocator(io_)), exec_handler_(exec_handler) {}
+
+  explicit MinRPCServer(TIOHandler* io)
+      : io_(io),
+        arena_(PageAllocator(io)),
+        ret_handler_(new MinRPCReturns<TIOHandler>(io_)),
+        exec_handler_(new MinRPCExecute<TIOHandler>(io_, ret_handler_)) {}

Review Comment:
   ah i see. i think we could likely remove operator new in rpc_server.cc if it's defined in <memory>. it's been long enough that I don't remember why i needed to explicitly override that anyhow--i do think though that we should verify by testing on Zephyr/Arduino to make sure <memory> behaves the same way there.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861412601


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void ProcessValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void ResetCurrHandleName(RPCCode code);
+
+  void UpdateCurrHandleName(const char* name);
+
+  void GetHandleName(void* handle);
+
+  void ReleaseHandleName(void* handle);
+
+  Logger* GetLogger() { return &logger_; }
+
+ private:
+  void RegisterHandleName(void* handle);
+
+  ReturnInterface* next_;
+  std::string curr_handle_name_;
+  std::unordered_map<void*, std::string> array_tracker_;
+  RPCCode code_;
+  Logger logger_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCExecute object, that also logs the responses.
+ *
+ * \tparam RExecInterface* underlying MinRPCExecute that processes the packets.

Review Comment:
   fixed



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void ProcessValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void ResetCurrHandleName(RPCCode code);

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861411698


##########
python/tvm/rpc/client.py:
##########
@@ -514,7 +517,10 @@ def connect(url, port, key="", session_timeout=0, session_constructor_args=None)
         session_constructor_args = session_constructor_args if session_constructor_args else []
         if not isinstance(session_constructor_args, (list, tuple)):
             raise TypeError("Expect the session constructor to be a list or tuple")
-        sess = _ffi_api.Connect(url, port, key, *session_constructor_args)
+        enable_logging = False

Review Comment:
   done!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861411638


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -524,94 +523,249 @@ class MinRPCServer {
     int call_ecode = TVMSetStream(dev.device_type, dev.device_id, handle);
 
     if (call_ecode == 0) {
-      this->ReturnVoid();
+      ret_handler_->ReturnVoid();
     } else {
-      this->ReturnLastTVMError();
+      ret_handler_->ReturnLastTVMError();
     }
   }
 
   void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone) {
-    io_->Exit(static_cast<int>(code));
+    ret_handler_->ThrowError(code, info);
   }
 
+  ReturnInterface* GetReturnInterface() { return ret_handler_; }
+
+ private:
   template <typename T>
-  T* ArenaAlloc(int count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return arena_.template allocate_<T>(count);
+  int ReadArray(T* data, size_t count) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    return ReadRawBytes(data, sizeof(T) * count);
   }
 
-  template <typename T>
-  void Read(T* data) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    this->ReadRawBytes(data, sizeof(T));
+  int ReadRawBytes(void* data, size_t size) {
+    uint8_t* buf = reinterpret_cast<uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixRead(buf, size - ndone);
+      if (ret <= 0) return ret;
+      ndone += ret;
+      buf += ret;
+    }
+    return 1;
   }
 
-  template <typename T>
-  void ReadArray(T* data, size_t count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return this->ReadRawBytes(data, sizeof(T) * count);
+  TIOHandler* io_;
+  ReturnInterface* ret_handler_;
+};
+
+/*!
+ * \brief A minimum RPC server that only depends on the tvm C runtime..
+ *
+ *  All the dependencies are provided by the io arguments.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ *         An IOHandler needs to provide the following functions:
+ *         - PosixWrite, PosixRead, Close: posix style, read, write, close API.
+ *         - MessageStart(num_bytes), MessageDone(): framing APIs.
+ *         - Exit: exit with status code.
+ */
+template <typename TIOHandler, template <typename> class Allocator = detail::PageAllocator>
+class MinRPCServer {
+ public:
+  using PageAllocator = Allocator<TIOHandler>;
+
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  MinRPCServer(TIOHandler* io, ExecInterface* exec_handler)
+      : io_(io), arena_(PageAllocator(io_)), exec_handler_(exec_handler) {}
+
+  explicit MinRPCServer(TIOHandler* io)
+      : io_(io),
+        arena_(PageAllocator(io)),
+        ret_handler_(new MinRPCReturns<TIOHandler>(io_)),
+        exec_handler_(new MinRPCExecute<TIOHandler>(io_, ret_handler_)) {}

Review Comment:
   I changed the implementation to use smart pointer for exec_handler_, I hope that addresses the object ownership concern.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861411864


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] alanmacd commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
alanmacd commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r849981746


##########
src/runtime/rpc/rpc_channel_logger.h:
##########
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+/*!
+ * \file rpc_channel_logger.h
+ * \brief A wrapper for RPCChannel with a NanoRPCListener for logging the commands.
+ */
+#ifndef TVM_RUNTIME_RPC_RPC_CHANNEL_LOGGER_H_
+#define TVM_RUNTIME_RPC_RPC_CHANNEL_LOGGER_H_
+
+#include <memory>
+#include <utility>
+
+#include "../minrpc/minrpc_server_logging.h"
+#include "rpc_channel.h"
+
+#define RX_BUFFER_SIZE 65536
+
+namespace tvm {
+namespace runtime {
+
+class Buffer {
+ public:
+  Buffer(uint8_t* data, size_t data_size_bytes)
+      : data_{data}, capacity_{data_size_bytes}, num_valid_bytes_{0}, read_cursor_{0} {}
+
+  size_t Write(const uint8_t* data, size_t data_size_bytes) {
+    size_t num_bytes_available = capacity_ - num_valid_bytes_;
+    size_t num_bytes_to_copy = data_size_bytes;
+    if (num_bytes_available < num_bytes_to_copy) {
+      num_bytes_to_copy = num_bytes_available;
+    }
+
+    memcpy(&data_[num_valid_bytes_], data, num_bytes_to_copy);
+    num_valid_bytes_ += num_bytes_to_copy;
+    return num_bytes_to_copy;
+  }
+
+  size_t Read(uint8_t* data, size_t data_size_bytes) {
+    size_t num_bytes_to_copy = data_size_bytes;
+    size_t num_bytes_available = num_valid_bytes_ - read_cursor_;
+    if (num_bytes_available < num_bytes_to_copy) {
+      num_bytes_to_copy = num_bytes_available;
+    }
+
+    memcpy(data, &data_[read_cursor_], num_bytes_to_copy);
+    read_cursor_ += num_bytes_to_copy;
+    return num_bytes_to_copy;
+  }
+
+  void Clear() {
+    num_valid_bytes_ = 0;
+    read_cursor_ = 0;
+  }
+
+  size_t ReadAvailable() const { return num_valid_bytes_ - read_cursor_; }
+
+  size_t Size() const { return num_valid_bytes_; }
+
+ private:
+  /*! \brief pointer to data buffer. */
+  uint8_t* data_;
+
+  /*! \brief The total number of bytes available in data_. Always a power of 2. */
+  size_t capacity_;
+
+  /*! \brief index into data_ of the next potentially-available byte in the buffer.
+   * The byte is available when tail_ != data_ + capacity_.

Review Comment:
   update comment "tail_"



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r850737018


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogTVMValue(int tcode, TVMValue value) {
+    switch (tcode) {
+      case kDLInt:
+        this->LogVal<int64_t>("(int64)", value.v_int64);
+        break;
+      case kDLUInt:
+        this->LogVal<uint64_t>("(uint64)", value.v_int64);
+        break;
+      case kDLFloat: {
+        this->LogVal<float>("(float)", value.v_float64);
+        break;
+      }
+      case kTVMDataType: {
+        this->LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+        break;
+      }
+      case kDLDevice: {
+        this->LogDLDevice("DLDevice(type,id)", &value.v_device);
+        break;
+      }
+      case kTVMPackedFuncHandle: {
+        this->LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+        break;
+      }
+      case kTVMModuleHandle: {
+        this->LogVal<void*>("(ModuleHandle)", value.v_handle);
+        break;
+      }
+      case kTVMOpaqueHandle: {
+        this->LogVal<void*>("(OpaqueHandle)", value.v_handle);
+        break;
+      }
+      case kTVMDLTensorHandle: {
+        this->LogVal<void*>("(TensorHandle)", value.v_handle);
+        break;
+      }
+      case kTVMNDArrayHandle: {
+        this->LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+        break;
+      }
+      case kTVMNullptr:
+        this->LogString("Nullptr");
+        break;
+      case kTVMStr: {
+        this->LogString("\"");
+        this->LogString(value.v_str);
+        this->LogString("\"");
+        break;
+      }
+      case kTVMBytes: {
+        TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+        int len = bytes->size;
+        this->LogVal<int64_t>("(Bytes) [size]: ", len);
+        if (PRINT_BYTES) {
+          this->LogString(", [Values]:");
+          this->LogString(" { ");
+          if (len > 0) {
+            this->LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+          }
+          for (int j = 1; j < len; j++) this->LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+          this->LogString(" } ");
+        }
+        break;
+      }
+      default: {
+        this->LogString("ERROR-kUnknownTypeCode)");
+        break;
+      }
+    }
+    this->LogString("; ");
+  }
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  std::stringstream LogTime();
+
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next);
+  ~MinRPCReturnsWithLog();
+  void ReturnVoid();
+  void ReturnHandle(void* handle);
+  void ReturnException(const char* msg);
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+  void ReturnLastTVMError();
+  void ThrowError(RPCServerStatus code, RPCCode info);
+  void processValues(const TVMValue** values, const int** tcodes, int* num_args);
+  void resetCurrHandleName(RPCCode code);
+  void updateCurrHandleName(const char* name);
+  void getHandleName(void* handle);
+  void releaseHandleName(void* handle);
+  Logger* getLogger();
+
+ private:
+  void registerHandleName(void* handle);
+  ReturnInterface* next_;
+  std::string CurrHandleName;
+  std::unordered_map<void*, std::string> array_tracker;
+  RPCCode code;
+  Logger logger_;
+  Logger* logger = &logger_;

Review Comment:
   thanks, fixed it!



##########
src/runtime/minrpc/minrpc_server_logging.h:
##########
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+
+#include "minrpc_logger.h"
+#include "minrpc_server.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief A minimum RPC server that logs the received commands.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCServerWithLog {
+ public:
+  explicit MinRPCServerWithLog(TIOHandler* io)
+      : ret(io), retWLog(&ret), exec(io, &retWLog), execWLog(&exec), next_(io, &execWLog) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+ private:
+  MinRPCReturns<TIOHandler> ret;

Review Comment:
   thanks, fixed it.



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogTVMValue(int tcode, TVMValue value) {

Review Comment:
   I moved the entire code to the .h file and deleted the .cc file, I believe this is inline with the code base convention.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r852331956


##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,307 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      this->LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      this->LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      this->LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      this->LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      this->LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      this->LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      this->LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      this->LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      this->LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      this->LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      this->LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      this->LogString("\"");
+      this->LogString(value.v_str);
+      this->LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      this->LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        this->LogString(", [Values]:");
+        this->LogString(" { ");
+        if (len > 0) {
+          this->LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) this->LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        this->LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      this->LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  this->LogString("; ");
+}
+
+std::stringstream Logger::LogTime() {
+  char buf[100];
+  time_t t;
+  struct tm *timeptr, result, temp;
+  std::stringstream ss;
+
+  t = time(NULL);
+  timeptr = localtime_r(&t, &temp);
+  strftime(buf, sizeof(buf), "%a %m/%d/%Y %r", timeptr);
+
+  if (strptime(buf, "%a %m/%d/%Y %r", &result) == NULL) {

Review Comment:
   since I end up using LOG(INFO) to output the log, and LOG(INFO) adds a timestamp, I removed the LogTime function.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r862279401


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console

Review Comment:
   I added docstrings to the one not included in the interfaces.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mehrdadh commented on pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mehrdadh commented on PR #10967:
URL: https://github.com/apache/tvm/pull/10967#issuecomment-1118040939

   Thanks @mkatanbaf @areusch @kparzysz-quic @alanmacd! This PR is merged now.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r864276388


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -58,95 +63,133 @@ class PageAllocator;
 }
 
 /*!
- * \brief A minimum RPC server that only depends on the tvm C runtime..
- *
- *  All the dependencies are provided by the io arguments.
+ * \brief Responses to a minimum RPC command.
  *
  * \tparam TIOHandler IO provider to provide io handling.
- *         An IOHandler needs to provide the following functions:
- *         - PosixWrite, PosixRead, Close: posix style, read, write, close API.
- *         - MessageStart(num_bytes), MessageDone(): framing APIs.
- *         - Exit: exit with status code.
  */
-template <typename TIOHandler, template <typename> class Allocator = detail::PageAllocator>
-class MinRPCServer {
+template <typename TIOHandler>
+class MinRPCReturns : public MinRPCReturnInterface {
  public:
-  using PageAllocator = Allocator<TIOHandler>;
-
   /*!
    * \brief Constructor.
    * \param io The IO handler.
    */
-  explicit MinRPCServer(TIOHandler* io) : io_(io), arena_(PageAllocator(io)) {}
+  explicit MinRPCReturns(TIOHandler* io) : io_(io) {}
 
-  /*! \brief Process a single request.
-   *
-   * \return true when the server should continue processing requests. false when it should be
-   *  shutdown.
-   */
-  bool ProcessOnePacket() {
-    RPCCode code;
-    uint64_t packet_len;
+  void ReturnVoid() {
+    int32_t num_args = 1;
+    int32_t tcode = kTVMNullptr;
+    RPCCode code = RPCCode::kReturn;
 
-    arena_.RecycleAll();
-    allow_clean_shutdown_ = true;
+    uint64_t packet_nbytes = sizeof(code) + sizeof(num_args) + sizeof(tcode);
 
-    this->Read(&packet_len);
-    if (packet_len == 0) return true;
-    this->Read(&code);
+    io_->MessageStart(packet_nbytes);
+    Write(packet_nbytes);
+    Write(code);
+    Write(num_args);
+    Write(tcode);
+    io_->MessageDone();
+  }
 
-    allow_clean_shutdown_ = false;
+  void ReturnHandle(void* handle) {
+    int32_t num_args = 1;
+    int32_t tcode = kTVMOpaqueHandle;
+    RPCCode code = RPCCode::kReturn;
+    uint64_t encode_handle = reinterpret_cast<uint64_t>(handle);
+    uint64_t packet_nbytes =
+        sizeof(code) + sizeof(num_args) + sizeof(tcode) + sizeof(encode_handle);
 
-    if (code >= RPCCode::kSyscallCodeStart) {
-      this->HandleSyscallFunc(code);
-    } else {
-      switch (code) {
-        case RPCCode::kCallFunc: {
-          HandleNormalCallFunc();
-          break;
-        }
-        case RPCCode::kInitServer: {
-          HandleInitServer();
-          break;
-        }
-        case RPCCode::kCopyFromRemote: {
-          HandleCopyFromRemote();
-          break;
-        }
-        case RPCCode::kCopyToRemote: {
-          HandleCopyToRemote();
-          break;
-        }
-        case RPCCode::kShutdown: {
-          this->Shutdown();
-          return false;
-        }
-        default: {
-          this->ThrowError(RPCServerStatus::kUnknownRPCCode);
-          break;
-        }
+    io_->MessageStart(packet_nbytes);
+    Write(packet_nbytes);
+    Write(code);
+    Write(num_args);
+    Write(tcode);
+    Write(encode_handle);
+    io_->MessageDone();
+  }
+
+  void ReturnException(const char* msg) { RPCReference::ReturnException(msg, this); }
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args) {
+    RPCReference::ReturnPackedSeq(arg_values, type_codes, num_args, this);
+  }
+
+  void ReturnCopyFromRemote(uint8_t* data_ptr, uint64_t num_bytes) {
+    RPCCode code = RPCCode::kCopyAck;
+    uint64_t packet_nbytes = sizeof(code) + num_bytes;
+
+    io_->MessageStart(packet_nbytes);
+    Write(packet_nbytes);
+    Write(code);
+    WriteArray(data_ptr, num_bytes);
+    io_->MessageDone();
+  }
+
+  void ReturnLastTVMError() {
+    const char* err = TVMGetLastError();
+    ReturnException(err);
+  }
+
+  void MessageStart(uint64_t packet_nbytes) { io_->MessageStart(packet_nbytes); }
+
+  void MessageDone() { io_->MessageDone(); }
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone) {
+    io_->Exit(static_cast<int>(code));
+  }
+
+  template <typename T>
+  void Write(const T& data) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    return WriteRawBytes(&data, sizeof(T));
+  }
+
+  template <typename T>
+  void WriteArray(T* data, size_t count) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    return WriteRawBytes(data, sizeof(T) * count);
+  }
+
+ private:
+  void WriteRawBytes(const void* data, size_t size) {
+    const uint8_t* buf = static_cast<const uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixWrite(buf, size - ndone);
+      if (ret == 0 || ret == -1) {

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r864276737


##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861414747


##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      LogString("\"");
+      LogString(value.v_str);
+      LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        LogString(", [Values]:");
+        LogString(" { ");
+        if (len > 0) {
+          LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  LogString("; ");
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (code_ == RPCCode::kGetGlobalFunc) {
+    RegisterHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  ProcessValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnLastTVMError() {
+  const char* err = TVMGetLastError();
+  ReturnException(err);
+}
+
+void MinRPCReturnsWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  next_->ThrowError(code, info);
+  logger_.LogString("-> ERROR");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ProcessValues(const TVMValue** values, const int** tcodes,
+                                         int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_.LogString("-> [");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_.LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMOpaqueHandle) {
+        RegisterHandleName((*values)[i].v_handle);
+      }
+    }
+    logger_.LogString("]");
+  }
+}
+
+void MinRPCReturnsWithLog::ResetCurrHandleName(RPCCode code) {
+  code_ = code;
+  logger_.LogString(RPCCodeToString(code));
+  logger_.LogString(", ");
+  curr_handle_name_.clear();
+}
+
+void MinRPCReturnsWithLog::UpdateCurrHandleName(const char* name) {
+  if (curr_handle_name_.length() != 0) {
+    curr_handle_name_.append("::");
+  }
+  curr_handle_name_.append(name);
+}
+
+void MinRPCReturnsWithLog::GetHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    curr_handle_name_.append(array_tracker_[handle]);
+    logger_.LogHandleName(curr_handle_name_);
+  }
+}
+
+void MinRPCReturnsWithLog::ReleaseHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    logger_.LogHandleName(array_tracker_[handle]);
+    array_tracker_.erase(handle);
+  }
+}
+
+void MinRPCReturnsWithLog::RegisterHandleName(void* handle) {
+  array_tracker_[handle] = curr_handle_name_;
+}
+
+void MinRPCExecuteWithLog::ExecInitServer(int* num_args) {
+  SetRPCCode(RPCCode::kInitServer);
+  logger_->LogString("Init Server");
+  next_->ExecInitServer(num_args);
+}
+
+void MinRPCExecuteWithLog::ExecNormalCallFunc(uint64_t* call_handle, TVMValue** values,
+                                              int** tcodes, int* num_args) {
+  SetRPCCode(RPCCode::kCallFunc);
+  logger_->LogVal<void*>("call_handle: ", reinterpret_cast<void*>(*call_handle));
+  ret_handler_->GetHandleName(reinterpret_cast<void*>(*call_handle));
+  if (*num_args > 0) {
+    logger_->LogString(", ");
+  }
+  ProcessValues(values, tcodes, num_args);
+  next_->ExecNormalCallFunc(call_handle, values, tcodes, num_args);
+}
+
+void MinRPCExecuteWithLog::ExecCopyFromRemote(DLTensor** arr, uint64_t* num_bytes,
+                                              uint8_t** temp_data) {
+  SetRPCCode(RPCCode::kCopyFromRemote);
+  logger_->LogVal<void*>("data_handle: ", reinterpret_cast<void*>((*arr)->data));
+  logger_->LogDLDevice(", DLDevice(type,id):", &(*arr)->device);
+  logger_->LogVal<int64_t>(", ndim: ", (*arr)->ndim);
+  logger_->LogDLData(", DLDataType(code,bits,lane): ", &(*arr)->dtype);
+  logger_->LogVal<uint64_t>(", num_bytes:", *num_bytes);
+  next_->ExecCopyFromRemote(arr, num_bytes, temp_data);
+}
+
+int MinRPCExecuteWithLog::ExecCopyToRemote(DLTensor** arr, uint64_t* num_bytes,
+                                           uint8_t** data_ptr) {
+  SetRPCCode(RPCCode::kCopyToRemote);
+  logger_->LogVal<void*>("data_handle: ", reinterpret_cast<void*>((*arr)->data));
+  logger_->LogDLDevice(", DLDevice(type,id):", &(*arr)->device);
+  logger_->LogVal<int64_t>(", ndim: ", (*arr)->ndim);
+  logger_->LogDLData(", DLDataType(code,bits,lane): ", &(*arr)->dtype);
+  logger_->LogVal<uint64_t>(", byte_offset: ", (*arr)->byte_offset);
+  return next_->ExecCopyToRemote(arr, num_bytes, data_ptr);
+}
+
+void MinRPCExecuteWithLog::ExecSyscallFunc(RPCCode* code, TVMValue** values, int** tcodes,
+                                           int* num_args) {
+  SetRPCCode(*code);
+  if ((*code) == RPCCode::kFreeHandle) {
+    if (((*num_args) == 2) && ((*tcodes)[0] == kTVMOpaqueHandle) && ((*tcodes)[1] == kDLInt)) {
+      logger_->LogVal<void*>("handle: ", reinterpret_cast<void*>((*values)[0].v_handle));
+      if ((*values)[1].v_int64 == kTVMModuleHandle ||
+          (*values)[1].v_int64 == kTVMPackedFuncHandle) {
+        ret_handler_->ReleaseHandleName(reinterpret_cast<void*>((*values)[0].v_handle));
+      }
+    }
+  } else {
+    ProcessValues(values, tcodes, num_args);
+  }
+  next_->ExecSyscallFunc(code, values, tcodes, num_args);
+}
+
+void MinRPCExecuteWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  logger_->LogString("-> Error\n");
+  next_->ThrowError(code, info);
+}
+
+void MinRPCExecuteWithLog::ProcessValues(TVMValue** values, int** tcodes, int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_->LogString("[");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_->LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMStr) {
+        if (strlen((*values)[i].v_str) > 0) {
+          ret_handler_->UpdateCurrHandleName((*values)[i].v_str);

Review Comment:
   As we talked, I kept the code as is for the moment (i.e. it adds all the strings in parameters to the handle name). In future we can change it once we have a better vision of what should or should not be logged.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r862272024


##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      LogString("\"");
+      LogString(value.v_str);
+      LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        LogString(", [Values]:");
+        LogString(" { ");
+        if (len > 0) {
+          LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  LogString("; ");
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (code_ == RPCCode::kGetGlobalFunc) {
+    RegisterHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  ProcessValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] kparzysz-quic commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
kparzysz-quic commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r855638705


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -524,94 +523,249 @@ class MinRPCServer {
     int call_ecode = TVMSetStream(dev.device_type, dev.device_id, handle);
 
     if (call_ecode == 0) {
-      this->ReturnVoid();
+      ret_handler_->ReturnVoid();
     } else {
-      this->ReturnLastTVMError();
+      ret_handler_->ReturnLastTVMError();
     }
   }
 
   void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone) {
-    io_->Exit(static_cast<int>(code));
+    ret_handler_->ThrowError(code, info);
   }
 
+  ReturnInterface* GetReturnInterface() { return ret_handler_; }
+
+ private:
   template <typename T>
-  T* ArenaAlloc(int count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return arena_.template allocate_<T>(count);
+  int ReadArray(T* data, size_t count) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    return ReadRawBytes(data, sizeof(T) * count);
   }
 
-  template <typename T>
-  void Read(T* data) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    this->ReadRawBytes(data, sizeof(T));
+  int ReadRawBytes(void* data, size_t size) {
+    uint8_t* buf = reinterpret_cast<uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixRead(buf, size - ndone);
+      if (ret <= 0) return ret;
+      ndone += ret;
+      buf += ret;
+    }
+    return 1;
   }
 
-  template <typename T>
-  void ReadArray(T* data, size_t count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return this->ReadRawBytes(data, sizeof(T) * count);
+  TIOHandler* io_;
+  ReturnInterface* ret_handler_;
+};
+
+/*!
+ * \brief A minimum RPC server that only depends on the tvm C runtime..
+ *
+ *  All the dependencies are provided by the io arguments.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ *         An IOHandler needs to provide the following functions:
+ *         - PosixWrite, PosixRead, Close: posix style, read, write, close API.
+ *         - MessageStart(num_bytes), MessageDone(): framing APIs.
+ *         - Exit: exit with status code.
+ */
+template <typename TIOHandler, template <typename> class Allocator = detail::PageAllocator>
+class MinRPCServer {
+ public:
+  using PageAllocator = Allocator<TIOHandler>;
+
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  MinRPCServer(TIOHandler* io, ExecInterface* exec_handler)
+      : io_(io), arena_(PageAllocator(io_)), exec_handler_(exec_handler) {}
+
+  explicit MinRPCServer(TIOHandler* io)
+      : io_(io),
+        arena_(PageAllocator(io)),
+        ret_handler_(new MinRPCReturns<TIOHandler>(io_)),
+        exec_handler_(new MinRPCExecute<TIOHandler>(io_, ret_handler_)) {}

Review Comment:
   I think this needs a better solution---where the object ownership is fixed, i.e. either this class owns these objects or not.  This will need a few more changes to the code creating objects of this class.  I'm not sure what solution is the best for this, though.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r852332951


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  std::stringstream LogTime();
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void processValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void resetCurrHandleName(RPCCode code);
+
+  void updateCurrHandleName(const char* name);
+
+  void getHandleName(void* handle);
+
+  void releaseHandleName(void* handle);
+
+  Logger* getLogger() { return &logger_; }
+
+ private:
+  void registerHandleName(void* handle);
+
+  ReturnInterface* next_;
+  std::string CurrHandleName_;
+  std::unordered_map<void*, std::string> array_tracker_;
+  RPCCode code_;
+  Logger logger_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCExecute object, that also logs the responses.
+ *
+ * \tparam RExecInterface* underlying MinRPCExecute that processes the packets.
+ */
+class MinRPCExecuteWithLog : public ExecInterface {
+ public:
+  explicit MinRPCExecuteWithLog(ExecInterface* next) : next_(next) {
+    this->ret_handler_ = reinterpret_cast<MinRPCReturnsWithLog*>(next_->getReturnInterface());
+    this->logger_ = ret_handler_->getLogger();
+  }
+
+  ~MinRPCExecuteWithLog() {}
+
+  void ExecInitServer(int* _num_args);

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861412752


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}

Review Comment:
   fixed



##########
src/runtime/minrpc/minrpc_server_logging.h:
##########
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_SERVER_LOGGING_H_
+
+#include "minrpc_logger.h"
+#include "minrpc_server.h"
+
+namespace tvm {
+namespace runtime {
+
+/*!
+ * \brief A minimum RPC server that logs the received commands.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCServerWithLog {
+ public:
+  explicit MinRPCServerWithLog(TIOHandler* io)
+      : ret_handler_(io),
+        ret_handler_WLog_(&ret_handler_),
+        exec_handler_(io, &ret_handler_WLog_),
+        exec_handler_WLog_(&exec_handler_),
+        next_(io, &exec_handler_WLog_) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+ private:
+  MinRPCReturns<TIOHandler> ret_handler_;
+  MinRPCExecute<TIOHandler> exec_handler_;
+  MinRPCReturnsWithLog ret_handler_WLog_;
+  MinRPCExecuteWithLog exec_handler_WLog_;
+  MinRPCServer<TIOHandler> next_;
+};
+
+/*!
+ * \brief A minimum RPC server that only logs the outgoing commands and received responses.
+ * (Does not process the packets or respond to them.)
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ */
+template <typename TIOHandler>
+class MinRPCSniffer {
+ public:
+  explicit MinRPCSniffer(TIOHandler* io)
+      : io_(io),
+        ret_handler_(io_),
+        ret_handler_WLog_(&ret_handler_),
+        exec_handler_(&ret_handler_WLog_),
+        exec_handler_WLog_(&exec_handler_),
+        next_(io_, &exec_handler_WLog_) {}
+
+  bool ProcessOnePacket() { return next_.ProcessOnePacket(); }
+
+  void ProcessOneResponse() {
+    RPCCode code;
+    uint64_t packet_len = 0;
+
+    Read(&packet_len);
+    if (packet_len == 0) OutputLog();
+    Read(&code);
+    switch (code) {
+      case RPCCode::kReturn: {
+        HandleReturn();
+        break;
+      }
+      case RPCCode::kException: {
+        ret_handler_WLog_.ReturnException("");
+        break;
+      }
+      default: {
+        OutputLog();
+        break;
+      }
+    }
+  }
+
+ private:
+  void HandleReturn() {
+    int32_t num_args;
+    int32_t tcode;
+
+    Read(&num_args);
+    if (num_args == 1) {
+      Read(&tcode);
+      if (tcode == kTVMNullptr) {
+        ret_handler_WLog_.ReturnVoid();
+        return;
+      }
+      if (tcode == kTVMOpaqueHandle) {
+        uint64_t handle;
+        Read(&handle);
+        ret_handler_WLog_.ReturnHandle(reinterpret_cast<void*>(handle));
+        return;
+      }
+    }
+    OutputLog();
+  }
+
+  void OutputLog() { ret_handler_WLog_.GetLogger()->OutputLog(); }
+
+  template <typename T>
+  void Read(T* data) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    ReadRawBytes(data, sizeof(T));
+  }
+
+  void ReadRawBytes(void* data, size_t size) {
+    uint8_t* buf = reinterpret_cast<uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixRead(buf, size - ndone);
+      if (ret <= 0) {
+        ret_handler_WLog_.GetLogger()->LogString("-> No Response Received.");
+        break;
+      }
+      ndone += ret;
+      buf += ret;
+    }
+  }
+
+  TIOHandler* io_;
+  MinRPCReturnsNoOp<TIOHandler> ret_handler_;
+  MinRPCReturnsWithLog ret_handler_WLog_;

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861412941


##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      LogString("\"");
+      LogString(value.v_str);
+      LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        LogString(", [Values]:");
+        LogString(" { ");
+        if (len > 0) {
+          LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  LogString("; ");
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (code_ == RPCCode::kGetGlobalFunc) {
+    RegisterHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  ProcessValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnLastTVMError() {
+  const char* err = TVMGetLastError();
+  ReturnException(err);
+}
+
+void MinRPCReturnsWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  next_->ThrowError(code, info);
+  logger_.LogString("-> ERROR");

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r861412469


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_interfaces.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] areusch commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
areusch commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r863949872


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -58,95 +63,133 @@ class PageAllocator;
 }
 
 /*!
- * \brief A minimum RPC server that only depends on the tvm C runtime..
- *
- *  All the dependencies are provided by the io arguments.
+ * \brief Responses to a minimum RPC command.
  *
  * \tparam TIOHandler IO provider to provide io handling.
- *         An IOHandler needs to provide the following functions:
- *         - PosixWrite, PosixRead, Close: posix style, read, write, close API.
- *         - MessageStart(num_bytes), MessageDone(): framing APIs.
- *         - Exit: exit with status code.
  */
-template <typename TIOHandler, template <typename> class Allocator = detail::PageAllocator>
-class MinRPCServer {
+template <typename TIOHandler>
+class MinRPCReturns : public MinRPCReturnInterface {
  public:
-  using PageAllocator = Allocator<TIOHandler>;
-
   /*!
    * \brief Constructor.
    * \param io The IO handler.
    */
-  explicit MinRPCServer(TIOHandler* io) : io_(io), arena_(PageAllocator(io)) {}
+  explicit MinRPCReturns(TIOHandler* io) : io_(io) {}
 
-  /*! \brief Process a single request.
-   *
-   * \return true when the server should continue processing requests. false when it should be
-   *  shutdown.
-   */
-  bool ProcessOnePacket() {
-    RPCCode code;
-    uint64_t packet_len;
+  void ReturnVoid() {
+    int32_t num_args = 1;
+    int32_t tcode = kTVMNullptr;
+    RPCCode code = RPCCode::kReturn;
 
-    arena_.RecycleAll();
-    allow_clean_shutdown_ = true;
+    uint64_t packet_nbytes = sizeof(code) + sizeof(num_args) + sizeof(tcode);
 
-    this->Read(&packet_len);
-    if (packet_len == 0) return true;
-    this->Read(&code);
+    io_->MessageStart(packet_nbytes);
+    Write(packet_nbytes);
+    Write(code);
+    Write(num_args);
+    Write(tcode);
+    io_->MessageDone();
+  }
 
-    allow_clean_shutdown_ = false;
+  void ReturnHandle(void* handle) {
+    int32_t num_args = 1;
+    int32_t tcode = kTVMOpaqueHandle;
+    RPCCode code = RPCCode::kReturn;
+    uint64_t encode_handle = reinterpret_cast<uint64_t>(handle);
+    uint64_t packet_nbytes =
+        sizeof(code) + sizeof(num_args) + sizeof(tcode) + sizeof(encode_handle);
 
-    if (code >= RPCCode::kSyscallCodeStart) {
-      this->HandleSyscallFunc(code);
-    } else {
-      switch (code) {
-        case RPCCode::kCallFunc: {
-          HandleNormalCallFunc();
-          break;
-        }
-        case RPCCode::kInitServer: {
-          HandleInitServer();
-          break;
-        }
-        case RPCCode::kCopyFromRemote: {
-          HandleCopyFromRemote();
-          break;
-        }
-        case RPCCode::kCopyToRemote: {
-          HandleCopyToRemote();
-          break;
-        }
-        case RPCCode::kShutdown: {
-          this->Shutdown();
-          return false;
-        }
-        default: {
-          this->ThrowError(RPCServerStatus::kUnknownRPCCode);
-          break;
-        }
+    io_->MessageStart(packet_nbytes);
+    Write(packet_nbytes);
+    Write(code);
+    Write(num_args);
+    Write(tcode);
+    Write(encode_handle);
+    io_->MessageDone();
+  }
+
+  void ReturnException(const char* msg) { RPCReference::ReturnException(msg, this); }
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args) {
+    RPCReference::ReturnPackedSeq(arg_values, type_codes, num_args, this);
+  }
+
+  void ReturnCopyFromRemote(uint8_t* data_ptr, uint64_t num_bytes) {
+    RPCCode code = RPCCode::kCopyAck;
+    uint64_t packet_nbytes = sizeof(code) + num_bytes;
+
+    io_->MessageStart(packet_nbytes);
+    Write(packet_nbytes);
+    Write(code);
+    WriteArray(data_ptr, num_bytes);
+    io_->MessageDone();
+  }
+
+  void ReturnLastTVMError() {
+    const char* err = TVMGetLastError();
+    ReturnException(err);
+  }
+
+  void MessageStart(uint64_t packet_nbytes) { io_->MessageStart(packet_nbytes); }
+
+  void MessageDone() { io_->MessageDone(); }
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone) {
+    io_->Exit(static_cast<int>(code));
+  }
+
+  template <typename T>
+  void Write(const T& data) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    return WriteRawBytes(&data, sizeof(T));
+  }
+
+  template <typename T>
+  void WriteArray(T* data, size_t count) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    return WriteRawBytes(data, sizeof(T) * count);
+  }
+
+ private:
+  void WriteRawBytes(const void* data, size_t size) {
+    const uint8_t* buf = static_cast<const uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixWrite(buf, size - ndone);
+      if (ret == 0 || ret == -1) {

Review Comment:
   probably should check ret < 0 instead of ret == -1 here



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mehrdadh merged pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mehrdadh merged PR #10967:
URL: https://github.com/apache/tvm/pull/10967


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] alanmacd commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
alanmacd commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r849969366


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogTVMValue(int tcode, TVMValue value) {

Review Comment:
   Did you intend for the this to be inlined since it's implemented in the header file?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r852332312


##########
src/runtime/minrpc/minrpc_logger.cc:
##########
@@ -0,0 +1,307 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#include "minrpc_logger.h"
+
+#include <string.h>
+#include <time.h>
+#include <tvm/runtime/c_runtime_api.h>
+#include <tvm/runtime/logging.h>
+
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+void Logger::LogTVMValue(int tcode, TVMValue value) {
+  switch (tcode) {
+    case kDLInt:
+      this->LogVal<int64_t>("(int64)", value.v_int64);
+      break;
+    case kDLUInt:
+      this->LogVal<uint64_t>("(uint64)", value.v_int64);
+      break;
+    case kDLFloat: {
+      this->LogVal<float>("(float)", value.v_float64);
+      break;
+    }
+    case kTVMDataType: {
+      this->LogDLData("DLDataType(code,bits,lane)", &value.v_type);
+      break;
+    }
+    case kDLDevice: {
+      this->LogDLDevice("DLDevice(type,id)", &value.v_device);
+      break;
+    }
+    case kTVMPackedFuncHandle: {
+      this->LogVal<void*>("(PackedFuncHandle)", value.v_handle);
+      break;
+    }
+    case kTVMModuleHandle: {
+      this->LogVal<void*>("(ModuleHandle)", value.v_handle);
+      break;
+    }
+    case kTVMOpaqueHandle: {
+      this->LogVal<void*>("(OpaqueHandle)", value.v_handle);
+      break;
+    }
+    case kTVMDLTensorHandle: {
+      this->LogVal<void*>("(TensorHandle)", value.v_handle);
+      break;
+    }
+    case kTVMNDArrayHandle: {
+      this->LogVal<void*>("kTVMNDArrayHandle", value.v_handle);
+      break;
+    }
+    case kTVMNullptr:
+      this->LogString("Nullptr");
+      break;
+    case kTVMStr: {
+      this->LogString("\"");
+      this->LogString(value.v_str);
+      this->LogString("\"");
+      break;
+    }
+    case kTVMBytes: {
+      TVMByteArray* bytes = static_cast<TVMByteArray*>(value.v_handle);
+      int len = bytes->size;
+      this->LogVal<int64_t>("(Bytes) [size]: ", len);
+      if (PRINT_BYTES) {
+        this->LogString(", [Values]:");
+        this->LogString(" { ");
+        if (len > 0) {
+          this->LogVal<uint64_t>("", (uint8_t)bytes->data[0]);
+        }
+        for (int j = 1; j < len; j++) this->LogVal<uint64_t>(" - ", (uint8_t)bytes->data[j]);
+        this->LogString(" } ");
+      }
+      break;
+    }
+    default: {
+      this->LogString("ERROR-kUnknownTypeCode)");
+      break;
+    }
+  }
+  this->LogString("; ");
+}
+
+std::stringstream Logger::LogTime() {
+  char buf[100];
+  time_t t;
+  struct tm *timeptr, result, temp;
+  std::stringstream ss;
+
+  t = time(NULL);
+  timeptr = localtime_r(&t, &temp);
+  strftime(buf, sizeof(buf), "%a %m/%d/%Y %r", timeptr);
+
+  if (strptime(buf, "%a %m/%d/%Y %r", &result) == NULL) {
+    ss << "TIME UNKNOWN, ";
+  } else {
+    ss << result.tm_hour << ":" << result.tm_min << ":" << result.tm_sec << ", ";
+  }
+  return ss;
+}
+
+void Logger::OutputLog() {
+  LOG(INFO) << os_.str();
+  this->os_.str(std::string());
+}
+
+void MinRPCReturnsWithLog::ReturnVoid() {
+  next_->ReturnVoid();
+  logger_.LogString("-> ReturnVoid");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnHandle(void* handle) {
+  next_->ReturnHandle(handle);
+  if (this->code_ == RPCCode::kGetGlobalFunc) {
+    this->registerHandleName(handle);
+  }
+  logger_.LogVal<void*>("-> ReturnHandle: ", handle);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnException(const char* msg) {
+  next_->ReturnException(msg);
+  logger_.LogString("-> Exception: ");
+  logger_.LogString(msg);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes,
+                                           int num_args) {
+  next_->ReturnPackedSeq(arg_values, type_codes, num_args);
+  processValues(&arg_values, &type_codes, &num_args);
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr) {
+  next_->ReturnCopyAck(num_bytes, data_ptr);
+  logger_.LogVal<uint64_t>("-> CopyAck: ", *num_bytes);
+  logger_.LogVal<void*>(", ", reinterpret_cast<void*>(*data_ptr));
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::ReturnLastTVMError() {
+  const char* err = TVMGetLastError();
+  this->ReturnException(err);
+}
+
+void MinRPCReturnsWithLog::ThrowError(RPCServerStatus code, RPCCode info) {
+  next_->ThrowError(code, info);
+  logger_.LogString("-> ERROR");
+  logger_.OutputLog();
+}
+
+void MinRPCReturnsWithLog::processValues(const TVMValue** values, const int** tcodes,
+                                         int* num_args) {
+  if (*tcodes != nullptr) {
+    logger_.LogString("-> [");
+    for (int i = 0; i < *num_args; ++i) {
+      logger_.LogTVMValue((*tcodes)[i], (*values)[i]);
+
+      if ((*tcodes)[i] == kTVMOpaqueHandle) {
+        this->registerHandleName((*values)[i].v_handle);
+      }
+    }
+    logger_.LogString("]");
+  }
+}
+
+void MinRPCReturnsWithLog::resetCurrHandleName(RPCCode code) {
+  this->code_ = code;
+  logger_.LogString(RPCCodeToString(code));
+  logger_.LogString(", ");
+  this->CurrHandleName_.clear();
+}
+
+void MinRPCReturnsWithLog::updateCurrHandleName(const char* name) {
+  if (this->CurrHandleName_.length() != 0) {
+    this->CurrHandleName_.append("::");
+  }
+  this->CurrHandleName_.append(name);
+}
+
+void MinRPCReturnsWithLog::getHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    CurrHandleName_.append(array_tracker_[handle]);
+    logger_.LogHandleName(CurrHandleName_);
+  }
+}
+
+void MinRPCReturnsWithLog::releaseHandleName(void* handle) {
+  if (array_tracker_.find(handle) != array_tracker_.end()) {
+    logger_.LogHandleName(array_tracker_[handle]);
+    array_tracker_.erase(handle);
+  }
+}
+
+void MinRPCReturnsWithLog::registerHandleName(void* handle) {
+  const std::string newString = CurrHandleName_;
+  array_tracker_[handle] = newString;
+}
+
+void MinRPCExecuteWithLog::ExecInitServer(int* _num_args) {
+  setRPCCode(RPCCode::kInitServer);
+  logger_->LogString("Init Server");
+  next_->ExecInitServer(_num_args);
+}
+
+void MinRPCExecuteWithLog::ExecNormalCallFunc(uint64_t* call_handle, TVMValue** values,
+                                              int** tcodes, int* num_args) {
+  setRPCCode(RPCCode::kCallFunc);
+  logger_->LogVal<void*>("call_handle: ", reinterpret_cast<void*>(*call_handle));
+  ret_handler_->getHandleName(reinterpret_cast<void*>(*call_handle));
+  if (*num_args > 0) {
+    logger_->LogString(", ");
+  }
+  this->processValues(values, tcodes, num_args);
+  next_->ExecNormalCallFunc(call_handle, values, tcodes, num_args);
+}
+
+void MinRPCExecuteWithLog::ExecCopyFromRemote(DLTensor** arr, uint64_t* num_bytes,
+                                              uint8_t** temp_data) {
+  setRPCCode(RPCCode::kCopyFromRemote);
+  logger_->LogVal<void*>("data_handle: ", reinterpret_cast<void*>((*arr)->data));
+  logger_->LogDLDevice(", DLDevice(type,id):", &(*arr)->device);
+  logger_->LogVal<int64_t>(", ndim: ", (*arr)->ndim);
+  logger_->LogDLData(", DLDataType(code,bits,lane): ", &(*arr)->dtype);
+  logger_->LogVal<uint64_t>(", num_bytes:", *num_bytes);
+  next_->ExecCopyFromRemote(arr, num_bytes, temp_data);
+}
+
+int MinRPCExecuteWithLog::ExecCopyToRemote(DLTensor** arr, uint64_t* _num_bytes,
+                                           uint8_t** _data_ptr) {

Review Comment:
   Thanks for pointing out to this, fixed



##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  std::stringstream LogTime();
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void processValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void resetCurrHandleName(RPCCode code);
+
+  void updateCurrHandleName(const char* name);
+
+  void getHandleName(void* handle);
+
+  void releaseHandleName(void* handle);
+
+  Logger* getLogger() { return &logger_; }

Review Comment:
   fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r852332759


##########
src/runtime/minrpc/minrpc_logger.h:
##########
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
+
+#include <tvm/runtime/c_runtime_api.h>
+
+#include <functional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include "minrpc_intrfc.h"
+#include "rpc_reference.h"
+
+namespace tvm {
+namespace runtime {
+
+#define PRINT_BYTES false
+
+/*!
+ * \brief Generates a user readeable log on the console
+ */
+class Logger {
+ public:
+  Logger() {}
+
+  void LogString(const char* s) { os_ << s; }
+
+  void LogStr(std::string s) { os_ << s; }
+
+  template <typename T>
+  void LogVal(const char* s, T val) {
+    os_ << s << val;
+  }
+
+  void LogDLDevice(const char* s, DLDevice* dev) {
+    os_ << s << "(" << dev->device_type << "," << dev->device_id << ")";
+  }
+
+  void LogDLData(const char* s, DLDataType* data) {
+    os_ << s << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
+        << ")";
+  }
+
+  void LogHandleName(std::string name) {
+    if (name.length() > 0) {
+      os_ << " <" << name.c_str() << ">";
+    }
+  }
+
+  std::stringstream LogTime();
+  void LogTVMValue(int tcode, TVMValue value);
+  void OutputLog();
+
+ private:
+  std::stringstream os_;
+};
+
+/*!
+ * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
+ *
+ * \tparam ReturnInterface* underlying MinRPCReturns that generates the responses.
+ */
+class MinRPCReturnsWithLog : public ReturnInterface {
+ public:
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  explicit MinRPCReturnsWithLog(ReturnInterface* next) : next_(next), logger_() {}
+
+  ~MinRPCReturnsWithLog() {}
+
+  void ReturnVoid();
+
+  void ReturnHandle(void* handle);
+
+  void ReturnException(const char* msg);
+
+  void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
+
+  void ReturnCopyAck(uint64_t* num_bytes, uint8_t** data_ptr);
+
+  void ReturnLastTVMError();
+
+  void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
+
+  void processValues(const TVMValue** values, const int** tcodes, int* num_args);
+
+  void resetCurrHandleName(RPCCode code);
+
+  void updateCurrHandleName(const char* name);
+
+  void getHandleName(void* handle);
+
+  void releaseHandleName(void* handle);
+
+  Logger* getLogger() { return &logger_; }
+
+ private:
+  void registerHandleName(void* handle);
+
+  ReturnInterface* next_;
+  std::string CurrHandleName_;

Review Comment:
   Thanks, fixed!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [tvm] mkatanbaf commented on a diff in pull request #10967: [rpc] Implemented rpc logging

Posted by GitBox <gi...@apache.org>.
mkatanbaf commented on code in PR #10967:
URL: https://github.com/apache/tvm/pull/10967#discussion_r854274054


##########
src/runtime/minrpc/minrpc_server.h:
##########
@@ -524,94 +523,249 @@ class MinRPCServer {
     int call_ecode = TVMSetStream(dev.device_type, dev.device_id, handle);
 
     if (call_ecode == 0) {
-      this->ReturnVoid();
+      ret_handler_->ReturnVoid();
     } else {
-      this->ReturnLastTVMError();
+      ret_handler_->ReturnLastTVMError();
     }
   }
 
   void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone) {
-    io_->Exit(static_cast<int>(code));
+    ret_handler_->ThrowError(code, info);
   }
 
+  ReturnInterface* GetReturnInterface() { return ret_handler_; }
+
+ private:
   template <typename T>
-  T* ArenaAlloc(int count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return arena_.template allocate_<T>(count);
+  int ReadArray(T* data, size_t count) {
+    static_assert(std::is_trivial<T>::value && std::is_standard_layout<T>::value,
+                  "need to be trival");
+    return ReadRawBytes(data, sizeof(T) * count);
   }
 
-  template <typename T>
-  void Read(T* data) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    this->ReadRawBytes(data, sizeof(T));
+  int ReadRawBytes(void* data, size_t size) {
+    uint8_t* buf = reinterpret_cast<uint8_t*>(data);
+    size_t ndone = 0;
+    while (ndone < size) {
+      ssize_t ret = io_->PosixRead(buf, size - ndone);
+      if (ret <= 0) return ret;
+      ndone += ret;
+      buf += ret;
+    }
+    return 1;
   }
 
-  template <typename T>
-  void ReadArray(T* data, size_t count) {
-    static_assert(std::is_pod<T>::value, "need to be trival");
-    return this->ReadRawBytes(data, sizeof(T) * count);
+  TIOHandler* io_;
+  ReturnInterface* ret_handler_;
+};
+
+/*!
+ * \brief A minimum RPC server that only depends on the tvm C runtime..
+ *
+ *  All the dependencies are provided by the io arguments.
+ *
+ * \tparam TIOHandler IO provider to provide io handling.
+ *         An IOHandler needs to provide the following functions:
+ *         - PosixWrite, PosixRead, Close: posix style, read, write, close API.
+ *         - MessageStart(num_bytes), MessageDone(): framing APIs.
+ *         - Exit: exit with status code.
+ */
+template <typename TIOHandler, template <typename> class Allocator = detail::PageAllocator>
+class MinRPCServer {
+ public:
+  using PageAllocator = Allocator<TIOHandler>;
+
+  /*!
+   * \brief Constructor.
+   * \param io The IO handler.
+   */
+  MinRPCServer(TIOHandler* io, ExecInterface* exec_handler)
+      : io_(io), arena_(PageAllocator(io_)), exec_handler_(exec_handler) {}
+
+  explicit MinRPCServer(TIOHandler* io)
+      : io_(io),
+        arena_(PageAllocator(io)),
+        ret_handler_(new MinRPCReturns<TIOHandler>(io_)),
+        exec_handler_(new MinRPCExecute<TIOHandler>(io_, ret_handler_)) {}

Review Comment:
   Thank you very much for taking the time to read through the code, and for valuable comments.
   Initially, I wanted to address this using unique_ptrs, but including "memory" resulted in "redefinition of operator new" error in rpc_server.cc. So, I simply use the "ret_handler_" variable as a flag to infer which constructor is used, and delete the allocated variables when needed.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org