13064: Check has_ref before checking in_use
authorPeter Amstutz <pamstutz@veritasgenetics.com>
Thu, 22 Feb 2018 19:09:33 +0000 (14:09 -0500)
committerPeter Amstutz <pamstutz@veritasgenetics.com>
Thu, 22 Feb 2018 19:09:33 +0000 (14:09 -0500)
Kernel behavior seems to be that if a file is referenced, its parents
remain referenced too.  This means has_ref() exits early when a
collection is not candidate for eviction.

By contrast, in_use() doesn't increment references on parents, so it
requires a full tree walk to determine if a collection is a candidate
for eviction.

Switching the order of the checks retains correctness but greatly
improves real-world performance.

Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz@veritasgenetics.com>

services/fuse/arvados_fuse/__init__.py

index 788d475e33c0d094d719503e6b9fc4dba386e1ec..3313e5a12e937232eca58eb741f85f56e185d750 100644 (file)
@@ -156,12 +156,14 @@ class InodeCache(object):
 
     def _remove(self, obj, clear):
         if clear:
-            if obj.in_use():
-                _logger.debug("InodeCache cannot clear inode %i, in use", obj.inode)
-                return
             if obj.has_ref(True):
                 _logger.debug("InodeCache cannot clear inode %i, still referenced", obj.inode)
                 return
+
+            if obj.in_use():
+                _logger.debug("InodeCache cannot clear inode %i, in use", obj.inode)
+                return
+
             obj.kernel_invalidate()
             _logger.debug("InodeCache sent kernel invalidate inode %i", obj.inode)
             obj.clear()
@@ -202,7 +204,8 @@ class InodeCache(object):
                     if obj not in self._by_uuid[obj.cache_uuid]:
                         self._by_uuid[obj.cache_uuid].append(obj)
             self._total += obj.objsize()
-            _logger.debug("InodeCache touched inode %i (size %i) (uuid %s) total now %i", obj.inode, obj.objsize(), obj.cache_uuid, self._total)
+            _logger.debug("InodeCache touched inode %i (size %i) (uuid %s) total now %i (%i entries)",
+                          obj.inode, obj.objsize(), obj.cache_uuid, self._total, len(self._entries))
             self.cap_cache()
 
     def touch(self, obj):