Skip to content

Commit

Permalink
optimize hot-key-sdk ArrayList init size
Browse files Browse the repository at this point in the history
  • Loading branch information
caojiajun committed Jul 18, 2023
1 parent fcf71ab commit 125a83e
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ public class CollectionSplitUtil {
public static <T> List<List<T>> split(Collection<T> collection, int splitSize) {
if (collection == null) return null;
if (collection.isEmpty()) return new ArrayList<>();
List<List<T>> res = new ArrayList<>();
List<List<T>> res = new ArrayList<>(collection.size() / splitSize + 1);
if (collection.size() < splitSize) {
res.add(new ArrayList<>(collection));
} else {
List<T> tmp = new ArrayList<>();
List<T> tmp = new ArrayList<>(splitSize);
for (T t : collection) {
tmp.add(t);
if (tmp.size() == splitSize) {
res.add(tmp);
tmp = new ArrayList<>();
tmp = new ArrayList<>(splitSize);
}
}
if (!tmp.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public List<KeyCounter> getList() {

@Override
public void marshal(Pack pack) {
ArrayMable<Props> arrayMable = new ArrayMable<>(Props.class);
ArrayMable<Props> arrayMable = new ArrayMable<>(new ArrayList<>(list.size()), Props.class);
for (KeyCounter counter : list) {
Props props = new Props();
props.put(Tag.namespace.value, counter.getNamespace());
Expand All @@ -60,7 +60,7 @@ public void marshal(Pack pack) {
public void unmarshal(Unpack unpack) {
ArrayMable<Props> arrayMable = new ArrayMable<>(Props.class);
unpack.popMarshallable(arrayMable);
list = new ArrayList<>();
list = new ArrayList<>(arrayMable.list.size());
for (Props props : arrayMable.list) {
KeyCounter counter = new KeyCounter();
counter.setNamespace(props.get(Tag.namespace.value));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.netease.nim.camellia.hot.key.sdk.netty.HotKeyClient;
import com.netease.nim.camellia.hot.key.sdk.netty.HotKeyClientHub;
import com.netease.nim.camellia.hot.key.sdk.netty.HotKeyClientListener;
import com.netease.nim.camellia.hot.key.sdk.util.HotKeySdkUtils;
import com.netease.nim.camellia.tools.executor.CamelliaThreadFactory;
import com.netease.nim.camellia.tools.utils.CamelliaMapUtils;
import org.slf4j.Logger;
Expand Down Expand Up @@ -58,6 +59,8 @@ public class CamelliaHotKeySdk implements ICamelliaHotKeySdk {
private final boolean async;
private LinkedBlockingQueue<QueueItem> queue;

private int collectListInitSize = HotKeySdkUtils.update(0);

public CamelliaHotKeySdk(CamelliaHotKeySdkConfig config) {
this.config = config;
if (config.getDiscovery() == null) {
Expand Down Expand Up @@ -194,16 +197,20 @@ private void schedulePush() {
Map<HotKeyClient, List<KeyCounter>> map = new HashMap<>();
for (KeyCounter counter : collect) {
HotKeyClient client = HotKeyClientHub.getInstance().selectClient(config.getDiscovery(), counter.getKey());
List<KeyCounter> counters = CamelliaMapUtils.computeIfAbsent(map, client, k -> new ArrayList<>());
List<KeyCounter> counters = CamelliaMapUtils.computeIfAbsent(map, client, k -> new ArrayList<>(collectListInitSize));
counters.add(counter);
}
int maxSize = 0;
for (Map.Entry<HotKeyClient, List<KeyCounter>> entry : map.entrySet()) {
HotKeyClient client = entry.getKey();
if (client == null) {
logger.error("selectClient return null, skip push");
continue;
}
List<KeyCounter> counters = entry.getValue();
if (counters.size() > maxSize) {
maxSize = counters.size();
}
List<List<KeyCounter>> split = CollectionSplitUtil.split(counters, config.getPushBatch());
for (List<KeyCounter> list : split) {
CompletableFuture<HotKeyPack> future = client.sendPack(HotKeyPack.newPack(HotKeyCommand.PUSH, new PushPack(list)));
Expand All @@ -218,6 +225,7 @@ private void schedulePush() {
});
}
}
this.collectListInitSize = HotKeySdkUtils.update(maxSize);
} catch (Exception e) {
logger.error("schedulePush error", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import com.github.benmanes.caffeine.cache.Caffeine;
import com.netease.nim.camellia.hot.key.common.model.KeyCounter;
import com.netease.nim.camellia.hot.key.common.model.KeyAction;
import com.netease.nim.camellia.hot.key.sdk.util.HotKeySdkUtils;
import com.netease.nim.camellia.tools.utils.CamelliaMapUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.LongAdder;

Expand All @@ -22,6 +24,7 @@ public class CaffeineHotKeyCounterCollector implements IHotKeyCounterCollector {
private final int capacity;
private final ConcurrentHashMap<String, Cache<String, LongAdder>> map1;
private final ConcurrentHashMap<String, Cache<String, LongAdder>> map2;
private int listInitSize = HotKeySdkUtils.update(0);

public CaffeineHotKeyCounterCollector(int capacity) {
this.capacity = capacity;
Expand Down Expand Up @@ -60,6 +63,7 @@ public synchronized List<KeyCounter> collect() {
clear(map1);
}
}
this.listInitSize = HotKeySdkUtils.update(result.size());
return result;
}

Expand All @@ -70,11 +74,11 @@ private void clear(ConcurrentHashMap<String, Cache<String, LongAdder>> map) {
}

private List<KeyCounter> toResult(ConcurrentHashMap<String, Cache<String, LongAdder>> map) {
List<KeyCounter> result = new ArrayList<>();
List<KeyCounter> result = new ArrayList<>(listInitSize);
for (Map.Entry<String, Cache<String, LongAdder>> entry : map.entrySet()) {
String namespace = entry.getKey();
Cache<String, LongAdder> subMap = entry.getValue();
for (Map.Entry<String, LongAdder> subEntry : subMap.asMap().entrySet()) {
ConcurrentMap<String, LongAdder> subMap = entry.getValue().asMap();
for (Map.Entry<String, LongAdder> subEntry : subMap.entrySet()) {
KeyCounter counter = new KeyCounter();
counter.setNamespace(namespace);
String uniqueKey = subEntry.getKey();
Expand All @@ -89,4 +93,5 @@ private List<KeyCounter> toResult(ConcurrentHashMap<String, Cache<String, LongAd
}
return result;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.netease.nim.camellia.hot.key.common.model.KeyAction;
import com.netease.nim.camellia.hot.key.common.model.KeyCounter;
import com.netease.nim.camellia.hot.key.sdk.util.HotKeySdkUtils;
import com.netease.nim.camellia.tools.utils.CamelliaMapUtils;

import java.util.ArrayList;
Expand All @@ -21,6 +22,7 @@ public class ConcurrentLinkedHashMapHotKeyCounterCollector implements IHotKeyCou
private final int capacity;
private final ConcurrentHashMap<String, ConcurrentLinkedHashMap<String, LongAdder>> map1;
private final ConcurrentHashMap<String, ConcurrentLinkedHashMap<String, LongAdder>> map2;
private int listInitSize = HotKeySdkUtils.update(0);

public ConcurrentLinkedHashMapHotKeyCounterCollector(int capacity) {
this.capacity = capacity;
Expand Down Expand Up @@ -56,6 +58,7 @@ public synchronized List<KeyCounter> collect() {
clear(map1);
}
}
this.listInitSize = HotKeySdkUtils.update(result.size());
return result;
}

Expand All @@ -66,7 +69,7 @@ private void clear(ConcurrentHashMap<String, ConcurrentLinkedHashMap<String, Lon
}

private List<KeyCounter> toResult(ConcurrentHashMap<String, ConcurrentLinkedHashMap<String, LongAdder>> map) {
List<KeyCounter> result = new ArrayList<>();
List<KeyCounter> result = new ArrayList<>(listInitSize);
for (Map.Entry<String, ConcurrentLinkedHashMap<String, LongAdder>> entry : map.entrySet()) {
String namespace = entry.getKey();
ConcurrentLinkedHashMap<String, LongAdder> subMap = entry.getValue();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.netease.nim.camellia.hot.key.sdk.util;

/**
* Created by caojiajun on 2023/7/18
*/
public class HotKeySdkUtils {

public static int update(int currentSize) {
if (currentSize <= 0) return 2000;
return Math.max(2000, Math.max(currentSize, currentSize + 1000));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static void main(String[] args) {
LocalConfHotKeyServerDiscovery discovery = new LocalConfHotKeyServerDiscovery("local", addrList);
config.setDiscovery(discovery);
config.setCollectorType(CollectorType.ConcurrentLinkedHashMap);//默认是Caffeine,如果对性能敏感,建议使用ConcurrentLinkedHashMap
config.setAsync(false);//是否异步,默认false,如果Collector的延迟不满足,则可以使用异步采集
config.setAsync(false);//是否异步,默认false,如果Collector的延迟不满足,则可以使用异步采集(异步采集会产生大量的线程上下文切换,可能得不偿失)
config.setAsyncQueueCapacity(100000);//异步队列的大小,默认10w

CamelliaHotKeySdk sdk = new CamelliaHotKeySdk(config);
Expand Down
2 changes: 1 addition & 1 deletion docs/hot-key/hot-key-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public class Test {

config.setDiscovery(null);//设置一个发现器,默认提供zk/eureka,也可以自己实现基于etcd/consul/nacos等其他注册中心
config.setCollectorType(CollectorType.Caffeine);//默认是Caffeine,还可以使用ConcurrentLinkedHashMap
config.setAsync(false);//是否异步,默认false,如果Collector的延迟不满足业务要求,则可以使用异步采集
config.setAsync(false);//是否异步,默认false,如果Collector的延迟不满足业务要求,则可以使用异步采集(异步采集会产生大量的线程上下文切换,可能得不偿失)
config.setAsyncQueueCapacity(100000);//异步队列的大小,默认10w
//如果需要同时访问多个集群,则需要初始化多个sdk,否则初始化一个实例即可
CamelliaHotKeySdk sdk = new CamelliaHotKeySdk(config);
Expand Down

0 comments on commit 125a83e

Please sign in to comment.