]> OCCT Git - occt.git/commitdiff
0025487: Extrema_GenExtPS needs to be optimized
authoraml <aml@opencascade.com>
Fri, 28 Nov 2014 10:19:30 +0000 (13:19 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 28 Nov 2014 10:49:44 +0000 (13:49 +0300)
Better caching and cashe usage in Extrema_GenExtPS.

Test-cases for issue #25487

Update of test-cases

src/Extrema/Extrema_GenExtPS.cdl
src/Extrema/Extrema_GenExtPS.cxx
src/Extrema/Extrema_POnSurf.cdl
src/Extrema/Extrema_POnSurf.lxx
tests/bugs/moddata_3/bug25487_1 [new file with mode: 0644]
tests/bugs/moddata_3/bug25487_2 [new file with mode: 0644]

index f2f8557b1c3eda4bd9bc246d5d566c867817b2ab..ca3e1dd5621b4737ddeb96639335f57df984cb6d 100644 (file)
@@ -144,6 +144,17 @@ is
     BuildGrid(me: in out; thePoint: Pnt from gp) is private;
        ---Purpose: Creation of grid of parametric points
 
+    ComputeEdgeParameters(me: in out;
+                          IsUEdge    : Boolean;
+                          theParam0  : POnSurfParams from Extrema;
+                          theParam1  : POnSurfParams from Extrema;
+                          thePoints  : Pnt from gp;
+                          theDiffTol : Real) returns POnSurfParams from Extrema
+    is private;
+      ---Purpose: Compute new edge parameters.
+      ---C++: return const &
+
+
 fields
     myDone    : Boolean;
     myInit    : Boolean;
@@ -164,6 +175,9 @@ fields
     myAlgo    : ExtAlgo from Extrema;
     myUParams : HArray1OfReal from TColStd;
     myVParams : HArray1OfReal from TColStd;
-    myFacePntParams : HArray2OfPOnSurfParams from Extrema;
+    myFacePntParams  : HArray2OfPOnSurfParams from Extrema;
+    myUEdgePntParams : HArray2OfPOnSurfParams from Extrema;
+    myVEdgePntParams : HArray2OfPOnSurfParams from Extrema;
+    myGridParam      : POnSurfParams from Extrema;
 
 end GenExtPS;
index d8af103d3841f7425a5d08db8028e59967a9959b..dc281f3f3b836057a0fefc840d147fc0a05bd405 100644 (file)
@@ -169,70 +169,6 @@ Standard_Boolean Bnd_SphereUBTreeSelectorMax::Accept(const Standard_Integer& the
   return Standard_False;
 }
 
-/*
- * This function computes the point on surface parameters on edge.
- * if it coincides with theParam0 or theParam1, it is returned.
- */
-static Extrema_POnSurfParams ComputeEdgeParameters
-      (const Standard_Boolean       IsUEdge,
-       const Extrema_POnSurfParams &theParam0,
-       const Extrema_POnSurfParams &theParam1,
-       const Adaptor3d_SurfacePtr  &theSurf,
-       const gp_Pnt                &thePoint,
-       const Standard_Real          theDiffTol)
-{
-  const Standard_Real aSqrDist01 =
-    theParam0.Value().SquareDistance(theParam1.Value());
-
-  if (aSqrDist01 <= theDiffTol) {
-    // The points are confused. Get the first point and change its type.
-    return theParam0;
-  } else {
-    const Standard_Real aDiffDist =
-      Abs(theParam0.GetSqrDistance() - theParam1.GetSqrDistance());
-
-    if (aDiffDist >= aSqrDist01 - theDiffTol) {
-      // The shortest distance is one of the nodes.
-      if (theParam0.GetSqrDistance() > theParam1.GetSqrDistance()) {
-        // The shortest distance is the point 1.
-        return theParam1;
-      } else {
-        // The shortest distance is the point 0.
-        return theParam0;
-      }
-    } else {
-      // The shortest distance is inside the edge.
-      gp_XYZ aPoP(thePoint.XYZ().Subtracted(theParam0.Value().XYZ()));
-      gp_XYZ aPoP1(theParam1.Value().XYZ().Subtracted(theParam0.Value().XYZ()));
-      Standard_Real aRatio = aPoP.Dot(aPoP1)/aSqrDist01;
-      Standard_Real aU[2];
-      Standard_Real aV[2];
-
-      theParam0.Parameter(aU[0], aV[0]);
-      theParam1.Parameter(aU[1], aV[1]);
-  
-      Standard_Real aUPar = aU[0];
-      Standard_Real aVPar = aV[0];
-
-      if (IsUEdge) {
-        aUPar += aRatio*(aU[1] - aU[0]);
-      } else {
-        aVPar += aRatio*(aV[1] - aV[0]);
-      }
-
-      Extrema_POnSurfParams aParam(aUPar, aVPar, theSurf->Value(aUPar, aVPar));
-      Standard_Integer anIndices[2];
-
-      theParam0.GetIndices(anIndices[0], anIndices[1]);
-      aParam.SetElementType(IsUEdge ? Extrema_UIsoEdge : Extrema_VIsoEdge);
-      aParam.SetSqrDistance(thePoint.SquareDistance(aParam.Value()));
-      aParam.SetIndices(anIndices[0], anIndices[1]);
-
-      return aParam;
-    }
-  }
-}
-
 //=============================================================================
 
 /*-----------------------------------------------------------------------------
@@ -288,32 +224,36 @@ Extrema_GenExtPS::Extrema_GenExtPS()
 
 
 Extrema_GenExtPS::Extrema_GenExtPS (const gp_Pnt&          P,
-                             const Adaptor3d_Surface& S,
-                             const Standard_Integer NbU, 
-                             const Standard_Integer NbV,
-                             const Standard_Real    TolU, 
-                              const Standard_Real    TolV,
-                              const Extrema_ExtFlag F,
-                              const Extrema_ExtAlgo A) 
-  : myF (P,S), myFlag(F), myAlgo(A)
+                                    const Adaptor3d_Surface& S,
+                                    const Standard_Integer NbU, 
+                                    const Standard_Integer NbV,
+                                    const Standard_Real    TolU, 
+                                    const Standard_Real    TolV,
+                                    const Extrema_ExtFlag F,
+                                    const Extrema_ExtAlgo A) 
+: myF (P,S),
+  myFlag(F),
+  myAlgo(A)
 {
   Initialize(S, NbU, NbV, TolU, TolV);
   Perform(P);
 }
 
 Extrema_GenExtPS::Extrema_GenExtPS (const gp_Pnt&          P,
-                             const Adaptor3d_Surface& S,
-                             const Standard_Integer NbU, 
-                             const Standard_Integer NbV,
-                             const Standard_Real    Umin,
-                             const Standard_Real    Usup,
-                             const Standard_Real    Vmin,
-                             const Standard_Real    Vsup,
-                             const Standard_Real    TolU, 
-                              const Standard_Real    TolV,
-                              const Extrema_ExtFlag F,
-                              const Extrema_ExtAlgo A) 
-  : myF (P,S), myFlag(F), myAlgo(A)
+                                    const Adaptor3d_Surface& S,
+                                    const Standard_Integer NbU, 
+                                    const Standard_Integer NbV,
+                                    const Standard_Real    Umin,
+                                    const Standard_Real    Usup,
+                                    const Standard_Real    Vmin,
+                                    const Standard_Real    Vsup,
+                                    const Standard_Real    TolU, 
+                                    const Standard_Real    TolV,
+                                    const Extrema_ExtFlag F,
+                                    const Extrema_ExtAlgo A) 
+: myF (P,S),
+  myFlag(F),
+  myAlgo(A)
 {
   Initialize(S, NbU, NbV, Umin, Usup, Vmin, Vsup, TolU, TolV);
   Perform(P);
@@ -321,10 +261,10 @@ Extrema_GenExtPS::Extrema_GenExtPS (const gp_Pnt&          P,
 
 
 void Extrema_GenExtPS::Initialize(const Adaptor3d_Surface& S,
-                                 const Standard_Integer NbU, 
-                                 const Standard_Integer NbV,
-                                 const Standard_Real    TolU, 
-                                 const Standard_Real    TolV)
+                                  const Standard_Integer NbU, 
+                                  const Standard_Integer NbV,
+                                  const Standard_Real    TolU, 
+                                  const Standard_Real    TolV)
 {
   myumin = S.FirstUParameter();
   myusup = S.LastUParameter();
@@ -335,14 +275,14 @@ void Extrema_GenExtPS::Initialize(const Adaptor3d_Surface& S,
 
 
 void Extrema_GenExtPS::Initialize(const Adaptor3d_Surface& S,
-                                 const Standard_Integer NbU, 
-                                 const Standard_Integer NbV,
-                                 const Standard_Real    Umin,
-                                 const Standard_Real    Usup,
-                                 const Standard_Real    Vmin,
-                                 const Standard_Real    Vsup,
-                                 const Standard_Real    TolU, 
-                                 const Standard_Real    TolV)
+                                  const Standard_Integer NbU, 
+                                  const Standard_Integer NbV,
+                                  const Standard_Real    Umin,
+                                  const Standard_Real    Usup,
+                                  const Standard_Real    Vmin,
+                                  const Standard_Real    Vsup,
+                                  const Standard_Real    TolU, 
+                                  const Standard_Real    TolV)
 {
   myS = (Adaptor3d_SurfacePtr)&S;
   myusample = NbU;
@@ -486,6 +426,80 @@ void Extrema_GenExtPS::GetGridPoints( const Adaptor3d_Surface& theSurf)
   
 }
 
+/*
+ * This function computes the point on surface parameters on edge.
+ * if it coincides with theParam0 or theParam1, it is returned.
+ */
+const Extrema_POnSurfParams& Extrema_GenExtPS::ComputeEdgeParameters
+      (const Standard_Boolean       IsUEdge,
+       const Extrema_POnSurfParams &theParam0,
+       const Extrema_POnSurfParams &theParam1,
+       const gp_Pnt                &thePoint,
+       const Standard_Real          theDiffTol)
+{
+  const Standard_Real aSqrDist01 =
+    theParam0.Value().SquareDistance(theParam1.Value());
+
+  if (aSqrDist01 <= theDiffTol)
+  {
+    // The points are confused. Get the first point and change its type.
+    return theParam0;
+  }
+  else
+  {
+    const Standard_Real aDiffDist =
+      Abs(theParam0.GetSqrDistance() - theParam1.GetSqrDistance());
+
+    if (aDiffDist >= aSqrDist01 - theDiffTol)
+    {
+      // The shortest distance is one of the nodes.
+      if (theParam0.GetSqrDistance() > theParam1.GetSqrDistance())
+      {
+        // The shortest distance is the point 1.
+        return theParam1;
+      }
+      else
+      {
+        // The shortest distance is the point 0.
+        return theParam0;
+      }
+    }
+    else
+    {
+      // The shortest distance is inside the edge.
+      gp_XYZ aPoP(thePoint.XYZ().Subtracted(theParam0.Value().XYZ()));
+      gp_XYZ aPoP1(theParam1.Value().XYZ().Subtracted(theParam0.Value().XYZ()));
+      Standard_Real aRatio = aPoP.Dot(aPoP1)/aSqrDist01;
+      Standard_Real aU[2];
+      Standard_Real aV[2];
+
+      theParam0.Parameter(aU[0], aV[0]);
+      theParam1.Parameter(aU[1], aV[1]);
+
+      Standard_Real aUPar = aU[0];
+      Standard_Real aVPar = aV[0];
+
+      if (IsUEdge)
+      {
+        aUPar += aRatio*(aU[1] - aU[0]);
+      }
+      else
+      {
+        aVPar += aRatio*(aV[1] - aV[0]);
+      }
+
+      myGridParam.SetParameters(aUPar, aVPar, myS->Value(aUPar, aVPar));
+      Standard_Integer anIndices[2];
+
+      theParam0.GetIndices(anIndices[0], anIndices[1]);
+      myGridParam.SetElementType(IsUEdge ? Extrema_UIsoEdge : Extrema_VIsoEdge);
+      myGridParam.SetSqrDistance(thePoint.SquareDistance(myGridParam.Value()));
+      myGridParam.SetIndices(anIndices[0], anIndices[1]);
+      return myGridParam;
+    }
+  }
+}
+
 void Extrema_GenExtPS::BuildGrid(const gp_Pnt &thePoint)
 {
   Standard_Integer NoU, NoV;
@@ -541,6 +555,14 @@ void Extrema_GenExtPS::BuildGrid(const gp_Pnt &thePoint)
       }
     }
 
+    myFacePntParams = 
+      new Extrema_HArray2OfPOnSurfParams(0, myusample, 0, myvsample);
+
+    myUEdgePntParams =
+      new Extrema_HArray2OfPOnSurfParams(1, myusample - 1, 1, myvsample);
+    myVEdgePntParams =
+      new Extrema_HArray2OfPOnSurfParams(1, myusample, 1, myvsample - 1);
+
     // Fill boundary with negative square distance.
     // It is used for computation of Maximum.
     for (NoV = 0; NoV <= myvsample + 1; NoV++) {
@@ -576,31 +598,28 @@ void Extrema_GenExtPS::BuildGrid(const gp_Pnt &thePoint)
     // Step 2. Compute distances to edges.
     // Assume UEdge(i, j) = { Point(i, j); Point(i + 1, j    ) }
     // Assume VEdge(i, j) = { Point(i, j); Point(i,     j + 1) }
-    Handle(Extrema_HArray2OfPOnSurfParams) aUEdgePntParams =
-          new Extrema_HArray2OfPOnSurfParams(1, myusample - 1, 1, myvsample);
-    Handle(Extrema_HArray2OfPOnSurfParams) aVEdgePntParams =
-          new Extrema_HArray2OfPOnSurfParams(1, myusample, 1, myvsample - 1);
-
-    for ( NoU = 1 ; NoU <= myusample; NoU++ ) {
-      for ( NoV = 1 ; NoV <= myvsample; NoV++) {
+    for ( NoU = 1 ; NoU <= myusample; NoU++ ) 
+    {
+      for ( NoV = 1 ; NoV <= myvsample; NoV++)
+      {
         const Extrema_POnSurfParams &aParam0 = myPoints->Value(NoU, NoV);
 
-        if (NoU < myusample) {
+        if (NoU < myusample)
+        {
           // Compute parameters to UEdge.
           const Extrema_POnSurfParams &aParam1 = myPoints->Value(NoU + 1, NoV);
-          Extrema_POnSurfParams aUEdgeParam = ComputeEdgeParameters
-              (Standard_True, aParam0, aParam1, myS, thePoint, aDiffTol);
+          const Extrema_POnSurfParams &anEdgeParam = ComputeEdgeParameters(Standard_True, aParam0, aParam1, thePoint, aDiffTol);
 
-          aUEdgePntParams->SetValue(NoU, NoV, aUEdgeParam);
+          myUEdgePntParams->SetValue(NoU, NoV, anEdgeParam);
         }
 
-        if (NoV < myvsample) {
+        if (NoV < myvsample)
+        {
           // Compute parameters to VEdge.
           const Extrema_POnSurfParams &aParam1 = myPoints->Value(NoU, NoV + 1);
-          Extrema_POnSurfParams aVEdgeParam = ComputeEdgeParameters
-              (Standard_False, aParam0, aParam1, myS, thePoint, aDiffTol);
+          const Extrema_POnSurfParams &anEdgeParam = ComputeEdgeParameters(Standard_False, aParam0, aParam1, thePoint, aDiffTol);
 
-          aVEdgePntParams->SetValue(NoU, NoV, aVEdgeParam);
+          myVEdgePntParams->SetValue(NoU, NoV, anEdgeParam);
         }
       }
     }
@@ -610,18 +629,16 @@ void Extrema_GenExtPS::BuildGrid(const gp_Pnt &thePoint)
     // { Point(i, j); Point(i + 1, j); Point(i + 1, j + 1); Point(i, j + 1) }
     //   Or
     // { UEdge(i, j); VEdge(i + 1, j); UEdge(i, j + 1); VEdge(i, j) }
-    myFacePntParams = 
-          new Extrema_HArray2OfPOnSurfParams(0, myusample, 0, myvsample);
     Standard_Real aSqrDist01;
     Standard_Real aDiffDist;
     Standard_Boolean isOut;
 
     for ( NoU = 1 ; NoU < myusample; NoU++ ) {
       for ( NoV = 1 ; NoV < myvsample; NoV++) {
-        const Extrema_POnSurfParams &aUE0 = aUEdgePntParams->Value(NoU, NoV);
-        const Extrema_POnSurfParams &aUE1 = aUEdgePntParams->Value(NoU, NoV+1);
-        const Extrema_POnSurfParams &aVE0 = aVEdgePntParams->Value(NoU, NoV);
-        const Extrema_POnSurfParams &aVE1 = aVEdgePntParams->Value(NoU+1, NoV);
+        const Extrema_POnSurfParams &aUE0 = myUEdgePntParams->Value(NoU, NoV);
+        const Extrema_POnSurfParams &aUE1 = myUEdgePntParams->Value(NoU, NoV+1);
+        const Extrema_POnSurfParams &aVE0 = myVEdgePntParams->Value(NoU, NoV);
+        const Extrema_POnSurfParams &aVE1 = myVEdgePntParams->Value(NoU+1, NoV);
 
         aSqrDist01 = aUE0.Value().SquareDistance(aUE1.Value());
         aDiffDist = Abs(aUE0.GetSqrDistance() - aUE1.GetSqrDistance());
@@ -689,13 +706,7 @@ void Extrema_GenExtPS::BuildGrid(const gp_Pnt &thePoint)
   }
 }
 
-/*
-a- Constitution of the table of distances (TbDist(0,myusample+1,0,myvsample+1)):
-   ---------------------------------------------------------------
-*/
-
 // Parameterisation of the sample
-
 void Extrema_GenExtPS::BuildTree()
 {
   // if tree already exists, assume it is already correctly filled
index 89d4819ee1ed14a30328fc84d8fdd09c76221696..a1f68693de5af8d075f58e40aa7ec4760d92342a 100644 (file)
@@ -35,6 +35,13 @@ is
        ---C++: inline
        is static;
 
+    SetParameters(me: in out;
+                  theU, theV: Real from Standard;
+                  thePnt: Pnt from gp);
+      ---Purpose: Sets the params of current POnSurf instance.
+      --          (e.g. to the point to be projected).
+      ---C++: inline
+
     Parameter (me; U,V: out Real) 
        ---Purpose: Returns the parameter values on the surface.
        ---C++: inline
index 9215d53198b716e5de0a4fce5c0746e5f703f8ba..17c6e630cca37f0ecc4df78f903c474b4ce41126 100644 (file)
@@ -16,11 +16,22 @@ inline Extrema_POnSurf::Extrema_POnSurf () {}
 
 inline Extrema_POnSurf::Extrema_POnSurf (const Standard_Real U,
                                          const Standard_Real V,
-                                         const gp_Pnt& P) :
-    myU (U), myV (V), myP (P)
+                                         const gp_Pnt& P)
+: myU (U),
+  myV (V),
+  myP (P)
 {
 }
 
+inline void Extrema_POnSurf::SetParameters (const Standard_Real U,
+                                            const Standard_Real V,
+                                            const gp_Pnt& P)
+{
+  myU = U;
+  myV = V;
+  myP = P;
+}
+
 inline void Extrema_POnSurf::Parameter ( Standard_Real& U, Standard_Real& V) const
 {
   U = myU;
diff --git a/tests/bugs/moddata_3/bug25487_1 b/tests/bugs/moddata_3/bug25487_1
new file mode 100644 (file)
index 0000000..a6eb562
--- /dev/null
@@ -0,0 +1,73 @@
+puts "========"
+puts "OCC25487"
+puts "========"
+puts ""
+##########################################
+# Extrema_GenExtPS needs to be optimized
+##########################################
+
+pload DATAEXCHANGEKERNEL
+
+# Restore testing shape and get timing characteristics for operation stepread
+dchrono perf_h reset
+dchrono perf_h start
+stepread [locate_data_file OCC25487_LP1.stp] a *
+dchrono perf_h stop
+
+# Get elapsed time for operation stepread
+set chrono_info [dchrono perf_h show]
+regexp {CPU user time: ([-0-9.+eE]+) seconds} $chrono_info full CPU_time
+puts "Elapsed time is: $CPU_time"
+
+# Check current OS
+set currentOS $tcl_platform(os)
+
+# Check prformance on Windows
+if {[string compare $currentOS "Windows NT"] == 0} {
+  if {[regexp {Debug mode} [dversion]]} {
+    # DEBUG mode
+    # initial CPU_time for WINDOWS in DEBUG mode is 410 ((186+19)*2) sec
+    puts "Checking WINDOWS performance in debug mode..."
+    if {$CPU_time > 410.} {
+      puts "ERROR: OCC25487 is reproduced."
+      puts "       Low performance: $CPU_time (but should be less than 410 sec)"
+    } else {
+      puts "Done!"
+    }
+  } else {
+    # OPTIMIZE mode
+    # initial CPU_time for WINDOWS in OPTIMIZE mode is 205 (186+19) sec
+    puts "Checking WINDOWS performance in optimize mode..."
+    if {$CPU_time > 205.} {
+      puts "ERROR: OCC25487 is reproduced."
+      puts "       Low performance: $CPU_time (but should be less than 205 sec)"
+    } else {
+      puts "Done!"
+    }
+  }
+}
+
+# Check performance on Linux
+if {[string compare $currentOS "Linux"] == 0} {
+  if {[regexp {Debug mode} [dversion]]} {
+    # DEBUG mode
+    # initial CPU_time for LINUX in DEBUG mode is 292 ((132+14)*2) sec
+    puts "Checking LINUX performance in debug mode..."
+    if {$CPU_time > 292.} {
+      puts "ERROR: OCC25487 is reproduced."
+      puts "       Low performance: $CPU_time (but should be less than 292 sec)"
+    } else {
+      puts "Done!"
+    }
+  } else {
+    # OPTIMIZE mode
+    # initial CPU_time for LINUX in OPTIMIZE mode is 146 (132+14) sec
+    puts "Checking LINUX performance in optimize mode..."
+    if {$CPU_time > 146.} {
+      puts "ERROR: OCC25487 is reproduced."
+      puts "       Low performance: $CPU_time (but should be less than 146 sec)"
+    } else {
+      puts "Done!"
+    }
+  }
+}
diff --git a/tests/bugs/moddata_3/bug25487_2 b/tests/bugs/moddata_3/bug25487_2
new file mode 100644 (file)
index 0000000..41f8cac
--- /dev/null
@@ -0,0 +1,73 @@
+puts "========"
+puts "OCC25487"
+puts "========"
+puts ""
+##########################################
+# Extrema_GenExtPS needs to be optimized
+##########################################
+
+pload DATAEXCHANGEKERNEL
+
+# Restore testing shape and get timing characteristics for operation stepread
+dchrono perf_h reset
+dchrono perf_h start
+stepread [locate_data_file OCC25487_LP2.stp] a *
+dchrono perf_h stop
+
+# Get elapsed time for operation stepread
+set chrono_info [dchrono perf_h show]
+regexp {CPU user time: ([-0-9.+eE]+) seconds} $chrono_info full CPU_time
+puts "Elapsed time is: $CPU_time"
+
+# Check current OS
+set currentOS $tcl_platform(os)
+
+# Check prformance on Windows
+if {[string compare $currentOS "Windows NT"] == 0} {
+  if {[regexp {Debug mode} [dversion]]} {
+    # DEBUG mode
+    # initial CPU_time for WINDOWS in DEBUG mode is 1208 ((549+55)*2) sec
+    puts "Checking WINDOWS performance in debug mode..."
+    if {$CPU_time > 1208.} {
+      puts "ERROR: OCC25487 is reproduced."
+      puts "       Low performance: $CPU_time (but should be less than 1208 sec)"
+    } else {
+      puts "Done!"
+    }
+  } else {
+    # OPTIMIZE mode
+    # initial CPU_time for WINDOWS in OPTIMIZE mode is 604 (549+55) sec
+    puts "Checking WINDOWS performance in optimize mode..."
+    if {$CPU_time > 604.} {
+      puts "ERROR: OCC25487 is reproduced."
+      puts "       Low performance: $CPU_time (but should be less than 604 sec)"
+    } else {
+      puts "Done!"
+    }
+  }
+}
+
+# Check performance on Linux
+if {[string compare $currentOS "Linux"] == 0} {
+  if {[regexp {Debug mode} [dversion]]} {
+    # DEBUG mode
+    # initial CPU_time for LINUX in DEBUG mode is 902 ((410+41)*2) sec
+    puts "Checking LINUX performance in debug mode..."
+    if {$CPU_time > 902.} {
+      puts "ERROR: OCC25487 is reproduced."
+      puts "       Low performance: $CPU_time (but should be less than 902 sec)"
+    } else {
+      puts "Done!"
+    }
+  } else {
+    # OPTIMIZE mode
+    # initial CPU_time for LINUX in OPTIMIZE mode is 451 (410+41) sec
+    puts "Checking LINUX performance in optimize mode..."
+    if {$CPU_time > 451.} {
+      puts "ERROR: OCC25487 is reproduced."
+      puts "       Low performance: $CPU_time (but should be less than 451 sec)"
+    } else {
+      puts "Done!"
+    }
+  }
+}