Liya Fan created ARROW-6723:
-------------------------------

             Summary: [Java] Reduce the range of synchronized block when 
releasing an ArrowBuf
                 Key: ARROW-6723
                 URL: https://issues.apache.org/jira/browse/ARROW-6723
             Project: Apache Arrow
          Issue Type: Improvement
          Components: Java
            Reporter: Liya Fan
            Assignee: Liya Fan


When releasing an ArrowBuf, we will run the following piece of code:

  private int decrement(int decrement) {
    allocator.assertOpen();
    final int outcome;
    synchronized (allocationManager) {
      outcome = bufRefCnt.addAndGet(-decrement);
      if (outcome == 0) {
        lDestructionTime = System.nanoTime();
        allocationManager.release(this);
      }
    }
    return outcome;
  }

It can be seen that we need to acquire the lock for allocation manager lock, no 
matter if we need to release the buffer. In addition, the operation of 
decrementing refcount is only carried out after the lock is acquired. This 
leads to unnecessary resource contention, and may degrade performance. 

We propose to change the code like this:

  private int decrement(int decrement) {
    allocator.assertOpen();
    final int outcome;
    outcome = bufRefCnt.addAndGet(-decrement);
    if (outcome == 0) {
      lDestructionTime = System.nanoTime();
      synchronized (allocationManager) {
        allocationManager.release(this);
      }
    }
    return outcome;
  }

Note that this change can be dangerous, as it lies in the core of our code 
base, so we should be careful with it. On the other hand, it may have 
non-trivial performance implication. As far as I know, when a distributed task 
is getting closed, a large number of ArrowBuf will be closed simultaneously. If 
we reduce the range of the synchronization block, we can significantly improve 
the performance. 

What do you think?



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to