在开发中
最后更新: 2023年2月13日13:48 通过管理
马丁
上创建: 2022年12月9日11:48
类别: WinForms的UI
类型: 功能要求
1
RadGridView:改进StringTokenizer的性能

我们与145000行和4列的RadGridView一起工作。我们使用复制粘贴来移动数据从其他应用程序和应用程序与Telerik构建。

当我们复制一个平面文件(用制表符分隔字段)并将其粘贴到RadGridView时,整个过程非常缓慢。从剪贴板中检索数据的函数需要几分钟(可能需要几个小时,我取消了它)。它将原因追踪到StringTokenizer类。标记器将字符串分割成单独的字段。但是在提取一个字段之后,它会创建该字符串(包含大约10MB的数据)减去该字段的新副本。我修补了它(与HarmonyX),现在只需要一秒钟:

静态StringTokenizerPerformancePatch{静态私人只读的InstanceFieldAccessor<StringTokenizerLinkedList<字符串> > _tokens=InstanceFieldAccessor< StringTokenizer, LinkedList<字符串> > (“令牌”);静态私人只读的InstanceFieldAccessor<StringTokenizer字符串> _sourceString=InstanceFieldAccessor < StringTokenizer,字符串> (“sourceString”);静态私人只读的InstanceFieldAccessor<StringTokenizer字符串> _delimiter=InstanceFieldAccessor < StringTokenizer,字符串> (“分隔符”);静态私人只读的InstanceFieldAccessor<StringTokenizerIEnumerator<字符串> > _enumerator=InstanceFieldAccessor < StringTokenizer, IEnumerator <字符串> > (“计数器”);[HarmonyPatch (typeof (StringTokenizer),“标记”静态Patch_StringTokenizer_Tokenize{静态保龄球前缀StringTokenizer __instance{vartoken = _token . getvalue (__instance);varsourceString = _sourceString.GetValue(__instance);vardelimiter = _delimiter.GetValue(__instance);Tokenize(tokens, sourceString, delimiter);_enumerator。SetValue (__instance tokens.GetEnumerator ());返回;}静态私人无效标记LinkedList <字符串>标记,字符串文本,字符串分隔符{tokens.Clear ();如果字符串.IsNullOrEmpty(文本)返回;int指数=0;真正的) {varIndex2 =文本。IndexOf(delimiter, index, stringcompare . ordinal);如果(index2 <0) {tokens.AddLast(text.Substring(index));打破;}字符串Token =文本。子字符串(index, index2 - index);tokens.AddLast(令牌);index = index2 + delimiter.Length;} } } }

请更新您的tokanizer以提高性能。当你在做的时候:
  • 如果分隔符是一个字符,为什么不使用String.Split?
  • 为什么要使用LinkedList?
13个评论
管理
技术支持工程师,负责人
发布: 2023年1月23日10:08

你好,马丁,

谢谢你分享所有的结果。

我理解您的担忧,非常感谢您的反馈。然而,请记住,一般来说,50万的记录是不打算在RadGridView管理在所有。这就是为什么建议的控件是RadVirtualGrid,这是与大量数据交互的正确方式,因为它不会一次加载整个数据,而只是在滚动时加载可见的部分。

StringTokenizer广泛用于这两个控件的粘贴操作。我们的开发人员已经投入了一些时间来执行不同的测试,并且确实观察到了相当大的改进。谢谢你的建议和你的宝贵时间。我们将尽最大努力在即将发布的版本中引入改进。

我也更新了你的Telerik点对于付出的努力和产品的贡献。非常感谢。

问候,
技术支持工程师,负责人
进步Telerik

喜欢Telerik和Kendo的UI产品,相信更多人应该尝试一下?邀请其他开发者成为Progress的客户每个人都可以得到50美元的亚马逊礼券

马丁
发布: 1月17日2023 12:38

嗨密不可分,

我有点糊涂了。让我回顾一下我们的转换:

  1. 我:粘贴方法RadGridView粘贴50万条记录时速度很慢。这是由于StringTokenizer
  2. RadGridView不能处理50万条记录,试试RadVirtualGrid

    (我:要花几天时间来更换RadGridViewRadVirtualGrid。实现后,粘贴50万条记录。仍然缓慢。)

  3. 我:RadVirtualGrid还慢,因为还用StringTokenizer
  4. 当然慢了,你粘贴的记录是一样多的。
  5. 我:呃……那么为什么建议使用RadVirtualGrid而粘贴50万条记录本身就是问题所在?

请看以下数据:

RecordCount 应用补丁的 打补丁的 获得
10000 00:01.561 00:00.002 781
20000 00:06.575 00:00.005 1315
30000 00:15.053 00:00.005 3011
40000 00:27.931 00:00.011 2539
50000 00:47.778 00:00.026 1838
60000 01:08.526 00:00.011 6230
70000 01:35.706 00:00.018 5317
80000 02:02.032 00:00.020 6102
90000 02:37.530 00:00.041 3842
100000 03:16.897 00:00.045 4375

我不明白的是:

  1. 根据你自己的文档RadGridView应该支持一百万条记录。它不是。
  2. 然后你给我的建议是转移到RadVirtualGrid,因为那将支持一百万条记录。它不是。
  3. 你说"StringTokenizer在Telerik Presentation Framework和TextPrimitive中被全局使用”。所以这是一个核心组件,如果这个组件真的很快,那该有多好?
  4. 我给了你一个工作补丁(见数字)。你的回答是"RadVirtualGrid案例在处理此请求时将考虑进行改进”,但……问题不在于RadVirtualGrid或者是RadGridView,问题在于StringTokenizer,你的核心组件之一。
  5. 简而言之:我真的不明白为什么会犹豫……
管理
技术支持工程师,负责人
发布: 16 Jan 2023 12:59

你好,马丁,

RadVirtualGrid提供了按需加载数据的内部机制,例如在滚动时。因此,只有可见的单元格元素请求在cellvaluenneeded事件中提供值。但是,如果您尝试复制RadVirtualGrid中的整个内容,则预计会请求整个数据,然后将其存储在剪贴板中。在这种情况下,不会有任何显著的差异,因为要将值复制到剪贴板将请求145000行。

StringTokenizer在Telerik Presentation Framework和TextPrimitive中被全局使用。因此,在处理此请求时,将考虑改进RadVirtualGrid的情况。谢谢您的理解。

问候,
技术支持工程师,负责人
进步Telerik

喜欢Telerik和Kendo的UI产品,相信更多人应该尝试一下?邀请其他开发者成为Progress的客户每个人都可以得到50美元的亚马逊礼券

马丁
发布: 2023年1月13日15:39

嗨密不可分,

也许在RadVirtualGrid的例子中,你会认为这是一个bug。在RadGridView的情况下,这不是一个bug,因为RadGridView不是为数百万条记录创建的。RadGridView是和粘贴一百万条记录不应该花几分钟…对吧?:)

问候,

马丁

管理
技术支持工程师,负责人
发布: 2023年1月13日14:46

嗨,马丁,

谢谢你的反馈。在解决这个问题时,我们也会考虑RadVirtualGrid。

确保你投了你的票,以增加其优先级。

问候,
技术支持工程师,负责人
进步Telerik

manbets登录虚拟教室,免费的自定进度的技术培训,让你跟上速度与Telerik和剑道UI产品迅速得到了一个全新的面貌+新的和改进的内容,包括一个全新的Blazor课程!点击这里查看https://learn.telerik.com/

马丁
发布: 1月13日2023 13:55

嗨密不可分,

你可能已经注意到我正在切换到RadVirtualGrid。我发现RadVirtualGrid也使用StringTokenizer。这意味着同样的性能问题仍然存在。

问候,

马丁

管理
技术支持工程师,负责人
发布: 2022年12月20日14:18

嗨,马丁,

说实话,100万条记录对于RadGridView来说太多了。推荐的方法不是使用RadGridView的虚拟模式,而是使用RadVirtualGrid,这是一个基于Telerik Presentation Framework开发的网格组件,它提供了一种方便的方法来实现您自己的数据管理操作,并在与大量数据交互时优化性能。请参考以下与RadVirtualGrid入门相关的帮助文章:

https://docs.telerik.com/devtools/winforms/controls/virtualgrid/getting-started

至于在公共反馈门户网站的功能请求中评论编辑器选项的问题,这些也是我账户上的编辑器选项:

在提交请求本身时,预计会有更多选项来提供尽可能多的信息来描述问题:

我相信这些信息会有帮助。

问候,
技术支持工程师,负责人
进步Telerik

喜欢Telerik和Kendo的UI产品,相信更多人应该尝试一下?邀请其他开发者成为Progress的客户每个人都可以得到50美元的亚马逊礼券

马丁
发布: 2022年12月17日13:40

关于总体性能:我们(客户)的期望是什么?这篇文章声明“你想将RadGridView绑定到超过一百万个项目。在这种情况下,建议使用“虚拟模式”。但是…我们甚至还不到一半,而且有些行动已经太慢了。

所以你能表达一些最低期望吗?当你加载一个有1M条记录的RadGridView时,所有的批量操作(比如加载、选择全部、删除全部选中、复制、粘贴等)应该最多花费10秒。(甚至可能基于特定的处理器类型)。

在这种情况下,我们可以报告错误而不是请求。在这种情况下,我们也知道何时切换到虚拟模式或RadVirtualGrid。在这种情况下,我还希望Progress在发布新版本之前测试性能。

这个特性请求只是RadGridView许多性能问题的一个例子。昨天我还修补了一段代码,以提高批量追加操作的性能。现在,对我来说,这样做是令人沮丧的,因为我有一种感觉,我正在解决进步的问题。但如果我对网格的期望比定义的更多,那么这是我的选择和我的奋斗。

马丁
发布: 2022年12月17日13:12

当我创建一个新的请求/bug时,我会看到您所显示的条形图。

当我回复(或添加新评论)时,我看到这个栏:

管理
技术支持工程师,负责人
发布: 2022年12月16日15:04

嗨,马丁,

当您从Telerik帐户发布回复时,您将在激活的编辑器中看到“插入代码”选项:

至于报告的反馈项,我已经批准了,这样我们就可以进一步研究如何提高StringTokenizer的性能。

我也更新了你的Telerik点

确保投你的票,以增加其优先级的项目。您可以订阅状态更改并添加您的评论。

问候,
技术支持工程师,负责人
进步Telerik

喜欢Telerik和Kendo的UI产品,相信更多人应该尝试一下?邀请其他开发者成为Progress的客户每个人都可以得到50美元的亚马逊礼券

马丁
发布: 2022年12月14日13:17

嗨密不可分,

我将做得更好,并将重点放在有问题的组件上:StringTokenizer。请参阅下面的代码(偏离主题:当创建新请求或错误时,我可以插入代码。当我回答一个现有的请求/错误,该按钮消失了…为什么?)

在这个例子中,我创建了包含50,000条记录和4列的“clipboarddata”。字符串的总长度为1.2MB。构造这个标记器需要38秒(在我的机器上)。这种延迟随着数据的大小呈指数级增长!使用我的补丁只需要0.03秒,并且呈线性增长。您可以想象剪贴板数据为10MB时它的执行速度有多慢。

这个标记器用于粘贴纯文本和粘贴HTML(也可能用于其他地方)。

==================================================================

MeasurePerformance()
{
var sb = new StringBuilder();
For (var I = 0;I < 50000;我+ +)
附加($"{i}\t{i + 1}\t{i + 2}\t{i + 3}\r\n");

var clipboardData = sb.ToString();

var stopwatch = new stopwatch ();
stopwatch.Start ();
var tokenizer = new StringTokenizer(clipboardData, "\n");
stopwatch.Stop ();
Console.WriteLine (stopwatch.Elapsed.TotalSeconds);
}

管理
技术支持工程师,负责人
发布: 2022年12月13日15:02

你好,马丁,

我很抱歉听到您在使用我们的RadGridView控件时遇到任何困难。但是,为了确认是否存在任何问题,我请您提供一个用于复制/粘贴功能的示例平面文件(带有制表符分隔字段)。然后,我们将能够打开文件,选择整个内容并复制它。然后将其粘贴到RadGridView中,并对具体案例进行充分的分析。如果有任何特定的设置也可用于网格,请随意提供一个示例可运行项目来演示您所面临的问题。这样,我们就能够对确切的情况作出充分的分析,并提供进一步的援助。

提前谢谢你。我期待你的回复。

问候,
技术支持工程师,负责人
进步Telerik

喜欢Telerik和Kendo的UI产品,相信更多人应该尝试一下?邀请其他开发者成为Progress的客户每个人都可以得到50美元的亚马逊礼券

马丁
发布: 2022年12月9日12:26

添加:

正如我在第一篇文章中所建议的,StringTokenizer可以利用字符串。分裂如果分隔符只有一个字符。但是…在方法中MasterGridViewTemplate。GetHtmlDataMasterGridViewTemplate。GetTextData为什么不用呢?字符串。分裂并去除使用的StringTokenizer

Baidu
map