首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Rx -哪里的方法会导致内存泄漏?

Rx -哪里的方法会导致内存泄漏?
EN

Stack Overflow用户
提问于 2018-08-12 08:19:30
回答 1查看 97关注 0票数 2

我已经创建了基于Rx interval的简单触发器。它每隔一个特定的时间间隔生成一个信号,并通过Where方法进行过滤,就像这样(简化的例子):

代码语言:javascript
运行
复制
var isActive = false;

Observable.Interval(TimeSpan.FromMilliseconds(1))
            .Where(_ => !isActive)
            .Subscribe(_ =>
            {
                isActive = true;
                Console.WriteLine("New subscription item");
                Thread.Sleep(30 * 1000); // simulate time-expensive work
                Console.WriteLine("Finished");
                isActive = false;
            });

当isActive标志设置为true时,我想忽略元素。它似乎是有效的,因为订阅块每30秒调用一次(模拟耗时的工作),但当我分析这种简单的应用程序时,我看到许多Action对象被存储到内存中(大约每秒60-70个实例),并在它们被订阅块消耗时被释放。我想立即忽略并处理它们。

EN

回答 1

Stack Overflow用户

发布于 2020-12-02 13:00:08

我想我能够重现这个问题。下面的序列启动一个计时器,每10毫秒计时一次。每3秒采样一次,然后在控制台中打印当前的内存使用情况。测试的总持续时间为5分钟。

代码语言:javascript
运行
复制
Observable
    .Interval(TimeSpan.FromMilliseconds(10))
    //.Do(x => Thread.Sleep(1000)) // Uncomment this line to see memory leak
    .Sample(TimeSpan.FromSeconds(3))
    .Select((x, i) => (Sample: i + 1, Ticks: x + 1))
    .Do(x => Console.WriteLine($"Sample #{x.Sample,-2}, Ticks: {x.Ticks,6:#,0}"
        + $", Memory usage: {GC.GetTotalMemory(true):#,0} bytes"))
    .IgnoreElements()
    .Timeout(TimeSpan.FromMinutes(5))
    .Materialize()
    .Wait();

下面是输出:

代码语言:javascript
运行
复制
Sample #1 , Ticks:    193, Memory usage: 160,048 bytes
Sample #2 , Ticks:    383, Memory usage: 160,440 bytes
Sample #3 , Ticks:    573, Memory usage: 161,000 bytes
...
Sample #49, Ticks:  9,345, Memory usage: 169,688 bytes
Sample #50, Ticks:  9,537, Memory usage: 169,688 bytes
Sample #51, Ticks:  9,730, Memory usage: 169,688 bytes
...
Sample #97, Ticks: 18,509, Memory usage: 176,120 bytes
Sample #98, Ticks: 18,700, Memory usage: 176,120 bytes
Sample #99, Ticks: 18,892, Memory usage: 176,120 bytes

程序使用的内存在整个测试过程中都是稳定的。

现在,让我们取消注释行.Do(x => Thread.Sleep(1000)),它会在1秒内阻止每个节拍的生成。下面是新的输出:

代码语言:javascript
运行
复制
Sample #1 , Ticks:      2, Memory usage: 166,432 bytes
Sample #2 , Ticks:      5, Memory usage: 173,136 bytes
Sample #3 , Ticks:      8, Memory usage: 185,424 bytes
...
Sample #32, Ticks:     95, Memory usage: 367,712 bytes
Sample #33, Ticks:     98, Memory usage: 367,712 bytes
Sample #34, Ticks:    101, Memory usage: 367,712 bytes
...
Sample #65, Ticks:    194, Memory usage: 563,576 bytes
Sample #66, Ticks:    197, Memory usage: 563,576 bytes
Sample #67, Ticks:    200, Memory usage: 563,576 bytes
...
Sample #97, Ticks:    290, Memory usage: 956,792 bytes
Sample #98, Ticks:    293, Memory usage: 956,792 bytes
Sample #99, Ticks:    296, Memory usage: 956,792 bytes

使用的内存几乎呈线性增长,大约每分钟增加150KB。

这里肯定发生了一些事情,但是Timer操作符的source code太复杂了,我搞不懂。我的猜测是,System.Timers.Timer在内部用作刻度生成器,它被抑制的刻度是以某种方式累积起来的。对于每个被抑制的节拍,平均泄漏约40个字节。

Windows 10、C# 8、.NET核心3.1.3、System.Reactive 4.4.1

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

https://stackoverflow.com/questions/51804755

复制
相关文章

相似问题

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