views:

68

answers:

3

Preamble: I'm working at heavy-loaded applicaion that produces large data arrays.

I wrote the following class

    using System;
    using System.Collections;
    using System.Collections.Generic;

    namespace CSharpSampleApplication.Data.CoreObjects
    {
        [Serializable]
        public class CalcItem
        {
            public CalcItem()
            {
                _additional = new Hashtable();
            }

            private readonly Hashtable _additional;

            public bool ContainsKey(int id)
            {
                return _additional.ContainsKey(id);
            }

            public void Add(int id, double value)
            {
                _additional.Add(id, value);
            }

            public DateTime Date { get; set; }

            public object this[int id]
            {
                get
                {
                    return _additional[id];
                }
            }
        }


    }

Then, in another class, i made manager which contains the following:

    public List<CalcItem> CalcItems{ get; private set;}
    private readonly Dictionary<string, int> _keys;
    private int _index;
    private readonly object  _lock = new object();

    public int GetIndex(string key)
    {
        lock (_lock)
        {
            if (_keys.ContainsKey(key))
                return _keys[key];
            else
            {
                _index++;
                _keys.Add(key, _index);
                return _index;
            }
        }
    }

By using those classes i log some realtime data, for example like this:

                var clc = new CalcItem();
                clc.Date = DateTime.Now;
                clc.Add(_calcItemManager.GetIndex("testData"), r.Next() / 100.00);
                clc.Add(_calcItemManager.GetIndex("testData1"), r.Next() / 100.00);

                i++;

                if (i % 25 == 0)
                {
                    clc.Add(_calcItemManager.GetIndex("testData2"), r.Next()/100.00);
                    clc.Add(_calcItemManager.GetIndex("testData3"), r.Next()/100.00);
                    clc.Add(_calcItemManager.GetIndex("testData4"), r.Next()/100.00);
                    clc.Add(_calcItemManager.GetIndex("testData5"), r.Next()/100.00);
                }
                _calcItemManager.Add(clc);

So the manager stores [string key]-[int index] bindings for all the calcItems.

The question is: Is it better to use Dictionary<int, double> instead of Hashtable() to optimize memory usage and faster perfomance? List Items - contains about 1.000.000 records CalcItem.Additional - contains about 5 - 10 records

+5  A: 

The obly way to answer "faster" is to time it for your typical data. However the dictionary is more convenient (no need to cast) and efficient (no boxing).

If the data keys are contiguous, however, it would be better just to use a List-of-double, and use the key as the index (with offset if your data doesn't start at 0).

Marc Gravell
The best! List-of-double - incredible idea - see my answer and new CalcItem class!!! Thanks a lot.
skaeff
+1  A: 

I think the accepted answer to this StackOverflow question also answers your question.

In brief, both data structures will have very similar performance in most situations. If it's important for you, you can (and should) measure.

RoadWarrior
A: 

Marc Gravell - awsome decision with List-of-double!!! How could i miss that?! Memory reduced twice! Here is my new code:

    using System;
    using System.Collections;
    using System.Collections.Generic;

    namespace CSharpSampleApplication.Data.CoreObjects
    {
        [Serializable]
        public class CalcItem
        {
            public CalcItem()
            {
                _additional = new List<double>();
            }

            private readonly List<double> _additional;

            public bool ContainsKey(int id)
            {
                return _additional.Count - 1 >= id;
            }

            public void Add(int id, double value)
            {
                if(ContainsKey(id))
                    _additional[id] = value;
                else
                {
                    while (!ContainsKey(id))
                    {
                        _additional.Add(0);
                    }
                    _additional[id] = value;
                }
            }

            public DateTime Date { get; set; }

            public object this[int id]
            {
                get
                {
                    return _additional[id];
                }
            }
        }


    }
skaeff