[Kst] branches/work/kst/portto4/kst/src/datasources/ascii

Peter Kümmel syntheticpp at gmx.net
Mon Jan 24 16:58:23 CET 2011


SVN commit 1216761 by kuemmel:

AsciiSource: much more inlining

Speedup of this commit:

Delimiters (comment, column)  :           time 
-----------------------------------------------------------
                                func ptr   inlined
No comment, custom: one space :   4.8        3.7
#  comment, custom: one space :   5.7        4.2
No comment, whitespace        :   6.2        4.0
#  comment, whitespace        :   6.9        4.2

 M  +53 -22    asciisource.cpp  
 M  +59 -18    asciisource.h  


--- branches/work/kst/portto4/kst/src/datasources/ascii/asciisource.cpp #1216760:1216761
@@ -30,6 +30,7 @@
 #include <assert.h>
 #include <ctype.h>
 #include <stdlib.h>
+#include <iostream>
 
 
 // Load faster in debug mode:
@@ -435,16 +436,17 @@
   } else if (_config._columnType == AsciiSourceConfig::Custom) {
     if (_config._columnDelimiter.value().size() == 1) {
       MeasureTime t("character");
-      _columnDelimiterCharacter = _config._columnDelimiter.value()[0].toAscii();
-      return readColumns(v, buffer, bufstart, bufread, col, s, n, &AsciiSource::isColumnDelimiter);
+      const IsCharacter column_del(_config._columnDelimiter.value()[0].toAscii());
+      return readColumns(v, buffer, bufstart, bufread, col, s, n, column_del);
     } if (_config._columnDelimiter.value().size() > 1) {
       MeasureTime t("string");
-      _columnDelimiterString = _config._columnDelimiter.value();
-      return readColumns(v, buffer, bufstart, bufread, col, s, n, &AsciiSource::isInColumnDelimiterString);
+      const IsInString column_del(_config._columnDelimiter.value());
+      return readColumns(v, buffer, bufstart, bufread, col, s, n, column_del);
     }
   } else if (_config._columnType == AsciiSourceConfig::Whitespace) {
     MeasureTime t("whitespace");
-    return readColumns(v, buffer, bufstart, bufread, col, s, n, &AsciiSource::isWhiteSpace);
+    const IsWhiteSpace column_del;
+    return readColumns(v, buffer, bufstart, bufread, col, s, n, column_del);
   }
 
   return 0;
@@ -452,42 +454,69 @@
 
 
 //-------------------------------------------------------------------------------------------
-int AsciiSource::readColumns(double* v, const char* buffer, int bufstart, int bufread, int col, int s, int n, DelimiterFunction columnDelemiterFunction)
+template<typename ColumnDelimiter>
+int AsciiSource::readColumns(double* v, const char* buffer, int bufstart, int bufread, int col, int s, int n,
+                              const ColumnDelimiter& column_del)
 {
-  LexicalCast lexc;
-  lexc.setDecimalSeparator(_config._useDot, _config._localSeparator);
-  const QString delimiters = _config._delimiters.value();
 
-  DelimiterFunction commentDelemiterFunction;
-
   if (_config._delimiters.value().size() == 0) {
-    commentDelemiterFunction = 0;
+    const NoDelimiter comment_del;
+    return readColumns(v, buffer, bufstart, bufread, col, s, n, column_del, comment_del);
   } else if (_config._delimiters.value().size() == 1) {
-    _commentDelimiterCharacter = _config._delimiters.value()[0].toAscii();
-    commentDelemiterFunction = &AsciiSource::isCommentDelimiter;
+    const IsCharacter comment_del(_config._delimiters.value()[0].toAscii());
+    return readColumns(v, buffer, bufstart, bufread, col, s, n, column_del, comment_del);
   } else if (_config._delimiters.value().size() > 1) {
-    _commentDelimiterString = _config._delimiters.value();
-    commentDelemiterFunction = &AsciiSource::isInCommentDelimiterString;
+    const IsInString comment_del(_config._delimiters.value());
+    return readColumns(v, buffer, bufstart, bufread, col, s, n, column_del, comment_del);
   }
 
+  return 0;
+}
+
+template<typename ColumnDelimiter, typename CommentDelimiter>
+int AsciiSource::readColumns(double* v, const char* buffer, int bufstart, int bufread, int col, int s, int n,
+                              const ColumnDelimiter& column_del, const CommentDelimiter& comment_del)
+{
+  if (_config._columnWidthIsConst) {
+    const AlwaysTrue column_withs_are_const;
+    return readColumns(v, buffer, bufstart, bufread, col, s, n, column_del, comment_del, column_withs_are_const);
+  } else {
+    const AlwaysFalse column_withs_are_not_const;
+    return readColumns(v, buffer, bufstart, bufread, col, s, n, column_del, comment_del, column_withs_are_not_const);
+  }
+}
+
+
+template<typename ColumnDelimiter, typename CommentDelimiter, typename ColumnWidthsAreConst>
+int AsciiSource::readColumns(double* v, const char* buffer, int bufstart, int bufread, int col, int s, int n,
+                              const ColumnDelimiter& column_del, const CommentDelimiter& comment_del,
+                              const ColumnWidthsAreConst& are_column_widths_const)
+{
+  LexicalCast lexc;
+  lexc.setDecimalSeparator(_config._useDot, _config._localSeparator);
+  const QString delimiters = _config._delimiters.value();
+
+  const IsLineBreak isLineBreak;
+
   int col_start = -1;
   for (int i = 0; i < n; i++, s++) {
     bool incol = false;
     int i_col = 0;
 
-    if (_config._columnWidthIsConst && col_start != -1) {
+    if (are_column_widths_const()) {
+      if (col_start != -1) {
       v[i] = lexc.toDouble(&buffer[0] + _rowIndex[s] + col_start);
       continue;
     }
+    }
 
     v[i] = Kst::NOPOINT;
-    int ch;
-    for (ch = _rowIndex[s] - bufstart; ch < bufread; ++ch) {
-      if (buffer[ch] == '\n' || buffer[ch] == '\r') {
+    for (int ch = _rowIndex[s] - bufstart; ch < bufread; ++ch) {
+      if (isLineBreak(buffer[ch])) {
         break;
-      } else if ((this->*columnDelemiterFunction)(buffer[ch])) { //<- check for column start
+      } else if (column_del(buffer[ch])) { //<- check for column start
         incol = false;
-      } else if (commentDelemiterFunction && (this->*commentDelemiterFunction)(buffer[ch])) {
+      } else if (comment_del(buffer[ch])) {
         break;
       } else {
         if (!incol) {
@@ -495,9 +524,11 @@
           ++i_col;
           if (i_col == col) {
             toDouble(lexc, buffer, bufread, ch, &v[i], i);
+            if (are_column_widths_const()) {
             if (col_start == -1) {
               col_start = ch - _rowIndex[s]  + 1;
             }
+            }
             break;
           }
         }
--- branches/work/kst/portto4/kst/src/datasources/ascii/asciisource.h #1216760:1216761
@@ -103,38 +103,79 @@
     int readFromFile(QFile&, T& buffer, int start, int numberOfBytes, int maximalBytes = -1);
 
 
-    // column delimiter functions
+    // column and comment delimiter functions
 
-    bool isWhiteSpace(char c) { 
-      return isspace((unsigned char)c); 
+    struct AlwaysTrue {
+      AlwaysTrue() {
     }
+      inline bool operator()() const {
+        return true;
+      }
+    };
 
-    char _columnDelimiterCharacter;
-    bool isColumnDelimiter(char c) {
-      return _columnDelimiterCharacter == c;
+    struct AlwaysFalse {
+      AlwaysFalse() {
     }
+      inline bool operator()() const {
+        return false;
+      }
+    };
 
-    QString _columnDelimiterString;
-    bool isInColumnDelimiterString(char c) {
-      return _columnDelimiterString.contains(c);
+    struct NoDelimiter {
+      NoDelimiter() {
     }
+      inline bool operator()(const char) const {
+        return false;
+      }
+    };
 
+    struct  IsWhiteSpace {
+      IsWhiteSpace() {
+      }
+      inline bool operator()(const char c) const {
+        return c == ' ' || c == '\t';
+      }
+    };
 
-    // comment delimiter functions
+    struct IsCharacter {
+      IsCharacter(char c) : character(c) {
+      }
+      const char character;
+      inline bool operator()(const char c) const {
+        return character == c;
+      }
+    };
 
-    char _commentDelimiterCharacter;
-    bool isCommentDelimiter(char c) {
-      return _commentDelimiterCharacter == c;
+    struct IsInString {
+      IsInString(const QString& s) : str(s) {
     }
+      const QString str;
+      inline bool operator()(const char c) const {
+        return str.contains(c);
+      }
+    };
 
-    QString _commentDelimiterString;
-    bool isInCommentDelimiterString(char c) {
-      return _commentDelimiterString.contains(c);
+    struct IsLineBreak {
+      IsLineBreak() {
     }
+      inline bool operator()(const char c) const {
+        return c == '\n' || c == '\r';
+      }
+    };
 
-    typedef bool (AsciiSource::*DelimiterFunction)(char);
 
-    int readColumns(double* v, const char* buffer, int bufstart, int bufread, int col, int s, int n, DelimiterFunction);
+    template<typename ColumnDelimiter>
+    int readColumns(double* v, const char* buffer, int bufstart, int bufread, int col, int s, int n,
+                    const ColumnDelimiter&);
+
+    template<typename ColumnDelimiter, typename CommentDelimiter>
+    int readColumns(double* v, const char* buffer, int bufstart, int bufread, int col, int s, int n,
+                    const ColumnDelimiter&, const CommentDelimiter&);
+
+    template<typename ColumnDelimiter, typename CommentDelimiter, typename ColumnWidthsAreConst>
+    int readColumns(double* v, const char* buffer, int bufstart, int bufread, int col, int s, int n,
+                    const ColumnDelimiter&, const CommentDelimiter&, const ColumnWidthsAreConst&);
+
     void toDouble(const LexicalCast& lexc, const char* buffer, int bufread, int ch, double* v, int row);
 
     // TODO remove


More information about the Kst mailing list