Jump to content
We've recently updated our Privacy Statement, available here ×

jwhang

Members
  • Posts

    8
  • Joined

  • Last visited

jwhang's Achievements

Rookie

Rookie (2/14)

  • First Post Rare
  • Conversation Starter Rare
  • Week One Done
  • One Month Later
  • One Year In

Recent Badges

0

Reputation

  1. Attached to this wiki page is a zip file containing examples of configuration files and test resources to aid in iterating through cycles of running simple load tests and collecting performance information. There is also an example of a simple 2 node cluster using Apache's mod_jk software load balancer. The recorded demonstration within the attachment follows these steps: Load Test: 1. Run test against local Tomcat instance on port 8080 using JMeter. 2. Review downloaded report sample and generated CSV file. Capture Performance Snapshot and HeapDump: 1. Connect to server using VisualVM. 2. Start sampling, execute report, stop sampling. 3. Review result- search for postgres. 4. Capture heap dump and review within Visual VM. Load two Heap dumps and compare deltas: 1. Open using Eclipse with Memory Analyzer plugin. Connect to Apache running Mod JK load balancer with sticky sessions: 1. view 2x virtual machines running with one instance of tomcat each with different IP addresses. 2. invoke a report against same Apache instance from two different user sessions; observe load on alternating virtual machines. File Descriptions: perfRecording.avi - desktop recording of steps used in demo.jMeterTest.jmx - load this test after opening jMeter to run the same tests against the sample database which may be installed with the JasperServer installation.modified_apache_v_modjk_loadBalancer folder- files modified within the Apache front end with load balancer.modified_tomcat_node folder- modified file for each tomcat node with standard JasperServer installation.Related wiki article with more detail on capturing performance snapshots and heap dumps: https://community.jaspersoft.com/wiki/capturing-detailed-middle-tier-performance-and-state-information General wiki article about Performance Tips and Tricks: https://community.jaspersoft.com/wiki/tibco-jasperreports-server-performance-tips-and-tricks Links to resources used: http://www.eclipse.org - Java IDE used to load heap files.https://www.eclipse.org/mat/ - Memory analyzer plug in for Eclipse.https://docs.oracle.com/javase/8/docs/technotes/guides/visualvm/index.html - information about Visual VM. This utility is bundled with Oracle JDKs.http://jmeter.apache.org/ - Apache Jmeter used for load testing.https://httpd.apache.org/ - Apache web server used to host software load balancing using mod_jk extension for Apache. wikiarticle_performancefiles.zip
  2. In cases where a standard Jasper Report created using JRXML is being viewed through an embedded view within the context of another web application, it may be necessary to alter the hyperlink targets for drill through report links. In the case of JasperServer, drill through targets can take the form of <webapp name>/flow.html?... e.g. "/jasperserver-pro/flow.html?_flowId=viewReportFlow&reportUnit=%2Fpublic%2FSamples%2FReports%2FMyReport" when a preferred outcome may be to point to an entirely different application which passes this JasperServer specific information to a custom embedded view page (<some host>/<some custom webapp>...?jasperParams=<jasperserver specific parameters>) The core Jasper Reports library supports functionality to switch out logic for how hyperlinks should be interpreted when rendering the report (http://jasperreports.sourceforge.net/sample.reference/hyperlink/index.html). In the case of JasperServer, the ReportExecutionHyperlinkProducerFactory class (com.jaspersoft.jasperserver.war.action.hyperlinks.ReportExecutionHyperlinkProducerFactory) is invoked when assembling the final report URL. One way to modify the outcome is to alter the ReportExecutionHyperlinkProducerFactory's nested HyperlinkProducer.getHyperlink method definition. e.g: public String getHyperlink(JRPrintHyperlink hyperlink) { String uri = super.getHyperlink(hyperlink); //apply additional modifications to the URI here. return response != null ? response.encodeURL(uri) : uri; } For example, if a prefix string is combined with the existing uri, this will change the resulting URL used for the drill through hyperlinks.
  3. This page demonstrates some of the variation found in using different approaches to gauge time required to fetch result sets from databases. In some cases, utilities may return very inaccurate results for the purpose of timing retrieval of full results as their functionality isn't oriented toward capturing this type of information. Versions used in examples:Oracle Express 11.2Toad for Oracle: version 12.10SQL Squirrel open source 3.6JasperServer 6.3 A query returning five million rows from the SugarCRM sample database were used in all examples. Oracle Toad:Using the default settings, Oracle Toad returns information for retrieving only the first row of data when the query is executed normally. The utility goes on to fetch 500 rows. In the screen shot below, a recorded time of 15 milliseconds is reported for fetching the first row. It is possible to return the full result set by running the query as a script, but the operation doesn't appear optimized for large result sets. The screen capture below shows ~2.5 million rows marshalled after 20 minutes. SQL Squirrel:SQL Squirrel has an option in the upper right hand corner of it's UI to remove the row limit when fetching result sets. With this option disabled, the same query requires 67 seconds. Jasper Server:Using the sample simple domain which ships with Jasper Server 6.3, a derived table was added representing the same query used in the examples above. When opening a view containing fields from that table, the following timing of 19/62 seconds was captured in the adhoc cache for timings. Simple Java Program:Using a java program to open a connection and obtain and iterate through the results in a minimal fashion, the result set was obtained in 38 seconds. The source code is listed below the screen capture. SimpleQueryTiming.java source code:package com.tibco.analytics.jaspersoft.cs.example; import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.SQLException;import java.sql.Statement; public class SimpleQueryTiming { //jsw: change these values for different connections and queries. String driverClassName = "oracle.jdbc.driver.OracleDriver"; // e.g. oracle.jdbc.driver.OracleDriver String jdbcUrl = "jdbc:oracle:thin:@localhost:1521:xe"; //e.g. jdbc:oracle:thin:@localhost:1521:orcl String username = "sugarcrm"; String password = "sugarcrm"; String sqlString = "select a.name, a.industry, a.account_type, a.billing_address_state, a.billing_address_city, a.billing_address_street, o.id, s.id " + "from accounts a, opportunities o, sales_location s " + "where s.city = a.billing_address_city and ROWNUM <= 5000000"; boolean showOnlyTop10 = true; public static void main(String [] args){ logInfo("Simple Query Timing - starting execution."); long startTime = System.currentTimeMillis(); SimpleQueryTiming sqt = new SimpleQueryTiming(); sqt.execTest(); logInfo("Simple Query Timing completed in " + String.valueOf(System.currentTimeMillis() - startTime) + " ms."); } public void execTest(){ Connection conn = getConnection(); long startRsTime = System.currentTimeMillis(); try{ Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(sqlString); logInfo("Resultset handle obtained in " + String.valueOf(System.currentTimeMillis() - startRsTime) + " ms."); ResultSetMetaData rsmd = rs.getMetaData(); int colCount = rsmd.getColumnCount(); int rowCount = 0; long startOutputTime = System.currentTimeMillis(); while (rs.next()){ rowCount ++; if ((showOnlyTop10 == true)&&(rowCount>10)){ if (rowCount==11) logInfo("..."); for (int t=1; t<=colCount; t++){ Object obj = rs.getObject(t); //not doing anything with the value other than fetching. } } else { StringBuffer sb = new StringBuffer(); sb.append(rowCount); sb.append(") "); for (int t=1; t<=colCount; t++){ if (t>1) sb.append(","); sb.append(rs.getObject(t)); } logInfo(sb.toString()); } } logInfo("ResultSet contained " + rowCount + " rows."); logInfo("ResultSet traversed in " + String.valueOf(System.currentTimeMillis() - startOutputTime) + " ms."); rs.close(); st.close(); conn.close(); } catch (SQLException sqle){ logInfo(sqle.getMessage()); } } protected Connection getConnection(){ long startConnectionTime = System.currentTimeMillis(); Connection connection = null; try{ Class.forName(driverClassName); connection = DriverManager.getConnection( jdbcUrl, username, password); } catch (ClassNotFoundException cnfe){ logInfo(cnfe.getMessage()); } catch (SQLException sqle){ logInfo(sqle.getMessage()); } logInfo("Connection established in: " + String.valueOf(System.currentTimeMillis() - startConnectionTime) + " ms."); return connection; } protected static void logInfo(String info){ System.out.println(info); }}
  4. Scenario: A JasperServer instance is being used to store report output contents to the JasperServer repository. This is being done in some type of high volume scenario which the default EhCache configuration settings are not ideal for. Diagnosis: Set the Java virtual machine to create a heap dump when an out of memory exception occurs using the -XX:+HeapDumpOnOutOfMemoryError parameter. (documentation for Java 7 available here: https://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-VM/html/clopts.html)Once the .hprof heap file is generated, examine the contents using a heap analysis tool. Many tools exist, but one ships with the Java JDK named "VisualVM"; it will be part of that JDK distribution or is available as a standalone utility here (https://visualvm.java.net)If the contents of the EhCache consist mostly of output resources, and this represents the majority of the utilized heap space, it may be necessary to change the configuration settings.Possible solution: Modify the ehCache configuration for the "defaultRepoCache" settings in the two "ehcache_hibernate.xml" files located within .../WEB-INF and .../WEB-INF/classes. The default settings are: <cache name="defaultRepoCache" maxElementsInMemory="10000" eternal="false" overflowToDisk="false" timeToIdleSeconds="36000" timeToLiveSeconds="180000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" statistics="true"> </cache>They should be reduced to a point appropriate to the amount of data volume being added to clear the ehCache before the heap space is exhaused. For example, the following settings could be used to help verify if this is the source of an out of memory issue: <cache name="defaultRepoCache" maxElementsInMemory="10" eternal="false" overflowToDisk="false" timeToIdleSeconds="15" timeToLiveSeconds="60" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" statistics="true"> </cache>
  5. Enable JMX for the virtual machineLow level information about the state of the virtual machine running TIBCO. JasperReports® Server may be obtained by using Java's JMX functionality. To create a generic access point on the virtual machine for Tomcat, the following command line arguments may be added to the start of the virtual machine: In most network configurations, you will also need these two properties: *Note: This is not a complete list and will enable a connection without any authentication or transport layer security. Additional options may be found in the official documentation available on the Oracle website, e.g. http://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html If TCP port 9999 is already used by another service, please choose an unused port, ideally a non-privileged port number (greater than or equal to 1024), as privileged ports require root access. Please BE AWARE of the security implications, you will want to open the JMX port only to specific trusted hosts. The file to amend will differ depending on operating system and mode of startup: Windows OS service: An executable within the Apache Tomcat home/bin folder will need to be executed. The name of the executable should match the name of the service being used <service name>w.exeWindows batch file: Located within the Apache Tomcat home/bin folder is a file named "setenv.bat". The options may be added to the JAVA_OPTS variable.Linux: Located within the Apache Tomcat home/bin folder is a file named "setenv.sh". The options may be added to the JAVA_OPTS variable.The middle tier will need to be restarted for the change to take effect.Retrieving State InformationThe "VisualVM" utility may be used to connect to the server to obtain performance and heap information. This utility is bundled with Java Development Kits, but may also be downloaded from: https://visualvm.github.io/ After launching the application, a connection definition with the same port specified in the step above may be created by right clicking on a node in the Applications tab visible in the left pane. A connection may be established by double clicking on the newly created connection node: Obtain a Performance Snapshotclick on the "Sampler" tab and click on the Sample: [CPU] button on the upper left. This should produce a view similar to below: When done sampling, click the "Stop" button. Within the "CPU samples" tab, click on the "Snapshot" button which should add another tab similar to below: Click on the disk icon in the upper left of the frame to export the data, and save as an ".nps" file. Obtain a Heap DumpA heap dump may be obtained by right clicking on the JMX connection node in the Applications pane located on the left of the application, and selecting the heap dump option. Creating a heap dump will add a sub node which appears similar to the below: Right clicking on the heap dump node presents an option to "save as...". Save the file in .hprof format. Example of using VisualVMSee article with a demo of VisualVM and a screencast attached (bottom of page): Basic Tools for Performance Optimization. Using VisualVM in a Kubernetes clusterSee article: Connecting VisualVM to JMX on Kubernetes pod via SSH tunnel. The success of this setup will depend on your network configuration and permissions granted by your K8s admins.
  6. Changed Status from Feedback Requested to Resolved Hi Teodor, Thanks for the information; I definitely had not considered some of what you mentioned above. I request that you still keep some kind of injection point in mind as a possible future enhancement. The approach you outlined requires knowledge of this utility class by the report developer and modification of report template for the behavior to trigger. I can think of some use cases where you may want this modification asserted without having to modify existing reports, or applied in all cases regardless of whether a template correctly used the utility class. e.g. customer is acting as a service provider for other customers who can upload their own custom reports, and would like to imprint information about credentials and submitted report parameters under certain execution conditions.thanks,-Jun
×
×
  • Create New...