代码在Xamarin上运行慢了很多.Android应用程序与主机应用程序的比较

本文关键字:应用程序 Android 主机 比较 Xamarin 运行 代码 | 更新日期: 2023-09-27 18:04:51

我在一个PCL项目中为String编写了一个扩展方法:

public static ICollection<string[]> SplitAt(this string input, char target, int length, StringSplitOptions opts, bool trin = false()
{
    string[] itens = input.Split(new char[] { target }, opts);
    return InternalSplitAt(itens, target, length, trim);
}
private static ICollection<string[]> InternalSplitAt(string[] itens, char target, int length, bool trim = false)
{
    var collectionToReturn = new List<string[]>();
    var targetString = target.ToString();
    do
    {
        string firstPart = string.Join(targetString, itens.Take(length));
        collectionToReturn.Add(firstPart.Split(target));
        if (trim)
        {
            itens = itens.Skip(length).Select(x => x.Trim()).ToArray();
        }
        else
        {
            itens = itens.Skip(length).ToArray();
        }
    }
    while (itens.Length >= length);
    return collectionToReturn;
}

然后我像这样使用SplitAt方法:

var arr = str.SplitAt('#', 34, StringSplitOption.None);

str是一个有280474个字符的String

当我在Xamarin中调用上述代码时。Android应用程序几乎需要40秒才能完成,而在控制台应用程序中,只需1秒。

我的代码可以在任何改进,使其在Android上运行得更快?

注意:该扩展方法是基于一段时间前我从另一个StackOverflow问题中得到的代码,我认为,但我找不到它再次给予适当的信任。

编辑:

解释我想要完成的事情:我有一个这样的字符串:

var str = "001#Test#002#Test#003#Test";

通过#执行正常的Split,我会得到一个数组this:

string[] { "001", "Test", "002", "Test", "003", "Test" }

但是我需要它是三个不同的数组,所以像这样调用扩展名:

var arr = str.SplitAt('#', 2, StringSplitOption.None);
我:

string[] { "001", "Test" }
string[] { "002", "Test" }
string[] { "003", "Test" }

在我的实际场景中,280474字符串具有53074个#字符,并且由于我使用34作为长度参数调用扩展名,因此我的最终输出将是一个包含1561个条目(53074/34)的iccollection,每个条目都是string[34]

代码在Xamarin上运行慢了很多.Android应用程序与主机应用程序的比较

试试这个,我已经减少了完成任务所需的操作数量。此外,我已经完成了最初的修剪,以防您需要它,所以代码不会多次调用修剪。它在我的机器上运行速度快了6倍,大约有10k的测试数据。

    public static ICollection<string[]> SplitAt(this string input, char target, int length, StringSplitOptions opts, bool trim = false)
    {
        var items = input.Split(new[] { target }, opts);
        if (trim) items = items.Select(x => x.Trim()).ToArray();
        return InternalSplitAt(items, length);
    }
    private static ICollection<string[]> InternalSplitAt(string[] items, int length)
    {
        var collectionToReturn = new List<string[]>();
        for (int i = 0; i < items.Length; i += length)
        {
            collectionToReturn.Add(items.Skip(i).Take(length).ToArray());
        }
        return collectionToReturn;
    }

基于@Simon的回答和@Jon Skeet的评论,我想出了一个非常有效的解决方案,在20~30毫秒内运行。在这种情况下,使用ToArray和字符串连接创建数组确实会影响性能。

public static ICollection<string[]> SplitAt(this string input, char target, int length, StringSplitOptions, opts = StringSplitOptions.None, bool trim = false)
{
    string[] itens = input.Split(new char[] { target }, opts);
    if (trim) itens = itens.Select(s => s.Trim()).ToArray();
    return InternalSplitAt(itens, length);
}
private static ICollection<string[]> InternalSplitAt(string[] itens, char target, int length, bool trim = false)
{
    var collectionToReturn = new List<string[]>();
    var loops = itens.Length / length;
    for (int i = 0; i < loops; i++)
    {
        var arrayToAdd = new string[length];
        Array.Copy(itens, i * length, newArray, 0, length);
        ret.Add(arrayToAdd);
    }
    return collectionToReturn;
}

感谢这一节的答案,我取了数组的一部分。

再次感谢Simon提供的有用的答案,感谢Jon Skeet指出了数组创建和字符串连接中可能存在的问题。