Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New threadLocal provides more performance. #1745

Merged
merged 28 commits into from
May 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0807761
SerializerFactory 获取Serializer时,锁住整个hashmap,导致整个过程被block
carryxyh Jan 10, 2018
65438b4
单元测试。保证一个class只有一个serializer和deserializer。单线程和多线程测试
carryxyh Jan 10, 2018
7291963
增加线程数 50 模拟多个线程来获取serializer和deserializer
carryxyh Jan 10, 2018
ed2ff0f
当cores线程数全都使用的情况下,默认线程池会把任务放入到队列中。队列满则再创建线程(总数不会超过Max线程数)
carryxyh Jan 11, 2018
f97db80
当cores线程数全都使用的情况下,默认线程池会把任务放入到队列中。队列满则再创建线程(总数不会超过Max线程数)
carryxyh Jan 11, 2018
a224bb0
Merge remote-tracking branch 'upstream/master'
carryxyh Jan 12, 2018
49aecfb
补全单元测试,测试扩展是否生效
carryxyh Jan 17, 2018
561397f
Merge remote-tracking branch 'upstream/master'
carryxyh Feb 7, 2018
60c2993
错误命名
carryxyh Feb 7, 2018
af29757
Merge remote-tracking branch 'upstream/master'
carryxyh Feb 26, 2018
4be8d61
增加@Override注解
carryxyh Feb 27, 2018
5cfe610
修复单元测试
carryxyh Feb 27, 2018
7830079
Merge remote-tracking branch 'upstream/master'
carryxyh Apr 8, 2018
a1a42c0
Merge remote-tracking branch 'upstream/master'
carryxyh Apr 25, 2018
be1418f
remove enhanced
carryxyh Apr 25, 2018
9653553
remove enhanced
carryxyh Apr 25, 2018
e28aa17
Merge remote-tracking branch 'upstream/master'
carryxyh May 5, 2018
dc41214
Faster ThreadLocal impl in internal use
carryxyh May 5, 2018
11373cf
add License
carryxyh May 5, 2018
6d4102c
fix ci failed
carryxyh May 5, 2018
c831e2c
fix ci failed
carryxyh May 5, 2018
3a055d2
fix ci failed
carryxyh May 5, 2018
722b757
fix ci failed
carryxyh May 5, 2018
3a2fad7
fix ci failed
carryxyh May 5, 2018
85249a3
Merge remote-tracking branch 'upstream/master' into fastthreadlocal
carryxyh May 14, 2018
ffac33f
remove author info
carryxyh May 14, 2018
c3ec317
fix destroy method
carryxyh May 14, 2018
1e38ad8
fix bug at method size.
carryxyh May 14, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.dubbo.common.threadlocal;

/**
* InternalThread
*/
public class InternalThread extends Thread {

private InternalThreadLocalMap threadLocalMap;

public InternalThread() {
}

public InternalThread(Runnable target) {
super(target);
}

public InternalThread(ThreadGroup group, Runnable target) {
super(group, target);
}

public InternalThread(String name) {
super(name);
}

public InternalThread(ThreadGroup group, String name) {
super(group, name);
}

public InternalThread(Runnable target, String name) {
super(target, name);
}

public InternalThread(ThreadGroup group, Runnable target, String name) {
super(group, target, name);
}

public InternalThread(ThreadGroup group, Runnable target, String name, long stackSize) {
super(group, target, name, stackSize);
}

/**
* Returns the internal data structure that keeps the threadLocal variables bound to this thread.
* Note that this method is for internal use only, and thus is subject to change at any time.
*/
public final InternalThreadLocalMap threadLocalMap() {
return threadLocalMap;
}

/**
* Sets the internal data structure that keeps the threadLocal variables bound to this thread.
* Note that this method is for internal use only, and thus is subject to change at any time.
*/
public final void setThreadLocalMap(InternalThreadLocalMap threadLocalMap) {
this.threadLocalMap = threadLocalMap;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.dubbo.common.threadlocal;

import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Set;

/**
* InternalThreadLocal
* A special variant of {@link ThreadLocal} that yields higher access performance when accessed from a
* {@link InternalThread}.
* <p></p>
* Internally, a {@link InternalThread} uses a constant index in an array, instead of using hash code and hash table,
* to look for a variable. Although seemingly very subtle, it yields slight performance advantage over using a hash
* table, and it is useful when accessed frequently.
* <p></p>
* This design is learning from {@see io.netty.util.concurrent.FastThreadLocal} which is in Netty.
*/
public class InternalThreadLocal<V> {

private static final int variablesToRemoveIndex = InternalThreadLocalMap.nextVariableIndex();

private final int index;

public InternalThreadLocal() {
index = InternalThreadLocalMap.nextVariableIndex();
}

/**
* Removes all {@link InternalThreadLocal} variables bound to the current thread. This operation is useful when you
* are in a container environment, and you don't want to leave the thread local variables in the threads you do not
* manage.
*/
@SuppressWarnings("unchecked")
public static void removeAll() {
InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet();
if (threadLocalMap == null) {
return;
}

try {
Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);
if (v != null && v != InternalThreadLocalMap.UNSET) {
Set<InternalThreadLocal<?>> variablesToRemove = (Set<InternalThreadLocal<?>>) v;
for (InternalThreadLocal<?> tlv : variablesToRemove) {
tlv.remove(threadLocalMap);
}
}
} finally {
InternalThreadLocalMap.remove();
}
}

/**
* Returns the number of thread local variables bound to the current thread.
*/
public static int size() {
InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet();
if (threadLocalMap == null) {
return 0;
} else {
return threadLocalMap.size();
}
}

public static void destroy() {
InternalThreadLocalMap.destroy();
}

@SuppressWarnings("unchecked")
private static void addToVariablesToRemove(InternalThreadLocalMap threadLocalMap, InternalThreadLocal<?> variable) {
Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);
Set<InternalThreadLocal<?>> variablesToRemove;
if (v == InternalThreadLocalMap.UNSET || v == null) {
variablesToRemove = Collections.newSetFromMap(new IdentityHashMap<InternalThreadLocal<?>, Boolean>());
threadLocalMap.setIndexedVariable(variablesToRemoveIndex, variablesToRemove);
} else {
variablesToRemove = (Set<InternalThreadLocal<?>>) v;
}

variablesToRemove.add(variable);
}

@SuppressWarnings("unchecked")
private static void removeFromVariablesToRemove(InternalThreadLocalMap threadLocalMap, InternalThreadLocal<?> variable) {

Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);

if (v == InternalThreadLocalMap.UNSET || v == null) {
return;
}

Set<InternalThreadLocal<?>> variablesToRemove = (Set<InternalThreadLocal<?>>) v;
variablesToRemove.remove(variable);
}

/**
* Returns the current value for the current thread
*/
@SuppressWarnings("unchecked")
public final V get() {
InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();
Object v = threadLocalMap.indexedVariable(index);
if (v != InternalThreadLocalMap.UNSET) {
return (V) v;
}

return initialize(threadLocalMap);
}

private V initialize(InternalThreadLocalMap threadLocalMap) {
V v = null;
try {
v = initialValue();
} catch (Exception e) {
throw new RuntimeException(e);
}

threadLocalMap.setIndexedVariable(index, v);
addToVariablesToRemove(threadLocalMap, this);
return v;
}

/**
* Sets the value for the current thread.
*/
public final void set(V value) {
if (value == null || value == InternalThreadLocalMap.UNSET) {
remove();
} else {
InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();
if (threadLocalMap.setIndexedVariable(index, value)) {
addToVariablesToRemove(threadLocalMap, this);
}
}
}

/**
* Sets the value to uninitialized; a proceeding call to get() will trigger a call to initialValue().
*/
@SuppressWarnings("unchecked")
public final void remove() {
remove(InternalThreadLocalMap.getIfSet());
}

/**
* Sets the value to uninitialized for the specified thread local map;
* a proceeding call to get() will trigger a call to initialValue().
* The specified thread local map must be for the current thread.
*/
@SuppressWarnings("unchecked")
public final void remove(InternalThreadLocalMap threadLocalMap) {
if (threadLocalMap == null) {
return;
}

Object v = threadLocalMap.removeIndexedVariable(index);
removeFromVariablesToRemove(threadLocalMap, this);

if (v != InternalThreadLocalMap.UNSET) {
try {
onRemoval((V) v);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

/**
* Returns the initial value for this thread-local variable.
*/
protected V initialValue() throws Exception {
return null;
}

/**
* Invoked when this thread local variable is removed by {@link #remove()}.
*/
protected void onRemoval(@SuppressWarnings("unused") V value) throws Exception {
}
}
Loading