ThreadLocal和泛型

时间:2016-08-05 14:11:25

标签: performance f#

我想使用泛型创建一些线程本地静态数组。数组的大小取决于类型。我正在尝试做类似的事情:

type LeftoverPool private () =
    static let instance  = new ThreadLocal<'T[]>(fun () -> Array.zeroCreate (Vector<'T>.Count))
    static member Instance = instance.Value

但是这会将T限制为int。 我已经尝试使实例方法通用或类型,但无法使其工作。

2 个答案:

答案 0 :(得分:3)

从类型的角度来看,您目前正在尝试做的事情确实没有意义。

你有一个静态属性Instance,但它的类型完全不明确,因为它无法解析'T的含义。为此,您需要将类型注释传播到包含类型,例如:

type LeftoverPool<'T> private () =
    static let instance  = new ThreadLocal<'T[]>(fun () -> Array.zeroCreate<'T> (Vector<'T>.Count))
    static member Instance = instance.Value

答案 1 :(得分:2)

创建泛型类型,然后其静态成员将特定于该类型。 Resharper(用于C#)将发出警告,但这是您真正需要的。

此外,您还需要对ThreadStatic vs ThreadLocal进行基准测试,后者实际上是一个对象池,与仅存在于特殊域中的线程静态字段相比,我有一些查找开销每个线程的内存区域。

<强>更新

无论如何我打算测试一下,这是代码和输出。 ThreadStatic更快。

[TestFixture]
public class BuffersTests {

    public static class LocalBuffers<T> {
        [ThreadStatic]
        private static T[] _threadStatic;
        private static ThreadLocal<T[]> _threadLocal = new ThreadLocal<T[]>(() => new T[10]);
        public static T[] ThreadStatic => _threadStatic ?? (_threadStatic = new T[10]);
        public static T[] ThreadLocal => _threadLocal.Value;
    }

    [Test, Ignore]
    public void ThreadStaticVsThreadLocal() {
        for (int r = 0; r < 10; r++) {

            const int count = 100000000;
            var sw = new Stopwatch();

            sw.Restart();
            var sum = 0L;
            for (var i = 0; i < count; i++) {
                var buffer = LocalBuffers<int>.ThreadStatic;
                buffer[0] = 123;
                sum += buffer[0] + buffer[1];
            }
            Assert.IsTrue(sum > 0);
            sw.Stop();
            Console.WriteLine($"ThreadStatic {sw.ElapsedMilliseconds}");

            sw.Restart();
            sum = 0L;
            for (var i = 0; i < count; i++) {
                var buffer = LocalBuffers<int>.ThreadLocal;
                buffer[0] = 123;
                sum += buffer[0] + buffer[1];
            }
            Assert.IsTrue(sum > 0);
            sw.Stop();
            Console.WriteLine($"ThreadLocal {sw.ElapsedMilliseconds}");

            Console.WriteLine("---------------------");
        }
    }
}


ThreadStatic 1286
ThreadLocal 1860
---------------------
ThreadStatic 1312
ThreadLocal 1849
---------------------
ThreadStatic 1334
ThreadLocal 1933
---------------------
ThreadStatic 1390
ThreadLocal 2076
---------------------
ThreadStatic 1438
ThreadLocal 2088
---------------------
ThreadStatic 1295
ThreadLocal 2216
---------------------
ThreadStatic 1317
ThreadLocal 1972
---------------------
ThreadStatic 1380
ThreadLocal 1943
---------------------
ThreadStatic 1410
ThreadLocal 1970
---------------------