splash/SplashXPathScanner.cc | 53 +++++++++++++++++++++++-------------------- splash/SplashXPathScanner.h | 3 -- 2 files changed, 30 insertions(+), 26 deletions(-)
New commits: commit a32fb958e48ced022a358b5933ae669923f81bb3 Author: Stefan Brüns <[email protected]> Date: Sun May 27 06:10:37 2018 +0200 SplashXPathScanner: Force inlining of addIntersection The majority of the code in addIntersection can be optimized away for vertical (x0 == x1) and horizontal (count == 0) segments, thus the inlined code is less than the function call setup alone. This leaves diagonal segments as the only remaining call site, i.e. inlining here is a net win as well. Reduces runtime for #57 (fdo#96728, runsforever-poppler.pdf) from 1442 seconds to 1239 seconds (86%), and #24 (fdo#78728, surf-types.pdf) from ~ 5.0 seconds to 4.7 seconds. diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc index 51cd2c91..9b6943dd 100644 --- a/splash/SplashXPathScanner.cc +++ b/splash/SplashXPathScanner.cc @@ -324,6 +324,7 @@ void SplashXPathScanner::computeIntersections() { } } +inline GBool SplashXPathScanner::addIntersection(double segYMin, double segYMax, int y, int x0, int x1, int count) { SplashIntersect intersect; commit 97f310b1c5e29e4c323a1688c20b2754e9b36adc Author: Stefan Brüns <[email protected]> Date: Sun May 27 06:10:36 2018 +0200 SplashXPathScanner: Move more invariant code out of the loop "seg->x0 - seg->y0 * seg->dxdy" is constant and can be moved out of the loop. The next start point is the old end point. Thus, only the new x coordinate has to clamped (segXMin <= xx1 <= segXMax), also do the 'floor' operation just once per loop. According to valgrind/callgrind, this reduces instruction count in computeIntersections() for #24 (fdo#78728) by 6%. No change for fdo#96728. diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc index d1aedc73..51cd2c91 100644 --- a/splash/SplashXPathScanner.cc +++ b/splash/SplashXPathScanner.cc @@ -286,27 +286,33 @@ void SplashXPathScanner::computeIntersections() { if (y1 > yMax) { y1 = yMax; } - // this loop could just add seg->dxdy to xx1 on each iteration, - // but that introduces numerical accuracy problems - xx1 = seg->x0 + ((SplashCoord)y0 - seg->y0) * seg->dxdy; int count = eo || (seg->flags & splashXPathFlip) ? 1 : -1; + // Calculate the projected intersection of the segment with the + // X-Axis. + SplashCoord xbase = seg->x0 - (seg->y0 * seg->dxdy); + xx0 = xbase + ((SplashCoord)y0) * seg->dxdy; + // the segment may not actually extend to the top and/or bottom edges + if (xx0 < segXMin) { + xx0 = segXMin; + } else if (xx0 > segXMax) { + xx0 = segXMax; + } + int x0 = splashFloor(xx0); + for (y = y0; y <= y1; ++y) { - xx0 = xx1; - xx1 = seg->x0 + ((SplashCoord)(y + 1) - seg->y0) * seg->dxdy; - // the segment may not actually extend to the top and/or bottom edges - if (xx0 < segXMin) { - xx0 = segXMin; - } else if (xx0 > segXMax) { - xx0 = segXMax; - } + xx1 = xbase + ((SplashCoord)(y + 1) * seg->dxdy); + if (xx1 < segXMin) { xx1 = segXMin; } else if (xx1 > segXMax) { xx1 = segXMax; } - if (!addIntersection(segYMin, segYMax, y, splashFloor(xx0), - splashFloor(xx1), count)) - break; + int x1 = splashFloor(xx1); + if (!addIntersection(segYMin, segYMax, y, x0, x1, count)) + break; + + xx0 = xx1; + x0 = x1; } } } commit d8ba50c6638ad6720188c0c8237ffb5bbc3af490 Author: Stefan Brüns <[email protected]> Date: Sat May 26 21:34:49 2018 +0200 SplashXPathScanner: Move invariant checks out of addIntersection loop For horizontal segments, count is always 0. For vertical/diagonal segments, the count depends on the winding rule (EvenOdd/NonZero) and the direction, but is constant for each segment. Reduces runtime for #57 (fdo#96728) from 1773 seconds to 1442 seconds (81%). diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc index 6954a2c8..d1aedc73 100644 --- a/splash/SplashXPathScanner.cc +++ b/splash/SplashXPathScanner.cc @@ -251,8 +251,8 @@ void SplashXPathScanner::computeIntersections() { if (seg->flags & splashXPathHoriz) { y = splashFloor(seg->y0); if (y >= yMin && y <= yMax) { - if (!addIntersection(segYMin, segYMax, seg->flags, - y, splashFloor(seg->x0), splashFloor(seg->x1))) + if (!addIntersection(segYMin, segYMax, y, splashFloor(seg->x0), + splashFloor(seg->x1), 0)) break; } } else if (seg->flags & splashXPathVert) { @@ -265,8 +265,9 @@ void SplashXPathScanner::computeIntersections() { y1 = yMax; } x = splashFloor(seg->x0); + int count = eo || (seg->flags & splashXPathFlip) ? 1 : -1; for (y = y0; y <= y1; ++y) { - if (!addIntersection(segYMin, segYMax, seg->flags, y, x, x)) + if (!addIntersection(segYMin, segYMax, y, x, x, count)) break; } } else { @@ -288,6 +289,7 @@ void SplashXPathScanner::computeIntersections() { // this loop could just add seg->dxdy to xx1 on each iteration, // but that introduces numerical accuracy problems xx1 = seg->x0 + ((SplashCoord)y0 - seg->y0) * seg->dxdy; + int count = eo || (seg->flags & splashXPathFlip) ? 1 : -1; for (y = y0; y <= y1; ++y) { xx0 = xx1; xx1 = seg->x0 + ((SplashCoord)(y + 1) - seg->y0) * seg->dxdy; @@ -302,8 +304,8 @@ void SplashXPathScanner::computeIntersections() { } else if (xx1 > segXMax) { xx1 = segXMax; } - if (!addIntersection(segYMin, segYMax, seg->flags, y, - splashFloor(xx0), splashFloor(xx1))) + if (!addIntersection(segYMin, segYMax, y, splashFloor(xx0), + splashFloor(xx1), count)) break; } } @@ -317,8 +319,7 @@ void SplashXPathScanner::computeIntersections() { } GBool SplashXPathScanner::addIntersection(double segYMin, double segYMax, - Guint segFlags, - int y, int x0, int x1) { + int y, int x0, int x1, int count) { SplashIntersect intersect; intersect.y = y; if (x0 < x1) { @@ -328,11 +329,8 @@ GBool SplashXPathScanner::addIntersection(double segYMin, double segYMax, intersect.x0 = x1; intersect.x1 = x0; } - if (segYMin <= y && - (SplashCoord)y < segYMax && - !(segFlags & splashXPathHoriz)) { - intersect.count = eo ? 1 - : (segFlags & splashXPathFlip) ? 1 : -1; + if (segYMin <= y && (SplashCoord)y < segYMax) { + intersect.count = count; } else { intersect.count = 0; } diff --git a/splash/SplashXPathScanner.h b/splash/SplashXPathScanner.h index 66aeb190..979d7786 100644 --- a/splash/SplashXPathScanner.h +++ b/splash/SplashXPathScanner.h @@ -86,8 +86,7 @@ private: void computeIntersections(); GBool addIntersection(double segYMin, double segYMax, - Guint segFlags, - int y, int x0, int x1); + int y, int x0, int x1, int count); SplashXPath *xPath; GBool eo; _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
