鏈表與Hash檢索實測

測試環境:html

  Win7 SP一、8G內存、3.4GHz 4核redis

測試代碼:緩存

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Diagnostics;

namespace FactoryMode
{
    public class TestObject
    {
        public string memberString { get; set; }
        public long memberBigInt { get; set; }
    }

    [Serializable]
    public class Program : MarshalByRefObject
    {
        static long TotalCount = 2000000;
        static long FisrtLv = 500000;
        static long SecondLv = 1000000;
        static long ThirdLv = 1500000;

        static void Main(string[] args)
        {
            //鏈表測試資源準備
            var ObjectList = new List<TestObject>();
            for (int i = 0; i < TotalCount; i++)
            {
                var newTestObject = new TestObject();
                newTestObject.memberString = i.ToString();
                newTestObject.memberBigInt = i;
                ObjectList.Add(newTestObject);
            }

            //查找1
            var stopWatch1 = Stopwatch.StartNew();
            var result1 = ObjectList.Find(p => p.memberBigInt == SecondLv);
            var lastElapsedTime1 = stopWatch1.ElapsedMilliseconds;
            Console.WriteLine("Condition 1: {0} ms.", lastElapsedTime1);
            Console.WriteLine("result1: {0}.", result1.memberString);

            //字典測試資源準備
            var ObjectDictionary = new Dictionary<string, TestObject>();
            for (int i = 0; i < TotalCount; i++)
            {
                var newTestObject = new TestObject();
                newTestObject.memberString = i.ToString();
                newTestObject.memberBigInt = i;
                ObjectDictionary.Add(newTestObject.memberString, newTestObject);
            }

            //查找2
            var stopWatch2 = Stopwatch.StartNew();
            var result2 = ObjectDictionary[Convert.ToString(ThirdLv)];
            var lastElapsedTime2 = stopWatch2.ElapsedMilliseconds;
            Console.WriteLine("Condition 2: {0} ms.", lastElapsedTime2);
            Console.WriteLine("result2: {0}.", result2.memberString);

            Console.Read();


        }
    }
}

測試結果:服務器

  鏈表檢索:每50w 12ms;數據結構

  Hash檢索:0ms;函數

 

測試代碼2:性能

            //寫入1
            var stopWatch3 = Stopwatch.StartNew();
            for (int i = 0; i < FisrtLv; i++)
            {
                ObjectList[i].memberBigInt += 1;
            }
            var lastElapsedTime3 = stopWatch3.ElapsedMilliseconds;
            Console.WriteLine("Condition 3: {0} ms.", lastElapsedTime3);
            
            //寫入2
            var stopWatch4 = Stopwatch.StartNew();
            for (int i = 0; i < FisrtLv; i++)
            {
                ObjectDictionary[Convert.ToString(i)].memberBigInt += 1;
            }
            var lastElapsedTime4 = stopWatch4.ElapsedMilliseconds;
            Console.WriteLine("Condition 4: {0} ms.", lastElapsedTime4);

測試結果2:測試

  鏈表寫入:12ms;spa

  Hash寫入:143ms;(根據散列函數獲得了新的存儲位置,數據轉移開銷)pwa

 

技術參考:http://blog.sina.com.cn/s/blog_7880b6e30100xi94.html

注意點:

  雖然Hash具備O(1)的數據檢索效率,但它空間開銷卻一般很大,是以空間換取時間,因此Hashtable適用於讀取操做頻繁,寫入操做不多的操做類型。

引伸思考:

  在實際的應用中,應避免將全部的經常使用、不經常使用的數據都放在同一個數據結構中,不管是使用自定義的內存結構或者是redis,都應該定時將過時數據放入二級緩存,爲一級緩存瘦身。

  在遊戲服務器應用中,一個服務器應將數據分爲內存數據、冷備數據,登錄時將冷備數據加載至內存(登錄較慢可容忍),單服熱數據容量通常不會超過5w級別,數據結構的性能可接受。

  在以前一個http短鏈接項目的應用中,每次協議都直接從redis讀取數據,處理完畢以後寫入redis,可是 redis 實際上沒有冷數據,這樣隨着運行時間的推移,效率會愈來愈低。

相關文章
相關標籤/搜索