message: [BatchScheduler] Avoid mutex contention when deciding if a batch is empty. This is an optimization on read-path only.
diff: @@ -128,6 +128,8 @@ class Batch {
  // The sum of the sizes of the tasks in 'tasks_'.
  size_t size_ TF_GUARDED_BY(mu_) = 0;
  + std::atomic<bool> empty_ TF_GUARDED_BY(mu_){true};
  +
  // Whether the batch has been closed.
  Notification closed_;
  @@ -215,6 +217,7 @@ void Batch<TaskType>::AddTask(std::unique_ptr<TaskType> task) {
  mutex_lock l(mu_);
  size_ += task->size();
  tasks_.push_back(std::move(task));
  + empty_.store(false);
  }
  }
  @@ -228,6 +231,9 @@ std::unique_ptr<TaskType> Batch<TaskType>::RemoveTask() {
  std::unique_ptr<TaskType> task = std::move(tasks_.back());
  size_ -= task->size();
  tasks_.pop_back();
  + if (tasks_.empty()) {
  + empty_.store(true);
  + }
  return task;
  }
  }
  @@ -241,16 +247,13 @@ int Batch<TaskType>::num_tasks() const {
  }
  template <typename TaskType>
  -bool Batch<TaskType>::empty() const {
  - {
  +bool Batch<TaskType>::empty() const TF_NO_THREAD_SAFETY_ANALYSIS {
  // tracer is added to zoom in about this method.
  // TODO(b/160249203): Remove tracer after evaluating a change to reduce
  // lock contention and cpu usage (which is observed in profiler and
  // very data-driven).
  tensorflow::profiler::TraceMe tracer("BatchTask::empty");
  - mutex_lock l(mu_);
  - return tasks_.empty();
  - }
  + return empty_.load();
  }
  template <typename TaskType>
  