小编Lou*_*Lou的帖子

Xamarin垃圾收集器和循环引用

"性能"部分阅读Xamarin文档时,我注意到以下章节:

下图说明了强引用可能出现的问题:

循环参考

对象A具有对对象B的强引用,对象B具有对对象A 的强引用.由于存在圆形强引用,这些对象被称为不朽对象.这种父子关系并不罕见,因此,即使对象不再被应用程序使用,垃圾收集器也不能回收任何对象.

这是我第一次在C#/ .NET/Mono语境中听说过"不朽的对象".

然后页面继续建议使用WeakReference其中一个对象,这将删除强循环引用并修复此"问题".

与此同时,Xamarin关于垃圾收集的文档声称:

Xamarin.Android使用Mono的Simple Generational垃圾收集器.这是一个标记和清除垃圾收集器[...]

标记和扫描GC不受循环引用的影响吗?

mono garbage-collection weak-references circular-reference xamarin

6
推荐指数
1
解决办法
682
查看次数

C# lambda 分配和收集

我今天看到了这个关于ConcurrentDictionary方法的一些性能差异的问题,我认为这是一个过早的微优化。

然而,经过一番思考,我意识到(如果我没记错的话),每次我们将 lambda 传递给一个方法时,CLR 都需要分配内存,传递适当的闭包(如果需要),然后过一段时间再收集它.

有以下三种可能:

  1. 没有闭包的 Lambda:

    // the lambda should internally compile to a static method, 
    // but will CLR instantiate a new ManagedDelegate wrapper or
    // something like that?
    return concurrent_dict.GetOrAdd(key, k => ValueFactory(k));
    
    Run Code Online (Sandbox Code Playgroud)
  2. 带闭包的 Lambda:

    // this is definitely an allocation
    return concurrent_dict.GetOrAdd(key, k => ValueFactory(k, stuff));
    
    Run Code Online (Sandbox Code Playgroud)
  3. 外部检查(例如检查锁定前的条件):

    // no lambdas in the hot path
    if (!concurrent_dict.TryGetValue(key, out value))
        return concurrent_dict.GetOrAdd(key, k => ValueFactory(k));
    
    Run Code Online (Sandbox Code Playgroud)

第三种情况显然不需要分配,第二种情况需要分配。

但是第一种情况(没有捕获的 lambda)是否完全不需要分配(至少在较新的 CLR 版本中)?另外,这是运行时的实现细节,还是标准指定的内容?

.net clr lambda garbage-collection micro-optimization

6
推荐指数
1
解决办法
2598
查看次数

中断安全 FIFO 中的 DMB 指令

此线程相关,我有一个 FIFO,它应该可以跨 Cortex M4 上的不同中断工作。

头部索引必须是

  • 多个中断(不是线程)原子地写入(修改)
  • 由单个(最低级别)中断原子读取

移动 FIFO 头的函数看起来与此类似(在实际代码中也有检查头是否溢出,但这是主要思想):

#include <stdatomic.h>
#include <stdint.h>

#define FIFO_LEN 1024
extern _Atomic int32_t _head;

int32_t acquire_head(void)
{
    while (1)
    {
        int32_t old_h = atomic_load(&_head);
        int32_t new_h = (old_h + 1) & (FIFO_LEN - 1);

        if (atomic_compare_exchange_strong(&_head, &old_h, new_h))
        {
            return old_h;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

GCC 会将其编译为:

acquire_head:
        ldr     r2, .L8
.L2:
        // int32_t old_h = atomic_load(&_head);
        dmb     ish
        ldr     r1, [r2]
        dmb     ish

        // int32_t new_h …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc atomicity c11

6
推荐指数
1
解决办法
706
查看次数

C“块”插入字符

我注意到这个涉及插入符号 (^) 字符的声明被固定在顶部的 cdecl.org 站点上:

// "cast foo into block(int, long long) returning double"
(double (^)(int , long long ))foo
Run Code Online (Sandbox Code Playgroud)

有人可以解释这里插入符号的目的是什么吗?这真的是 C 声明中的有效字符,还是某物的占位符?

c declaration caret

6
推荐指数
1
解决办法
152
查看次数

WinForms标签页不重新绘制表单大小调整

TabPage当我调整表单大小时,.NET WinForms 没有完全重新绘制其背景的原因吗?它应该是完全白色的(在Windows 7中),但一部分仍然是灰色的(SystemColors.Control最有可能).每当我点击最大化按钮时,当前可见的TabPage背景都不会被重绘.此外,如果我调整大小,我需要将表单移动到屏幕边界以便绘制它.

如果我最小化然后恢复表单,会发生同样的事情.在这种情况下,TabPage背景保持灰色.子控件正确呈现(标签,例如,保持其白色背景).

我使用的是Windows 7 32位,.NET 3.5.使用Visual Studio设计器添加了选项卡控件,并包含几个标签和两个文本框.我没有更改任何与绘制消息相关的本机样式标志.

[编辑]

我创建了一个测试项目,源代码在这里上传.

这是窗口最初的样子:

形成初始状态

这是我最小化然后恢复后窗口的样子:

最小化,然后恢复

请注意TabPage背景颜色的变化.

.net resize tabcontrol paint winforms

5
推荐指数
2
解决办法
3457
查看次数

简单的无锁秒表

根据 MSDN,类Stopwatch实例方法对于多线程访问并不安全。这也可以通过检查个别方法来确认。

然而,由于我只需要在代码中的几个地方使用简单的“经过时间”计时器,我想知道它是否仍然可以无锁地完成,使用类似的东西:

public class ElapsedTimer : IElapsedTimer
{
    /// Shared (static) stopwatch instance.
    static readonly Stopwatch _stopwatch = Stopwatch.StartNew();

    /// Stopwatch offset captured at last call to Reset
    long _lastResetTime;

    /// Each instance is immediately reset when created
    public ElapsedTimer()
    { 
        Reset();
    }

    /// Resets this instance.
    public void Reset()
    {
        Interlocked.Exchange(ref _lastResetTime, _stopwatch.ElapsedMilliseconds);
    }

    /// Seconds elapsed since last reset.
    public double SecondsElapsed
    {
        get
        {
             var resetTime = Interlocked.Read(ref _lastResetTime);
             return (_stopwatch.ElapsedMilliseconds - resetTime) / …
Run Code Online (Sandbox Code Playgroud)

c# atomic stopwatch lockless

5
推荐指数
1
解决办法
723
查看次数

GCC优化纯函数

我对GCC关于优化pure功能的保证感到困惑(来自在线文档):

pure
Run Code Online (Sandbox Code Playgroud)

除返回值外,许多函数都没有效果,它们的返回值仅取决于参数和/或全局变量.(......)

有趣的非纯函数是具有无限循环的函数或取决于易失性存储器或其他系统资源的函数,其可以在两个连续调用之间改变(例如feof在多线程环境中).

并为const:

const
Run Code Online (Sandbox Code Playgroud)

许多函数不检查除参数之外的任何值,除了返回值之外没有任何效果.基本上,这只是比下面的纯属性稍微严格的类,因为该函数不允许读取全局内存.

请注意,不得声明具有指针参数并检查指向的数据的函数const.同样,调用非const函数的函数通常不能是const.

所以,我尝试创建一个接受指针参数的函数,并尝试标记它pure.不过,我试着在网上编译使用GCC此功能(我都尝试constpure):

typedef struct
{
    int32_t start;
    int32_t end;
}
Buffer;

inline __attribute__((pure,always_inline)) int32_t getLen(Buffer * b) 
{
    return b->end - b->start;
}
Run Code Online (Sandbox Code Playgroud)

并注意到GCC(至少我试过的几个在线编译器版本):

  1. 如果传递的Buffer*参数指向全局值,则不优化对此函数的调用(即多次调用),
  2. 如果传递的指针指向本地(堆栈)变量,则优化对此函数的调用(即仅调用一次).
  3. 即使我标记函数const而不是两种情况都是相同的pure,但const如果有一个指针参数,可能会被忽略?

这是一件好事,因为全局Buffer可能随时由不同的线程/中断改变,而本地Buffer对于优化是完全安全的.

但是我对传递指针的言论感到困惑.是否存在为pure接受指针参数的函数显式定义GCC行为的地方?

c++ optimization gcc const purely-functional

5
推荐指数
1
解决办法
578
查看次数

将内联函数放在C标头中是否错误?

我正在为几个编译器构建一个C项目,其中一些是旧式编译器,它们似乎没有链接时间内联支持,因此将static inline函数直接放在标头中并实际上让每个翻译单元都有自己的副本似乎合乎逻辑。

另外,我需要确保内联某些函数,以便在某些低级中断处理程序中调用时不会调用其他函数(即,更改CPU寄存器),因此这不仅仅是让编译器选择是否会影响性能。 。

但是,我的一位同事告诉我,这是一件不寻常的事情,我应该避免这样做。在项目的这一点上,我可能仍然可以重新排列所有内容,所以我想确认如果决定使用标头内联,从长远来看是否还会遇到一些问题?

c inline c-header

5
推荐指数
1
解决办法
781
查看次数

ARM Cortex M7未对齐访问和memcpy

我正在使用GCC为Cortex M7编译此代码:

// copy manually
void write_test_plain(uint8_t * ptr, uint32_t value)
{
    *ptr++ = (u8)(value);
    *ptr++ = (u8)(value >> 8);
    *ptr++ = (u8)(value >> 16);
    *ptr++ = (u8)(value >> 24); 
}

// copy using memcpy
void write_test_memcpy(uint8_t * ptr, uint32_t value)
{
    void *px = (void*)&value;
    memcpy(ptr, px, 4);
}

int main(void) 
{
    extern uint8_t data[];
    extern uint32_t value;

    // i added some offsets to data to
    // make sure the compiler cannot
    // assume it's aligned in memory

    write_test_plain(data …
Run Code Online (Sandbox Code Playgroud)

c embedded memory-alignment memcpy cortex-m

5
推荐指数
1
解决办法
846
查看次数

使用指定的初始化程序时,不同的gcc程序集

我正在为ARM检查一些gcc生成的程序集,并注意到如果我使用指定的初始化程序,我会得到奇怪的结果:

例如,如果我有这个代码:

struct test 
{
    int x;
    int y;
};

__attribute__((noinline))
struct test get_struct_1(void)
{
    struct test x;
    x.x = 123456780;
    x.y = 123456781;
    return x;
}

__attribute__((noinline))
struct test get_struct_2(void)
{
    return (struct test){ .x = 123456780, .y = 123456781 };
}
Run Code Online (Sandbox Code Playgroud)

对于ARM(ARM GCC 6.3.0),我使用gcc -O2 -std = C11 得到以下输出:

get_struct_1:
    ldr r1, .L2
    ldr r2, .L2+4
    stm r0, {r1, r2}
    bx lr
.L2:
    .word 123456780
    .word 123456781


get_struct_2:     // <--- what is happening here
    mov r3, …
Run Code Online (Sandbox Code Playgroud)

c assembly gcc arm

5
推荐指数
1
解决办法
78
查看次数