Generating SSRS through website, fine -- through Code, out of Memory - c#

I have a report that is 68,000 pages plus that needs to be generated in PDF. (I put the comma in so you knew it wasn’t a typo :)
And this actually works fine if I generate it through the Website/WebService of SSRS.
It takes a little over a minute and generates the first page. During this time Server CPU goes to 100% and Memory to 2GB. After the first page is generated both CPU and Memory drop down to their pre-report state. Now if I choose to export to PDF. CPU on the Server goes to 100 but Memory does not jump significantly maybe .05GB (50 MB) as the pdf is being generated. This takes about 10-15 Minutes.
Now if I use the Render method in code
rs.Render(Me.ReportName, Me.ContentType, Nothing, Nothing, ....
I set the rs.Timeout to 1800000 //(30 minutes). CPU and Memory on the server spikes and about after 10 Minutes I get a out of Memory Exception. I believe from the server and not the host machine with the calling code (a web service).
Now I did notice when the PDF gets render through the SSRS website it creates a new URL with the parameters
ReportSession=gvrjxt4504wtpkiydu0o51fo
ControlID=5754f0889fb34bea80e7b5e97c120cfd
Culture=1033
UICulture=9
ReportStack=1
OpType=Export
FileName=Invoice+Session+Register+Batch
ContentDisposition=OnlyHtmlInline
Format=PDF
Now it is my belief that it is this ReportSession or ControlId that makes the PDF generation not take up so much memory.
Either way my question is how can I mimic through code the behavior that the Website is showing?
I about to look into LoadReport method and also NULL is one of the content types you can pass to the render method. But I cannot find an example nor and explanation of what it does.
So before I go down all these rabbit holes, has anyone else done something like this or encounter a project like this?
Background:If I generate the report one page at a time it took 9.5 hours to run and generate all the PDFs. I was really excited when I could generate the whole report in 10 minutes and use PDFSharp to split the report. Now I most likely can generate 10,000 or 20,000 at a time but it really fustrates me when a method works but I cannot duplicate it in code.

Related

Asp.Net Page takes a long time to load

I am experiencing a strange issue where some sections of the Asp.Net(aspx pages) site are taking a long time to load than others. After going through all the stages of the cycle and getting the page and the master page processed after it exits the code it takes about 20 seconds for the application to get to the Application_EndRequest event. I am not sure what it is doing for those 20 seconds. Since I know what I am telling is not specific I am just asking for suggestions on how to debug the issue or any helpful tips I can follow to see what's the holdup.
Thanks
You can try to use a code profiler. I used Stackify's Prefix in a similar situation. It's a free download.

Webform ReportViewer Service Unavailable, timeouts and performance issues

We are currently using ReportViewer control embedded in an aspx file to render RDLC files for an MVC Web Application. The data is fetched from an SQL Server using nhibernate, the ReportViewer is running in Local Processing mode. The various reports contain calculations within the RDLC including sums, counts and grouping.
We are finding the reports using this method run terribly slowly, usually causing the web server to display the Service 'Unavailable Error'.
It appears that the live servers do not have enough resources to run these reports, and even in an environment where the servers have much more memory and CPU speed, while the reports do not time out, they take a very long time to render even a single report.
Does anyone have recommendations on this matter. How can we reduce the amount of processing time for these reports?
From observing the resource usage, the calculations carried out internally by report viewer on the data are taking a great deal of time. As an example of the data we are looking at about 3000 individual reports, using over 40000 records to calculate from.

10,000 + records on html to render quickly

Now this is going to be a very absurd question. But what can I do, it's the client's requirement. Basically, we have a grid (master-detail type) that goes up to about 15 thousand plus rows (has the potential to go up to 30-50 thousand rows in a few years time).
My client does NOT want any paging, does not want any data cropped as well. Also he isn't exactly using the latest hardware so rendering on browsers is a big issue. He wants to view everything by printing it out or looking through it on the browser. (You may all think how insane that sounds, and it sure is).
Now I want to resolve this issue by rendering html quickly. At the moment its a simple asp.net grid view w/o paging. That essentially renders HTML tables. My options that I think are:
- Manually rendering html using div (for quick loading)
- export it to pdf or excel (is there any way to export without the need to resort to third party controls?)
- give the finger (to the client :D j/k)
So to sum up, whats the best way to show 10,000 plus records of data on html?
consider using the "Scroller" plug-in for Datatables..
As part of DataTables 1.8 release a new plug-in called "Scroller" was
introduced as part of the download package. Scroller is an
implementation of virtual scrolling for DataTables, which presents a
vertically scrolling table, scrolling the full height of the table,
but drawing only the rows which are necessary for the visible display,
leading to a huge performance increase. This is quite an exciting
plug-in for DataTables not only for the performance increase, but also
because it effectively provide a new user interaction with the table,
allowing full scrolling of very large data sets.
I know this is almost a year late, but in case it helps someone.
Use SlickGrid - It uses divs instead of tables, which gives so much more performance in IE. Check this example
He wants to view everything by printing
This is imho the only viable solution to view all information. PDF or Excel is much better at handling a large number of rows.
Doing the rendering is quite easy. Just set the excel mime type and return a HTML table.
http://www.designdetector.com/archives/05/07/HTMLToExcelTheEasyWay.php
When it comes to PDF, you probably have to use an external library like PDFSharp.
You should do the paging - it does not mean that you need to show only one page of data at a time but rather you should retrieve and render pageful of data at a time (and keep continuously fetching pages one after one till data is finished).
For example, send the first page of data from the server in the initial request. Setup a js timer and use AJAX requests to retrieve subsequent pages of data and load that into the browser. You can have multiple (say 3-4) AJAX requests going on simultaneously for retrieving pages - only thing would be to achieve the ordering correctly in such approach.
I will personally avoid grid-view and render the html table using manual java-script (with help for jquery) or use some java-script template engine. I will use JSON for retrieving the data from the server.

ASP.NET: Strategy for handling really large reports

Maybe not specific to reports but still...
In my asp.net mvc web application there's a section for reports that show 5 columns of data that map almost directly to a table in the db.
The problem is, in some cases, the length of that report may exceed 40,000 records (I know, nobody can really process 40,000 records of data but the report is what it is) and as you can expect, it times out and throws an error.
The question is, what's a good way to process and deliver a report of that size? I thought about creating a small little console app that would build the report outside of the webserver but I'm kind of at a loss as to what direction to look into?
Does the report need to have up-to-the-minute data? If not, you can look at generating the report as a PDF at night (or whenever your server isn't busy) and just providing a link to the PDF. A scheduled task that runs a console app as you suggested could create the report and output it to a file. A lot of reporting tools like Crystal Reports will allow you to export the report to a PDF or an Excel spreadsheet. For that matter, you could generate the report on a completely different machine and then copy it over to the web server. This could allow you to update the report every hour (or whatever) without putting such a load on your web server.
Generating the report while the user waits is probably not a good idea (not to mention SQL / IIS timeouts etc)
You could get the user request a report, then have a windows service pick up these requests, generate the report and email the user? (or have some kind of ajax polling script on the site to notify users when their reports are ready?)
You could extend this to scheduling of the same report at recurring intervals etc.
I would look into SQL Reporting Services (assuming this is running on SQL Server). There's several delivery options which may be better suited to your application's needs (you can schedule a PDF or Excel document to show up in someone's mailbox every night, for example).
There's also a great article from the StackOverflow team that allows background processes within ASP.NET if you can simply generate this report every so often instead of on-demand (maybe every 5-10 minutes?)
https://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/
Another frequent usage I've seen to handle large scale reporting is setting up a windows service that does the physical generation of the report which dumps the completed binary into a database or file store somewhere and then updates data to show the report is complete with the information needed for the application to link the completed report.
Then you could have your do report button fire off a request to initiate a report and then move them to a processing report page where it lists all the reports queued up / processing for them.
It's doubtful that a user would ever actually look at all of a 40,000 row report. So why not show just the top 1,000 most current rows ordered backwards? If you're using a reporting solution that supports on-demand reports, you could always drill down to second report that shows the next 1,000 most current rows. Just a thought...

Handling Long Running Reports

I am working on a ASP.net application written in C# with Sql Server 2000 database. We have several PDF reports which clients use for their business needs. The problem is these reports take a while to generate (> 3 minutes). What usually ends up happening is when the user requests the report the request timeout kills the request before the web server has time to finish generating the report, so the user never gets a chance to download the file. Then the user will refresh the page and try again, which starts the entire report generation process over and still ends up timing out. (No we aren't caching reports right now; that is something I am pushing hard for...).
How do you handle these scenarios? I have an idea in my head which involves making an aysnchronous request to start the report generating and then have some javascript to periodically check the status. Once the status indicates the report is finished then make a separate request for the actual file.
Is there a simpler way that I am not seeing?
Using the filesystem here is probably a good bet. Have a request that immediately returns a url to the report pdf location. Your server can then either kick off an external process or send a request to itself to perform the reporting. The client can poll the server (using http HEAD) for the PDF at the supplied url. If you make the filename of the PDF derive from the report parameters, either by using a hash or directly putting the parameters into the name you will get instant server side caching too.
I would consider making this report somehow a little bit more offline from the processing point of view.
Like creating a queue to put report requests into, process the reports from there and after finish, it can send a message to the user.
Maybe I would even create a separate Windows Service for the queue handling.
Update: sending to the user can be email or they can have a 'reports' page, where they can check their reports' status and download them if they are ready.
What about emailing the report to the user. All the asp page should do is send the request to generate the report and return a message that the report will be emailed after is has finished running.
Your users may not accept this approach, but:
When they request a report (by clicking a button or a link or whatever), you could start the report generation process on a separate thread, and re-direct the user to a page that says "thank you, your report will be emailed to you in a few minutes".
When the thread is done generating the report, you could email the PDF directly (probably won't work because of size), or save the report on the server and email a link to the user.
Alternatively, you could go into IIS and raise the timeout to > 3 minutes.
Here is some of the things I would do if I would be presented this problem:
1- Stop those timeout! They are a total waste of resources. (bring up the timeout value of asp pages)
2- Centralize all the db access in one single point, then gather stats about what reports ran when by whom and how much time it took. Investigate why it takes so long, is it because of report complexity? data range? server load? (you could actually all write that on a .csv file on the server and import this file periodically in the sql server to analyze later).
Eventually, it's going to be easier for you to "cache" reports if you go through this single access point (example, same query same date will return same PDF previously generated)
3- I know this really wasn't the question but have you tried diving into those queries to see why they are so long to run? Query tuning maybe?
4- Email/SMS/on screen message when report is ready seems great... if your user generally send a batch of report to be generated maybe a little dashboard indicating progression of "their" queue could be built in the app. A little ajax control would periodically refresh the status..
Hint: If you used that central db access and you have sufficient information about what runs when why and how-long you will eventually be able to roughly estimates the time it will take for a report to run.
If the response time is mission critical, should certain users be limited in the data range (date range for example) during some hours of the day?
Good luck and please post more details about your scenario if you want to get more accurate hints...
Query tuning is probably your best place to start. Though I don't know you are generating the report, that step shouldn't really take all that long. A poorly performing query on the other hand could absolutely kill your performance.
Depending on what you find in looking at the query, you may need to add some indexes, or possibly even set up a table to store the information for your report in a denormalized way, to make it available faster. This denormalized table could then be refreshed (through a SQL Server Job) every hour, or with whatever frequency your requirements dictate (within reason).
If its' a relatively static report, without varying user input parameters, then caching the report run earlier in the day would be a good idea as well, but its' hard to say any more about this without knowing your situation.
For a problem like this you really need to start at the database unless you have reason to suspect your report generating code of being the culprit. There are various band-aids you could use that might help for a while, but if your db is the root cause then those solutions will not scale well, and you'll likely run into similar problems (or worse) some time in the future.

Categories

Resources