好的情况如下:
我有一个网络应用程序,其中包含我们销售人员客户的统计表,每行都有一个迷你图表,显示过去12个月销售数据的总体趋势。每个页面显示一个特定的销售人员的客户列表,其中一些可以拥有大量的客户=大量的行=大量的迷你图(例如,一个特别是有125个,需要15秒才能加载)
出于这个原因,jQuery sparklines无法使用 - 它们完全固定了访问具有IE的许多迷你图的页面的用户的CPU。
所以我继续使用Google Chart API,效果要好得多,除了两个问题:1)它位于安全的网站上,而Google Chart API URL只能通过HTTP提供(通过使用一个小的包装器脚本动态下载图形并从我们的安全服务器重新提供它来解决; 2)在一个有125个迷你图的页面上,由于请求的数量,它仍然非常慢(即使使用0-9服务器前缀来最大化可用连接数)。
所以我的下一步是尝试制作每个"下载/抓取/重新提供的图像"方法调用异步 - 它工作正常!
...但仅限于在调试模式下运行的开发箱。
当我把它推到现场时,速度更快,但是它会卸下一些图像,这当然是不可接受的。
所以这就是我希望一些SO热点知道的事情:
1)为什么我的异步方法调用时会调用,但不能在实时站点上工作?
2)有没有更容易的方法来获得某种类型的大量迷你图,以便在安全的服务器上快速加载,而不会让我想要撕掉我的头发?
2a。)有没有人有使用ASP.NET图表库的经验?这是我应该调查的吗?
2b。)一位同事建议我使用1x1 CSS背景图像并改变高度来制作我自己的迷你线程序。问题是:a)如果我们想要进行更改,它是完全不可扩展的; b)它看起来很糟糕(在标记中留下大约每个迷你线的bajillion DIV); c)我不知道当一页上有100-200个时它是否足够快 - 你对1x1精灵方法的可行性有何看法?
提前致谢。
答案 0 :(得分:2)
首先,异步并不意味着更快,在你的情况下,如果不是更慢的话,它将没有任何区别。
我只是简化发生的事情,这样我就能更好地理解它。有一个页面可以加载125-200张图像。这些图像是动态生成的图形。这总结了发生了什么吗?如果是,那么:
如果客户端有足够的带宽并且您的服务器可以处理请求并且您的服务器上有足够大的管道,则加载这些图像不应该是一个问题。那么延迟在哪里?是谷歌吗?或者你的服务器放慢了速度?
与从浏览器直接访问Google相比,它的速度有多慢? 从浏览器直接到Google的响应时间是否可以接受? 如果不是,您可能需要在UI中使用不同的策略,以便不会自动加载所有图像。或者每个客户都在一个标签页或分解成页面,因此一次只能请求少量数据和图像。
您正在使用的Http套接字将限制为随时向Google发出2个请求,无论您产生多少mant线程。有一种方法可以改变这个数字(但我不记得我的头脑怎么样)。无论如何,这很可能是导致经济放缓的原因。
从业务层代码中使用异步调用(在这种情况下执行一些I / O绑定操作)并没有让您获得释放请求线程来为其他请求提供服务的好处。为此,您需要使用异步页面,因为页面可以通知IIS这个事实。任何其他异步工作只使用更多线程(除非您使用Async CTP中使用的技术 - C#5.0和专门使用I / O线程而不是工作线程。
现在看到你所看到的,在从谷歌获取图像时服务器端出现错误,你需要知道这些错误是什么。我建议你不要使用异步。
答案 1 :(得分:1)
ASP.Net图表在我的经验中运作良好。在http://betterdashboards.wordpress.com/2010/02/21/how-to-create-a-sparkline-chart-in-asp-net/有一个快速启动器,可以帮助您开始使用必要的配置来渲染迷你图。
编辑:在MVC中添加了使用ASP.Net图表的示例。显然,你想将这些代码中的一部分转移到某种类型的帮助程序类中,但希望这清楚地说明了使这项工作成功的必要条件。
@model IEnumerable<CustomerSales>
@using Chart = System.Web.UI.DataVisualization.Charting.Chart
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Name
</th>
<th>
Sales
</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@item.Name
</td>
<td>
@{
var chart = new Chart();
chart.ChartAreas.Add(new ChartArea());
chart.ChartAreas[0].AxisX.LabelStyle.Enabled = false;
chart.ChartAreas[0].AxisY.LabelStyle.Enabled = false;
chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
chart.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
chart.ChartAreas[0].AxisX.MajorTickMark.Enabled = false;
chart.ChartAreas[0].AxisY.MajorTickMark.Enabled = false;
chart.ChartAreas[0].AxisX.LineWidth = 0;
chart.ChartAreas[0].AxisY.LineWidth = 0;
chart.Series.Add(new Series());
// Assign the random number to the chart to create 35 points
for (int x = 0; x < item.Sales.Length; x++)
{
chart.Series[0].Points.AddXY(x, item.Sales[x]);
}
// Start hiding both sets of axes, labels, gridlines and tick marks
chart.ChartAreas[0].AxisX.LabelStyle.Enabled = false;
chart.ChartAreas[0].AxisY.LabelStyle.Enabled = false;
chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
chart.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
chart.ChartAreas[0].AxisX.MajorTickMark.Enabled = false;
chart.ChartAreas[0].AxisY.MajorTickMark.Enabled = false;
chart.ChartAreas[0].AxisX.LineWidth = 0;
chart.ChartAreas[0].AxisY.LineWidth = 0;
// Sparklines use the 'Spline' chart type to show a smoother trend with a line chart
chart.Series[0].ChartType = SeriesChartType.Spline;
// Since the line is the only thing you see on the chart, you might want to
// increase its width. Interestingly, you need to set the BorderWidth property
// in order to accomplish that.
chart.Series[0].BorderWidth = 2;
// Re-adjust the size of the chart to reduce unnecessary white space
chart.Width = 400;
chart.Height = 100;
string base64;
using (MemoryStream ms = new MemoryStream())
{
chart.SaveImage(ms);
var bytes = ms.GetBuffer();
base64 = Convert.ToBase64String(bytes);
}
/**
* Here's a simpler example that would do a regular chart,
* rather than a sparkline. No way to make the gridlines and axes go
* away with this helper that I'm aware of.
var chart = new Chart(
width: 300,
height: 100
)
.AddSeries(chartType: "Spline", yValues: item.Sales);
var bytes = chart.GetBytes();
var base64 = Convert.ToBase64String(bytes);
*/
}
<img src="data:image/jpeg;base64,@base64" />
</td>
</tr>
}
</table>
这是使用看起来像这样的模型:
public class CustomerSales
{
public CustomerSales(string name, params int[] sales)
{
Name = name;
Sales = sales;
}
[Required]
public string Name { get; set; }
[Required]
public int[] Sales { get; set; }
}