From f7bae45c694afe597c1e2aa259862c705ebd77e7 Mon Sep 17 00:00:00 2001
From: Derek Murray <mrry@google.com>
Date: Fri, 17 Apr 2020 09:09:29 -0700
Subject: [PATCH] [Graph] Avoid copying the NodeDef where possible in
 `Node::UpdateProperties()`.

1. We currently only call `UpdateProperties()` from `AddAttr()`, which ensures that we have unique ownership of the shared `NodeProperties`. This allows us to modify the `NodeProperties` in place.
2. We only need to update the `NodeProperties` when the input and output types change as a result of adding the new attr. Most calls to `AddAttr()` add inferred shape attributes, and do not modify the input or output types.

PiperOrigin-RevId: 307054556
Change-Id: I01fbc6ba832020bcd2d89822a5d3a2e3beba02ce
---
 tensorflow/core/graph/graph.cc | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/tensorflow/core/graph/graph.cc b/tensorflow/core/graph/graph.cc
index 98cf4a2491d..2cc297afb82 100644
--- a/tensorflow/core/graph/graph.cc
+++ b/tensorflow/core/graph/graph.cc
@@ -156,8 +156,17 @@ void Node::UpdateProperties() {
     LOG(ERROR) << "Failed at updating node: " << status;
     return;
   }
-  props_ = std::make_shared<NodeProperties>(props_->op_def, props_->node_def,
-                                            inputs, outputs);
+  if (props_->input_types != inputs || props_->output_types != outputs) {
+    if (TF_PREDICT_TRUE(props_.use_count() == 1)) {
+      props_->input_types = inputs;
+      props_->input_types_slice = props_->input_types;
+      props_->output_types = outputs;
+      props_->output_types_slice = props_->output_types;
+    } else {
+      props_ = std::make_shared<NodeProperties>(
+          props_->op_def, std::move(props_->node_def), inputs, outputs);
+    }
+  }
 }
 
 const string& Node::name() const { return props_->node_def.name(); }