首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我的StringReader 50us比.NET StringReader慢?

为什么我的StringReader 50us比.NET StringReader慢?
EN

Stack Overflow用户
提问于 2009-09-10 02:51:35
回答 5查看 1.5K关注 0票数 3

在我的测试中,我创建了一个32000个字符的字符串。在重复执行测试之后,BCL StringReader始终在350us内执行,而我的在400us内运行。他们在隐藏着什么样的秘密?

测试:

代码语言:javascript
复制
private void SpeedTest()
{
    String r = "";
    for (int i = 0; i < 1000; i++)
    {
        r += Randomization.GenerateString();
    }

    StopWatch s = new StopWatch();
    s.Start();
    using (var sr = new System.IO.StringReader(r))
    {               
        while (sr.Peek() > -1)
        {
            sr.Read();
        }
    }

    s.Stop();
    _Write(s.Elapsed);
    s.Reset();
    s.Start();

    using (var sr = new MagicSynthesis.StringReader(r))
    {               
        while (sr.PeekNext() > Char.MinValue)
        {
            sr.Next();
        }               
    }

    s.Stop();
    _Write(s.Elapsed);
}

代码:

代码语言:javascript
复制
public unsafe class StringReader : IDisposable
{
    private Char* Base;
    private Char* End;
    private Char* Current;
    private const Char Null = '\0';


    /// <summary></summary>
    public StringReader(String s)
    {
        if (s == null)
            throw new ArgumentNullException("s");           

        Base = (Char*)Marshal.StringToHGlobalUni(s).ToPointer();
        End = (Base + s.Length);
        Current = Base;
    }


    /// <summary></summary>
    public Char Next()
    {
        return (Current < End) ? *(Current++) : Null; 
    }

    /// <summary></summary>
    public String Next(Int32 length)
    {
        String s = String.Empty;

        while (Current < End && length > 0)
        {
            length--;
            s += *(Current++);
        }

        return s;
    }

    /// <summary></summary>
    public Char PeekNext()
    {
        return *(Current); 
    }

    /// <summary></summary>
    public String PeekNext(Int32 length)
    {
        String s = String.Empty;
        Char* a = Current;

        while (Current < End && length > 0)
        {
            length--;
            s += *(Current++);
        }

        Current = a;

        return s;
    }


    /// <summary></summary>
    public Char Previous()
    {
        return ((Current > Base) ? *(--Current) : Null);
    }

    /// <summary></summary>
    public Char PeekPrevious()
    {
        return ((Current > Base) ? *(Current - 1) : Null);
    }


    /// <summary></summary>
    public void Dispose()
    {
        Marshal.FreeHGlobal(new IntPtr(Base));          
    }
}
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-09-10 03:19:30

我敢打赌,Marshal.StringToHGlobalUni()Marshal.FreeHGlobal(new IntPtr(Base))与这些差异有很大关系。我不确定StringReader是如何管理字符串的,但我敢打赌它不会将它复制到非托管内存中。

查看Reflector中的StringReader.Read()方法将显示以下内容:

代码语言:javascript
复制
public override int Read()
{
    if (this._s == null)
    {
        __Error.ReaderClosed();
    }
    if (this._pos == this._length)
    {
        return -1;
    }
    return this._s[this._pos++];
}

构造者也只是:

代码语言:javascript
复制
public StringReader(string s)
{
    if (s == null)
    {
        throw new ArgumentNullException("s");
    }
    this._s = s;
    this._length = (s == null) ? 0 : s.Length;
}

因此,看起来StringReader只是维护当前位置,并使用常规索引返回值。

编辑

作为对您的注释的响应,您的Next()方法将进行比较和不安全的强制转换,这可能没有以任何方式进行优化。StringReader.Read()执行简单的比较,并将字符作为字符串中的_pos索引返回,这可能是由编译器进行了一些优化。

票数 4
EN

Stack Overflow用户

发布于 2009-09-10 03:01:36

也许Reflector会帮你找到答案?

票数 4
EN

Stack Overflow用户

发布于 2009-09-10 03:06:23

您可以随时查看source code

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1403146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档