diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index c894cc85d9fca6ae9ce0818b8cf9858acb3aa381..b55aa2e17e1eac98f0afd0ff54cb2aedab11feac 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -222,6 +222,7 @@ set(llcommon_HEADER_FILES
     llsdutil.h
     llsimplehash.h
     llsingleton.h
+    llsortedvector.h
     llstacktrace.h
     llstl.h
     llstreamqueue.h
diff --git a/indra/llcommon/llsortedvector.h b/indra/llcommon/llsortedvector.h
new file mode 100644
index 0000000000000000000000000000000000000000..bb779e5192a68326dfb6d233ea17ef0eac0cdb78
--- /dev/null
+++ b/indra/llcommon/llsortedvector.h
@@ -0,0 +1,162 @@
+/**
+ * @file   llsortedvector.h
+ * @author Nat Goodspeed
+ * @date   2012-04-08
+ * @brief  LLSortedVector class wraps a vector that we maintain in sorted
+ *         order so we can perform binary-search lookups.
+ * 
+ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
+ * Copyright (c) 2012, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLSORTEDVECTOR_H)
+#define LL_LLSORTEDVECTOR_H
+
+#include <vector>
+#include <algorithm>
+
+/**
+ * LLSortedVector contains a std::vector<std::pair> that we keep sorted on the
+ * first of the pair. This makes insertion somewhat more expensive than simple
+ * std::vector::push_back(), but allows us to use binary search for lookups.
+ * It's intended for small aggregates where lookup is far more performance-
+ * critical than insertion; in such cases a binary search on a small, sorted
+ * std::vector can be more performant than a std::map lookup.
+ */
+template <typename KEY, typename VALUE>
+class LLSortedVector
+{
+public:
+    typedef LLSortedVector<KEY, VALUE> self;
+    typedef KEY key_type;
+    typedef VALUE mapped_type;
+    typedef std::pair<key_type, mapped_type> value_type;
+    typedef std::vector<value_type> PairVector;
+    typedef typename PairVector::iterator iterator;
+    typedef typename PairVector::const_iterator const_iterator;
+
+    /// Empty
+    LLSortedVector() {}
+
+    /// Fixed initial size
+    LLSortedVector(std::size_t size):
+        mVector(size)
+    {}
+
+    /// Bulk load
+    template <typename ITER>
+    LLSortedVector(ITER begin, ITER end):
+        mVector(begin, end)
+    {
+        // Allow caller to dump in a bunch of (pairs convertible to)
+        // value_type if desired, but make sure we sort afterwards.
+        std::sort(mVector.begin(), mVector.end());
+    }
+
+    /// insert(key, value)
+    std::pair<iterator, bool> insert(const key_type& key, const mapped_type& value)
+    {
+        return insert(value_type(key, value));
+    }
+
+    /// insert(value_type)
+    std::pair<iterator, bool> insert(const value_type& pair)
+    {
+        typedef std::pair<iterator, bool> iterbool;
+        iterator found = std::lower_bound(mVector.begin(), mVector.end(), pair,
+                                          less<value_type>());
+        // have to check for end() before it's even valid to dereference
+        if (found == mVector.end())
+        {
+            std::size_t index(mVector.size());
+            mVector.push_back(pair);
+            // don't forget that push_back() invalidates 'found'
+            return iterbool(mVector.begin() + index, true);
+        }
+        if (found->first == pair.first)
+        {
+            return iterbool(found, false);
+        }
+        // remember that insert() invalidates 'found' -- save index
+        std::size_t index(found - mVector.begin());
+        mVector.insert(found, pair);
+        // okay, convert from index back to iterator
+        return iterbool(mVector.begin() + index, true);
+    }
+
+    iterator begin() { return mVector.begin(); }
+    iterator end()   { return mVector.end(); }
+    const_iterator begin() const { return mVector.begin(); }
+    const_iterator end()   const { return mVector.end(); }
+
+    bool empty() const { return mVector.empty(); }
+    std::size_t size() const { return mVector.size(); }
+
+    /// find
+    iterator find(const key_type& key)
+    {
+        iterator found = std::lower_bound(mVector.begin(), mVector.end(),
+                                          value_type(key, mapped_type()),
+                                          less<value_type>());
+        if (found == mVector.end() || found->first != key)
+            return mVector.end();
+        return found;
+    }
+
+    const_iterator find(const key_type& key) const
+    {
+        return const_cast<self*>(this)->find(key);
+    }
+
+	//For easy insertion shorthand. Eases std::map => LLSortedVector drop-in replacement.
+	mapped_type& operator[] (const key_type& key)
+	{
+		 return insert(std::make_pair(key,mapped_type())).first->second;
+	}
+	const mapped_type& operator[] (const key_type& key) const
+	{
+		 return insert(std::make_pair(key,mapped_type())).first->second;
+	}
+
+private:
+    // Define our own 'less' comparator so we can specialize without messing
+    // with std::less.
+    template <typename T>
+    struct less: public std::less<T> {};
+
+    // Specialize 'less' for an LLSortedVector::value_type involving
+    // std::type_info*. This is one of LLSortedVector's foremost use cases. We
+    // specialize 'less' rather than just defining a specific comparator
+    // because LLSortedVector should be usable for other key_types as well.
+    template <typename T>
+    struct less< std::pair<std::type_info*, T> >:
+        public std::binary_function<std::pair<std::type_info*, T>,
+                                    std::pair<std::type_info*, T>,
+                                    bool>
+    {
+        bool operator()(const std::pair<std::type_info*, T>& lhs,
+                        const std::pair<std::type_info*, T>& rhs) const
+        {
+            return lhs.first->before(*rhs.first);
+        }
+    };
+
+    // Same as above, but with const std::type_info*.
+    template <typename T>
+    struct less< std::pair<const std::type_info*, T> >:
+        public std::binary_function<std::pair<const std::type_info*, T>,
+                                    std::pair<const std::type_info*, T>,
+                                    bool>
+    {
+        bool operator()(const std::pair<const std::type_info*, T>& lhs,
+                        const std::pair<const std::type_info*, T>& rhs) const
+        {
+            return lhs.first->before(*rhs.first);
+        }
+    };
+
+    PairVector mVector;
+};
+
+#endif /* ! defined(LL_LLSORTEDVECTOR_H) */