2

好的,情况如下:

我有一个 Web 应用程序,其中包含一个关于我们销售人员的客户的统计数据表,每一行都有一个迷你图,显示过去 12 个月的销售数据的总体趋势。每个页面显示一个特定推销员的客户列表,其中一些可能有大量客户 = 大量行 = 大量迷你图(例如,特别是一个有 125 条并需要 15 秒加载)。

出于这个原因,无法使用jQuery 迷你图 - 它们完全固定了使用 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 sprite 方法的可行性有何看法?

提前致谢。

4

2 回答 2

2

首先,异步并不意味着更快,在您的情况下,如果不进一步减慢速度,它也没有什么区别。

我只是要简化正在发生的事情,以便我能更好地理解它。有一个页面可以加载 125-200 张图片。这些图像是动态生成的图表。这是否总结了正在发生的事情?如果是这样,那么:

如果客户端有足够的带宽并且您的服务器可以处理请求并且您的服务器上有足够大的管道,那么加载这么多图像应该不是问题。那么延迟在哪里呢?是谷歌吗?还是您的服务器放慢了速度?

与从浏览器直接转到 Google 相比,它慢了多少?从浏览器直接访问 Google 的响应时间是否可以接受?如果不是,您可能需要在 UI 中使用不同的策略,以便不会自动加载所有图像。或者每个客户都在一个选项卡中或将内容分解为页面,因此一次只请求少量数据和图像。

您使用的 Http 套接字将被限制为在任何时候向 Google 发出 2 个请求,无论您产生多少线程。有一种方法可以改变这个数字(但我不记得怎么做了)。无论如何,这很可能是您减速的原因。

使用来自业务层代码的异步调用(在这种情况下执行一些 I/O 绑定操作)不会让您获得释放请求线程以服务其他请求的好处。为此,您需要使用异步页面,因为该页面可以通知 IIS 这一事实。任何其他异步工作都只是使用更多线程(除非您使用的是异步 CTP - C# 5.0 中使用的技术,并且专门使用 I/O 线程而不是工作线程。

现在鉴于您所看到的,在从 Google 获取图像时服务器端存在错误,您需要知道这些错误是什么。我建议您不要为此使用异步。

于 2011-01-26T05:13:54.290 回答
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.&nbsp; 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; }
}
于 2011-01-26T01:26:19.130 回答