Browse Source

replace every call to toupper with one to our own tolower_ascii

This sounds like a premature optimization and since Mr. Knuth we all
know that they are the root of all evil - but, and here it starts to be
interesting: As the tolower_ascii method is by far the most called
method we have (~60 Mio. times) and as we compare only strings containing
ascii characters (package names, configuration options) using our own
method reduces execution time of APT by 4% plus it avoids that the
locale settings can influence us.
David Kalnischkies 16 years ago
parent
commit
6dc60370a7
5 changed files with 44 additions and 46 deletions
  1. 4 4
      apt-pkg/contrib/error.h
  2. 6 4
      apt-pkg/contrib/macros.h
  3. 26 23
      apt-pkg/contrib/strutl.cc
  4. 6 15
      apt-pkg/contrib/strutl.h
  5. 2 0
      debian/changelog

+ 4 - 4
apt-pkg/contrib/error.h

@@ -60,13 +60,13 @@ class GlobalError
    public:
 
    // Call to generate an error from a library call.
-   bool Errno(const char *Function,const char *Description,...) __like_printf_2 __cold;
-   bool WarningE(const char *Function,const char *Description,...) __like_printf_2 __cold;
+   bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold;
+   bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold;
 
    /* A warning should be considered less severe than an error, and may be
       ignored by the client. */
-   bool Error(const char *Description,...) __like_printf_1 __cold;
-   bool Warning(const char *Description,...) __like_printf_1 __cold;
+   bool Error(const char *Description,...) __like_printf(2) __cold;
+   bool Warning(const char *Description,...) __like_printf(2) __cold;
 
    // Simple accessors
    inline bool PendingError() {return PendingFlag;};

+ 6 - 4
apt-pkg/contrib/macros.h

@@ -58,6 +58,7 @@
 #if __GNUC__ >= 3
 	#define __must_check	__attribute__ ((warn_unused_result))
 	#define __deprecated	__attribute__ ((deprecated))
+	#define __attrib_const	__attribute__ ((__const__))
 	/* likely() and unlikely() can be used to mark boolean expressions
 	   as (not) likely true which will help the compiler to optimise */
 	#define likely(x)	__builtin_expect (!!(x), 1)
@@ -65,6 +66,7 @@
 #else
 	#define __must_check	/* no warn_unused_result */
 	#define __deprecated	/* no deprecated */
+	#define __attrib_const	/* no const attribute */
 	#define likely(x)	(x)
 	#define unlikely(x)	(x)
 #endif
@@ -72,17 +74,17 @@
 // cold functions are unlikely() to be called
 #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
 	#define __cold	__attribute__ ((__cold__))
+	#define __hot	__attribute__ ((__hot__))
 #else
 	#define __cold	/* no cold marker */
+	#define __hot	/* no hot marker */
 #endif
 
 #ifdef __GNUG__
 // Methods have a hidden this parameter that is visible to this attribute
-	#define __like_printf_1	__attribute__ ((format (printf, 2, 3)))
-	#define __like_printf_2	__attribute__ ((format (printf, 3, 4)))
+	#define __like_printf(n)	__attribute__((format(printf, n, n + 1)))
 #else
-	#define __like_printf_1	/* no like-printf */
-	#define __like_printf_2	/* no like-printf */
+	#define __like_printf(n)	/* no like-printf */
 #endif
 
 #endif

+ 26 - 23
apt-pkg/contrib/strutl.cc

@@ -566,7 +566,7 @@ int stringcmp(string::const_iterator A,string::const_iterator AEnd,
 int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
 {
    for (; A != AEnd && B != BEnd; A++, B++)
-      if (toupper(*A) != toupper(*B))
+      if (tolower_ascii(*A) != tolower_ascii(*B))
 	 break;
 
    if (A == AEnd && B == BEnd)
@@ -575,7 +575,7 @@ int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd)
       return 1;
    if (B == BEnd)
       return -1;
-   if (toupper(*A) < toupper(*B))
+   if (tolower_ascii(*A) < tolower_ascii(*B))
       return -1;
    return 1;
 }
@@ -584,7 +584,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
 		  const char *B,const char *BEnd)
 {
    for (; A != AEnd && B != BEnd; A++, B++)
-      if (toupper(*A) != toupper(*B))
+      if (tolower_ascii(*A) != tolower_ascii(*B))
 	 break;
 
    if (A == AEnd && B == BEnd)
@@ -593,7 +593,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
       return 1;
    if (B == BEnd)
       return -1;
-   if (toupper(*A) < toupper(*B))
+   if (tolower_ascii(*A) < tolower_ascii(*B))
       return -1;
    return 1;
 }
@@ -601,7 +601,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
 		  string::const_iterator B,string::const_iterator BEnd)
 {
    for (; A != AEnd && B != BEnd; A++, B++)
-      if (toupper(*A) != toupper(*B))
+      if (tolower_ascii(*A) != tolower_ascii(*B))
 	 break;
 
    if (A == AEnd && B == BEnd)
@@ -610,7 +610,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd,
       return 1;
    if (B == BEnd)
       return -1;
-   if (toupper(*A) < toupper(*B))
+   if (tolower_ascii(*A) < tolower_ascii(*B))
       return -1;
    return 1;
 }
@@ -789,28 +789,28 @@ bool ReadMessages(int Fd, vector<string> &List)
 // MonthConv - Converts a month string into a number			/*{{{*/
 // ---------------------------------------------------------------------
 /* This was lifted from the boa webserver which lifted it from 'wn-v1.07'
-   Made it a bit more robust with a few touppers though. */
+   Made it a bit more robust with a few tolower_ascii though. */
 static int MonthConv(char *Month)
 {
-   switch (toupper(*Month)) 
+   switch (tolower_ascii(*Month)) 
    {
-      case 'A':
-      return toupper(Month[1]) == 'P'?3:7;
-      case 'D':
+      case 'a':
+      return tolower_ascii(Month[1]) == 'p'?3:7;
+      case 'd':
       return 11;
-      case 'F':
+      case 'f':
       return 1;
-      case 'J':
-      if (toupper(Month[1]) == 'A')
+      case 'j':
+      if (tolower_ascii(Month[1]) == 'a')
 	 return 0;
-      return toupper(Month[2]) == 'N'?5:6;
-      case 'M':
-      return toupper(Month[2]) == 'R'?2:4;
-      case 'N':
+      return tolower_ascii(Month[2]) == 'n'?5:6;
+      case 'm':
+      return tolower_ascii(Month[2]) == 'r'?2:4;
+      case 'n':
       return 10;
-      case 'O':
+      case 'o':
       return 9;
-      case 'S':
+      case 's':
       return 8;
 
       // Pretend it is January..
@@ -1133,10 +1133,13 @@ char *safe_snprintf(char *Buffer,char *End,const char *Format,...)
 
 // tolower_ascii - tolower() function that ignores the locale		/*{{{*/
 // ---------------------------------------------------------------------
-/* */
-int tolower_ascii(int c)
+/* This little function is the most called method we have and tries
+   therefore to do the absolut minimum - and is noteable faster than
+   standard tolower/toupper and as a bonus avoids problems with different
+   locales - we only operate on ascii chars anyway. */
+int tolower_ascii(int const c)
 {
-   if (c >= 'A' and c <= 'Z')
+   if (c >= 'A' && c <= 'Z')
       return c + 32;
    return c;
 }

+ 6 - 15
apt-pkg/contrib/strutl.h

@@ -25,19 +25,12 @@
 #include <iostream>
 #include <time.h>
 
+#include "macros.h"
+
 using std::string;
 using std::vector;
 using std::ostream;
 
-#ifdef __GNUG__
-// Methods have a hidden this parameter that is visible to this attribute
-#define APT_FORMAT2 __attribute__ ((format (printf, 2, 3)))
-#define APT_FORMAT3 __attribute__ ((format (printf, 3, 4)))
-#else
-#define APT_FORMAT2
-#define APT_FORMAT3
-#endif    
-
 bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest);
 char *_strstrip(char *String);
 char *_strtabexpand(char *String,size_t Len);
@@ -60,11 +53,11 @@ bool Hex2Num(const string &Str,unsigned char *Num,unsigned int Length);
 bool TokSplitString(char Tok,char *Input,char **List,
 		    unsigned long ListMax);
 vector<string> ExplodeString(string const &haystack, char const &split);
-void ioprintf(ostream &out,const char *format,...) APT_FORMAT2;
-void strprintf(string &out,const char *format,...) APT_FORMAT2;
-char *safe_snprintf(char *Buffer,char *End,const char *Format,...) APT_FORMAT3;
+void ioprintf(ostream &out,const char *format,...) __like_printf(2);
+void strprintf(string &out,const char *format,...) __like_printf(2);
+char *safe_snprintf(char *Buffer,char *End,const char *Format,...) __like_printf(3);
 bool CheckDomainList(const string &Host, const string &List);
-int tolower_ascii(int c);
+int tolower_ascii(int const c) __attrib_const __hot;
 
 #define APT_MKSTRCMP(name,func) \
 inline int name(const char *A,const char *B) {return func(A,A+strlen(A),B,B+strlen(B));}; \
@@ -144,6 +137,4 @@ struct RxChoiceList
 unsigned long RegexChoice(RxChoiceList *Rxs,const char **ListBegin,
 		      const char **ListEnd);
 
-#undef APT_FORMAT2
-
 #endif

+ 2 - 0
debian/changelog

@@ -60,6 +60,8 @@ apt (0.7.26) UNRELEASED; urgency=low
   * doc/po/de.po:
     - correct a few typos in the german manpage translation.
       Thanks to Chris Leick and Georg Koppen! (Closes: #574962)
+  * apt-pkg/contrib/strutl.cc:
+    - convert all toupper calls to tolower_ascii for a little speedup
 
   [ Julian Andres Klode ]
   * cmdline/apt-mark: