2016-08-05 62 views
2

我想創建一些線程局部靜態數組,使用泛型。數組的大小取決於類型。我試圖做類似的:ThreadLocal和泛型

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

但是,這約束T爲int。 我試着讓實例方法泛型或類型,但不能得到這個工作。

+0

您正在使用靜態解析泛型,請嘗試使用常規類型 - 只需用'T'替換'^ T'。 –

+0

我已編輯示例以使用常規泛型。但問題依然存在。 – jackmott

+1

嘗試指定泛型參數的起源位置。 'LeftoverPool < 'T>' –

回答

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 
+0

啊,我曾試過這個,但是我們得到了約束錯誤,但是一旦我將它們全部應用,它看起來就像這樣。經過一些測試後會稍微接受。 – jackmott

+0

@jackmott是的,如果'Vector <'T>'對'T'有一些限制,您將不得不將它們應用於'LeftoverPool <'T>'。 – TheInnerLight

+0

Downvoter:也許你可以解釋你對這個答案的反對意見嗎? – TheInnerLight

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 
---------------------