You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ce...@apache.org on 2020/12/29 19:29:22 UTC

svn commit: r1884917 - in /poi/trunk: src/java/org/apache/poi/hssf/usermodel/HSSFOptimiser.java test-data/spreadsheet/styles-3563.xls

Author: centic
Date: Tue Dec 29 19:29:22 2020
New Revision: 1884917

URL: http://svn.apache.org/viewvc?rev=1884917&view=rev
Log:
Improve the speed of the styles-optimiser when there are many styles in a Workbook

Profiling showed that the call to isUserDefined() took most of the time,
so we now fetch this only once for each style and remember the result and
use it in the inner loop.

The attached sample-file took aprox. 1m30s on a decent machine, now it is down
to around 2s.

Added:
    poi/trunk/test-data/spreadsheet/styles-3563.xls
Modified:
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFOptimiser.java

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFOptimiser.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFOptimiser.java?rev=1884917&r1=1884916&r2=1884917&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFOptimiser.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFOptimiser.java Tue Dec 29 19:29:22 2020
@@ -30,7 +30,7 @@ import org.apache.poi.ss.usermodel.Row;
  * Excel can get cranky if you give it files containing too
  *  many (especially duplicate) objects, and this class can
  *  help to avoid those.
- * In general, it's much better to make sure you don't 
+ * In general, it's much better to make sure you don't
  *  duplicate the objects in your code, as this is likely
  *  to be much faster than creating lots and lots of
  *  excel objects+records, only to optimise them down to
@@ -52,27 +52,27 @@ public class HSSFOptimiser {
 	public static void optimiseFonts(HSSFWorkbook workbook) {
 		// Where each font has ended up, and if we need to
 		//  delete the record for it. Start off with no change
-		short[] newPos = 
+		short[] newPos =
 			new short[workbook.getWorkbook().getNumberOfFontRecords()+1];
 		boolean[] zapRecords = new boolean[newPos.length];
 		for(int i=0; i<newPos.length; i++) {
 			newPos[i] = (short)i;
 			zapRecords[i] = false;
 		}
-		
+
 		// Get each font record, so we can do deletes
 		//  without getting confused
-		FontRecord[] frecs = new FontRecord[newPos.length]; 
+		FontRecord[] frecs = new FontRecord[newPos.length];
 		for(int i=0; i<newPos.length; i++) {
 			// There is no 4!
 			if(i == 4) continue;
-			
+
 			frecs[i] = workbook.getWorkbook().getFontRecordAt(i);
 		}
-		
+
 		// Loop over each font, seeing if it is the same
 		//  as an earlier one. If it is, point users of the
-		//  later duplicate copy to the earlier one, and 
+		//  later duplicate copy to the earlier one, and
 		//  mark the later one as needing deleting
 		// Note - don't change built in fonts (those before 5)
 		for(int i=5; i<newPos.length; i++) {
@@ -81,20 +81,20 @@ public class HSSFOptimiser {
 			int earlierDuplicate = -1;
 			for(int j=0; j<i && earlierDuplicate == -1; j++) {
 				if(j == 4) continue;
-				
+
 				FontRecord frCheck = workbook.getWorkbook().getFontRecordAt(j);
 				if(frCheck.sameProperties(frecs[i])) {
 					earlierDuplicate = j;
 				}
 			}
-			
+
 			// If we got a duplicate, mark it as such
 			if(earlierDuplicate != -1) {
 				newPos[i] = (short)earlierDuplicate;
 				zapRecords[i] = true;
 			}
 		}
-		
+
 		// Update the new positions based on
 		//  deletes that have occurred between
 		//  the start and them
@@ -107,11 +107,11 @@ public class HSSFOptimiser {
 			for(int j=0; j<preDeletePos; j++) {
 				if(zapRecords[j]) newPosition--;
 			}
-			
+
 			// Update the new position
 			newPos[i] = newPosition;
 		}
-		
+
 		// Zap the un-needed user font records
 		for(int i=5; i<newPos.length; i++) {
 			if(zapRecords[i]) {
@@ -120,12 +120,12 @@ public class HSSFOptimiser {
 				);
 			}
 		}
-		
+
 		// Tell HSSFWorkbook that it needs to
 		//  re-start its HSSFFontCache
 		workbook.resetFontCache();
-		
-		// Update the cell styles to point at the 
+
+		// Update the cell styles to point at the
 		//  new locations of the fonts
 		for(int i=0; i<workbook.getWorkbook().getNumExFormats(); i++) {
 			ExtendedFormatRecord xfr = workbook.getWorkbook().getExFormatAt(i);
@@ -133,7 +133,7 @@ public class HSSFOptimiser {
 					newPos[ xfr.getFontIndex() ]
 			);
 		}
-		
+
 		// Update the rich text strings to point at
 		//  the new locations of the fonts
 		// Remember that one underlying unicode string
@@ -146,7 +146,7 @@ public class HSSFOptimiser {
 					if(cell.getCellType() == CellType.STRING) {
 						HSSFRichTextString rtr = (HSSFRichTextString)cell.getRichStringCellValue();
 						UnicodeString u = rtr.getRawUnicodeString();
-						
+
 						// Have we done this string already?
 						if(! doneUnicodeStrings.contains(u)) {
 							// Update for each new position
@@ -155,7 +155,7 @@ public class HSSFOptimiser {
 									u.swapFontUse(i, newPos[i]);
 								}
 							}
-							
+
 							// Mark as done
 							doneUnicodeStrings.add(u);
 						}
@@ -164,7 +164,7 @@ public class HSSFOptimiser {
 			}
 		}
 	}
-	
+
    /**
     * Goes through the Wokrbook, optimising the cell styles
     *  by removing duplicate ones, and ones that aren't used.
@@ -178,17 +178,24 @@ public class HSSFOptimiser {
        short[] newPos = new short[workbook.getWorkbook().getNumExFormats()];
        boolean[] isUsed = new boolean[newPos.length];
        boolean[] zapRecords = new boolean[newPos.length];
+
+	   // to speed up the optimisation for workbooks with a large number of
+	   // styles we perform the isUserDefined() check only once as it is
+	   // costly according to some profiling
+	   boolean[] userDefined = new boolean[newPos.length];
+
+	   // Get each style record, so we can do deletes
+	   //  without getting confused
+	   ExtendedFormatRecord[] xfrs = new ExtendedFormatRecord[newPos.length];
+
        for(int i=0; i<newPos.length; i++) {
            isUsed[i] = false;
            newPos[i] = (short)i;
            zapRecords[i] = false;
-       }
 
-       // Get each style record, so we can do deletes
-       //  without getting confused
-       ExtendedFormatRecord[] xfrs = new ExtendedFormatRecord[newPos.length];
-       for(int i=0; i<newPos.length; i++) {
-           xfrs[i] = workbook.getWorkbook().getExFormatAt(i);
+		   userDefined[i] = isUserDefined(workbook, i);
+
+		   xfrs[i] = workbook.getWorkbook().getExFormatAt(i);
        }
 
 	   // Loop over each style, seeing if it is the same
@@ -200,12 +207,13 @@ public class HSSFOptimiser {
 		   // Check this one for being a duplicate
 		   //  of an earlier one
 		   int earlierDuplicate = -1;
-		   for (int j = 0; j < i && earlierDuplicate == -1; j++) {
+		   for (int j = 0; j < i; j++) {
 			   ExtendedFormatRecord xfCheck = workbook.getWorkbook().getExFormatAt(j);
 			   if (xfCheck.equals(xfrs[i]) &&
-					   // newer duplicate user defined styles
-					   !isUserDefined(workbook, j)) {
+					   // never duplicate user defined styles
+					   !userDefined[j]) {
 				   earlierDuplicate = j;
+				   break;
 			   }
 		   }
 

Added: poi/trunk/test-data/spreadsheet/styles-3563.xls
URL: http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/styles-3563.xls?rev=1884917&view=auto
==============================================================================
Binary files poi/trunk/test-data/spreadsheet/styles-3563.xls (added) and poi/trunk/test-data/spreadsheet/styles-3563.xls Tue Dec 29 19:29:22 2020 differ



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org