From 985b50e26cd580b41dd62153ebb82cf75cd05222 Mon Sep 17 00:00:00 2001 From: Tigran Mkrtchyan Date: Mon, 17 Dec 2018 10:01:33 +0100 Subject: [PATCH] nlm: improve concurrency of simple lock manager Motivation: when a large number of concurrent applications competing for file locks, then SimpleLm will serialise all request as a single lock object is used for all files. To reduce lock conjunction and improve concurrency a serialization per lock subject (file) is a better option. Modification: Use Striped lock to partition locks. The number of partition is equal 4x#CPUs. It's guaranteed, that for the same file, the same lock will be used. Result: Better lock throughput. Acked-by: Paul Millar Target: master Require-book: no Require-notes: no --- .../java/org/dcache/nfs/v4/nlm/SimpleLm.java | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/dcache/nfs/v4/nlm/SimpleLm.java b/core/src/main/java/org/dcache/nfs/v4/nlm/SimpleLm.java index 99a6ad3e8..195374415 100644 --- a/core/src/main/java/org/dcache/nfs/v4/nlm/SimpleLm.java +++ b/core/src/main/java/org/dcache/nfs/v4/nlm/SimpleLm.java @@ -22,9 +22,9 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.google.common.io.BaseEncoding; +import com.google.common.util.concurrent.Striped; import java.util.Collection; import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; /** * Simple non-distributed implementation of {@link LockManager}. @@ -33,10 +33,17 @@ */ public class SimpleLm extends AbstractLockManager { - /** - * Exclusive lock on file object. + /* + * Use {@link Striped} here to split synchronized block on file locks into + * multiple partitions to increase concurrency, while guaranteeing atomicity + * on a single file. + * + * Use number of stripes equals to 4x#CPU. This matches to number of + * worker threads configured by default. + * + * FIXME: get number of threads from RPC service. */ - private final Lock objLock = new ReentrantLock(); + private final Striped objLock = Striped.lock(Runtime.getRuntime().availableProcessors() * 4); /** * Exclusive lock on objects locks. @@ -45,37 +52,42 @@ public class SimpleLm extends AbstractLockManager { @Override protected Lock getObjectLock(byte[] objId) { - return objLock; + String key = toKey(objId); + return objLock.get(key); } @Override protected Collection getActiveLocks(byte[] objId) { - String key = BaseEncoding.base16().lowerCase().encode(objId); + String key = toKey(objId); return locks.get(key); } @Override protected void add(byte[] objId, NlmLock lock) { - String key = BaseEncoding.base16().lowerCase().encode(objId); + String key = toKey(objId); locks.put(key, lock); } @Override protected boolean remove(byte[] objId, NlmLock lock) { - String key = BaseEncoding.base16().lowerCase().encode(objId); + String key = toKey(objId); return locks.remove(key, lock); } @Override protected void addAll(byte[] objId, Collection locks) { - String key = BaseEncoding.base16().lowerCase().encode(objId); + String key = toKey(objId); locks.forEach(l -> this.locks.put(key, l)); } @Override protected void removeAll(byte[] objId, Collection locks) { - String key = BaseEncoding.base16().lowerCase().encode(objId); + String key = toKey(objId); locks.forEach(l -> this.locks.remove(key, l)); } + private final String toKey(byte[] objId) { + return BaseEncoding.base16().lowerCase().encode(objId); + } + }