Bug #34000 Connection string cache optimization
Submitted: 23 Jan 2008 1:07 Modified: 1 Mar 2008 11:19
Reporter: Maxim Mass Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S5 (Performance)
Version:5.1.4 OS:Any
Assigned to: CPU Architecture:Any

[23 Jan 2008 1:07] Maxim Mass
Description:
Retrieving the MySqlConnectionStringBuilder object from connection string cache currently incurs an unnecessary overhead of performing a lookup in a NameObjectCollection. Even when there is only one item in the cache there's roughly .5ms of overhead which becomes noticeable as this is done very often in a db dependent app.

Another connection string related optimization is in MySqlConnectionStringBuilder.Clear()

How to repeat:
Make repeated db calls and look at 
Void MySql.Data.MySqlClient.MySqlConnection.set_ConnectionString(String)
with a profiler.

Suggested fix:
Replace the MySql.Data.Common.Cache class with the following which uses a dictionary instead but still removes connection string when filled to capacity.

MySql.Data.Common.Cache:

        private int _capacity;
        private Queue<KeyType> _keyQ;
        private Dictionary<KeyType, ValueType> _contents;

        public Cache(int initialCapacity, int capacity) {
            _capacity = capacity;
            _contents = new Dictionary<KeyType, ValueType>(initialCapacity);

            if (capacity > 0) {
                _keyQ = new Queue<KeyType>(initialCapacity);
            }
        }

        public ValueType this[KeyType key] {
            get {
                ValueType val;
                if (_contents.TryGetValue(key, out val))
                    return val;
                else
                    return default(ValueType);
            }
            set { InternalAdd(key, value); }
        }

        public void Add(KeyType key, ValueType value) {
            InternalAdd(key, value);
        }

        private void InternalAdd(KeyType key, ValueType value) {
            if (!_contents.ContainsKey(key)) {

                if (_capacity > 0) {
                    _keyQ.Enqueue(key);

                    if (_keyQ.Count > _capacity) {
                        _contents.Remove(_keyQ.Dequeue());
                    }
                }
            }

            _contents[key] = value;
        }
    }

MySqlConnectionStringBuilder.Clear():
Change
            foreach (Keyword k in defaultValues.Keys)
                SetValue(k, defaultValues[k]);
TO:
            foreach (KeyValuePair<Keyword, object> k in defaultValues)
                SetValue(k.Key, k.Value);

to avoid unnecessary dictionary lookups
[23 Jan 2008 1:09] Maxim Mass
Please note that this is part of a series of MySql.Data.DLL optimizations made by MindTouch for open source wiki software Deki Wiki.
[29 Jan 2008 16:32] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/41369
[29 Jan 2008 16:32] Reggie Burnett
Incorporated into 5.1.5 and 5.2+
[1 Mar 2008 11:19] MC Brown
A note has been added to the 5.1.5 and 5.2.0 changelog: 

Incorporated some connection string cache optimizations sent to us by Maxim Mass.