]> granicus.if.org Git - icinga2/commitdiff
Improve performance for icinga::Deserialize.
authorGunnar Beutner <gunnar.beutner@netways.de>
Fri, 13 Dec 2013 11:54:14 +0000 (12:54 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Fri, 13 Dec 2013 13:08:11 +0000 (14:08 +0100)
Refs #5327

lib/base/serializer.cpp
lib/base/utility.cpp
lib/base/utility.h
tools/mkclass/classcompiler.cpp
tools/mkclass/classcompiler.h

index a23450c63534cc77f7bdb390b8731247b9fbb5be..7f5faa900ccf7b1e602307bb5122ce952bd957fa 100644 (file)
@@ -161,21 +161,24 @@ static Object::Ptr DeserializeObject(const Object::Ptr& object, const Dictionary
        if (!instance)
                instance = type->Instantiate();
 
-       for (int i = 0; i < type->GetFieldCount(); i++) {
-               Field field = type->GetFieldInfo(i);
+       BOOST_FOREACH(const Dictionary::Pair& kv, input) {
+               if (kv.first.IsEmpty())
+                       continue;
 
-               if ((field.Attributes & attributeTypes) == 0)
+               int fid = type->GetFieldId(kv.first);
+       
+               if (fid < 0)
                        continue;
 
-               Value value = input->Get(field.Name);
+               Field field = type->GetFieldInfo(fid);
 
-               if (value.IsEmpty())
+               if ((field.Attributes & attributeTypes) == 0)
                        continue;
 
                try {
-                       instance->SetField(i, Deserialize(value, attributeTypes));
+                       instance->SetField(fid, Deserialize(kv.second, attributeTypes));
                } catch (const std::exception&) {
-                       instance->SetField(i, Empty);
+                       instance->SetField(fid, Empty);
                }
        }
 
index f60e6771830a0b9e745e637739dd34b23796dde8..f891ac8b29431fe9e8df61d94cd2658fbb6fe006 100644 (file)
@@ -705,12 +705,18 @@ String Utility::GetThreadName(void)
        return *name;
 }
 
-unsigned long Utility::SDBM(const String& str)
+unsigned long Utility::SDBM(const String& str, size_t len)
 {
        unsigned long hash = 0;
+       size_t current = 0;
 
        BOOST_FOREACH(char c, str) {
+               if (current >= len)
+                       break;
+
                hash = c + (hash << 6) + (hash << 16) - hash;
+
+               current++;
        }
 
        return hash;
index 6fef1d6081b94541997da6889247771d012c54c2..8ad1b49a36cf6ea82271431c96669601b41dad66 100644 (file)
@@ -102,7 +102,7 @@ public:
        static void SetThreadName(const String& name, bool os = true);
        static String GetThreadName(void);
 
-       static unsigned long SDBM(const String& str);
+       static unsigned long SDBM(const String& str, size_t len = String::NPos);
 
        static int CompareVersion(const String& v1, const String& v2);
 
index 28892309ed4b3c63155c827163255c98b3eaa9ae..561ac74c0dcbbac7a472bead985fb7e93ed0036e 100644 (file)
@@ -21,6 +21,8 @@
 #include <iostream>
 #include <fstream>
 #include <stdexcept>
+#include <map>
+#include <vector>
 
 using namespace icinga;
 
@@ -77,6 +79,27 @@ void ClassCompiler::HandleCode(const std::string& code, const ClassDebugInfo& lo
        std::cout << code << std::endl;
 }
 
+unsigned long ClassCompiler::SDBM(const std::string& str, size_t len = std::string::npos)
+{
+       unsigned long hash = 0;
+       size_t current = 0;
+
+       std::string::const_iterator it;
+
+       for (it = str.begin(); it != str.end(); it++) {
+               if (current >= len)
+                        break;
+
+               char c = *it;
+
+                hash = c + (hash << 6) + (hash << 16) - hash;
+
+                current++;
+        }
+
+        return hash;
+}
+
 void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
 {
        std::vector<Field>::const_iterator it;
@@ -136,11 +159,47 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
 
        std::cout << ";" << std::endl << std::endl;
 
-       int num = 0;
-       for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
-               std::cout << "\t\t" << "if (name == \"" << it->Name << "\")" << std::endl
-                       << "\t\t\t" << "return offset + " << num << ";" << std::endl;
-               num++;
+       std::map<int, std::vector<std::pair<int, std::string> > > jumptable;
+
+       int hlen = 0, collisions = 0;
+
+       do {
+               int num = 0;
+
+               hlen++;
+               jumptable.clear();
+               collisions = 0;
+
+               for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
+                       int hash = static_cast<int>(SDBM(it->Name, hlen));
+                       jumptable[hash].push_back(std::make_pair(num, it->Name));
+                       num++;
+
+                       if (jumptable[hash].size() > 1)
+                               collisions++;
+               }
+       } while (collisions >= 5 && hlen < 8);
+
+       if (!klass.Fields.empty()) {
+               std::cout << "\t\tswitch (static_cast<int>(Utility::SDBM(name, " << hlen << "))) {" << std::endl;
+
+               std::map<int, std::vector<std::pair<int, std::string> > >::const_iterator itj;
+
+               for (itj = jumptable.begin(); itj != jumptable.end(); itj++) {
+                       std::cout << "\t\t\tcase " << itj->first << ":" << std::endl;
+
+                       std::vector<std::pair<int, std::string> >::const_iterator itf;
+
+                       for (itf = itj->second.begin(); itf != itj->second.end(); itf++) {
+                               std::cout << "\t\t\t\t" << "if (name == \"" << itf->second << "\")" << std::endl
+                                       << "\t\t\t\t\t" << "return offset + " << itf->first << ";" << std::endl;
+                       }
+
+                       std::cout << std::endl
+                                 << "\t\t\t\tbreak;" << std::endl;
+               }
+
+               std::cout << "\t\t}" << std::endl;
        }
 
        std::cout << std::endl
@@ -178,7 +237,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
 
                std::cout << ") {" << std::endl;
 
-               num = 0;
+               size_t num = 0;
                for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
                        std::cout << "\t\t\t" << "case " << num << ":" << std::endl
                                << "\t\t\t\t" << "return Field(" << num << ", \"" << it->Name << "\", " << it->Attributes << ");" << std::endl;
@@ -259,7 +318,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
 
                std::cout << ") {" << std::endl;
 
-               num = 0;
+               size_t num = 0;
                for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
                        std::cout << "\t\t\t" << "case " << num << ":" << std::endl
                                          << "\t\t\t\t" << "Set" << it->GetFriendlyName() << "(";
@@ -417,7 +476,8 @@ void ClassCompiler::CompileStream(const std::string& path, std::istream *stream)
                          << "#include \"base/debug.h\"" << std::endl
                          << "#include \"base/value.h\"" << std::endl
                          << "#include \"base/array.h\"" << std::endl
-                         << "#include \"base/dictionary.h\"" << std::endl << std::endl
+                         << "#include \"base/dictionary.h\"" << std::endl
+                         << "#include \"base/utility.h\"" << std::endl << std::endl
                          << "#ifdef _MSC_VER" << std::endl
                          << "#pragma warning( push )" << std::endl
                          << "#pragma warning( disable : 4244 )" << std::endl
index c6298d9bcf8925a6ec7bf32eb0a44fa6a35543d9..386d212440bc001e24d8a8a20b50e7a37a7f7c73 100644 (file)
@@ -142,6 +142,8 @@ private:
        std::string m_Path;
        std::istream *m_Input;
        void *m_Scanner;
+
+       static unsigned long SDBM(const std::string& str, size_t len);
 };
 
 }