小编Wat*_*ter的帖子

使用不安全代码的C#位图

我正在使用以下代码在C#中制作图像蒙版:

for(int x = 0; x < width; x++)
{
    for(int y = 0; y < height; y++)
    {
        bmp.SetPixel(x,y,Color.White);
    }
}

for(int x = left; x < width; x++)
{
    for(int y = top; y < height; y++)
    {
        bmp.SetPixel(x,y,Color.Transparent);
    }
}
Run Code Online (Sandbox Code Playgroud)

但这太慢了......与此相比,不安全的是什么?它会分配得更快吗?

最后我用PNG格式做了一个bmp.Save().

更新:

按照MusiGenesis的建议阅读http://www.bobpowell.net/lockingbits.htm后,我使用以下代码(适用于需要它的任何人)使其工作:

Bitmap     bmp = new Bitmap(1000,1000,PixelFormat.Format32bppArgb);
BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, bmp.Width,bmp.Height), 
                                  System.Drawing.Imaging.ImageLockMode.ReadWrite, 
                                  bmp.PixelFormat);

int PixelSize=4;

unsafe 
{
    for(int y=0; y<bmd.Height; y++)
    {
        byte* row=(byte *)bmd.Scan0+(y*bmd.Stride);

        for(int x=0; x<bmd.Width; x++)
        { …
Run Code Online (Sandbox Code Playgroud)

c# unsafe bitmap

22
推荐指数
1
解决办法
8344
查看次数

C#性能分析器显示了长时间的暂停,无法从提供的数据中确定它是什么

渲染框架时,我的C#应用​​程序中出现了意外的峰值。我在探查器中进行了遍历,发现以下内容:

  • 当vsync打开时,该程序似乎在交换缓冲区时将控制权交给了OS(或执行了某些操作)...并且在某种程度上保持了渲染的一致性。这很好,因为它使帧平滑且没有怪异的微笔画。下图显示了被认为是完美的流体。这就是我们的情况,“它可以流畅地渲染而不会出现卡顿现象,从而完美地工作”。

VSync影​​像

  • 当vsync关闭并且程序不执行任何操作,只是尽可能快地进行写入而没有任何中断时,即使每秒的帧数更高,似乎仍然存在这些较大的空白,因此什么也不做。我很确定这是我在游戏中注意到的微结点,因为它会导致FPS急剧下降到60fps以下。下图显示了出问题的地方:

微口吃

在上面,增量时间为21毫秒(每秒60帧超过16.6毫秒),并在游戏中造成明显的停顿。甚至比这更糟,因为它仅在它之后才开始渲染(如您之后所看到的实心矩形),所以这21ms是一个谎言,根据该图,它更像是40ms,这太可怕了。

由于我不了解的原因,当打开vsync时,这种巨大差距永远不会发生。对于不熟悉vsync和游戏的用户,您不能在第一人称射击游戏中使用vsync,因为由于它的工作原理,它会削弱输入处理,因此我无法使用vsync,并且必须研究非vsync版本。我需要找到为什么非vsync版本具有这些主要停滞点的原因。

我的问题是,如何知道您从上面看到的图像中导致此延迟的原因?

性能分析器表示,这里有大量等待时间,超过80%的等待时间需要20%的CPU使用率(相比之下,准备渲染数据时需要100%的CPU使用率)。

探查器还显示该循环中没有运行任何渲染代码...这很奇怪,因为渲染器几乎完全控制了性能,因此,如果每秒不对帧进行任何上限,则应该使用纯蓝色淹没整个图形长方形。

问题在于,探查器显示的代码只是调用我在上面选择的区域中的轮询输入和dll:

DLL调用

请注意,的另一个调用DispatchRenderFrame是进行OpenGL调用,当我完全删除它时,它对程序没有影响,因此您可以忽略它。这可能意味着下面看到的用户输入也不会影响微笔画问题...但是我无法删除它,因为它是我用于窗口管理(OpenTK)的库的一部分。

我不确定CLR Worker线程是什么或正在做什么。它也发生在vsync一个(希望平滑分析一个)中,因此即使我不知道它是否是罪魁祸首,我猜也可能不是,但我不确定,因为它显示在“所需的vsync示例”也位于同一常规位置。

是否发生了一些中断,操作系统正在接管但未恢复我的线程,因为它被归类为CPU吞噬?只是一个想法...但是在示例中再次显示了蓝色条,因此我认为该Main线程实际上并未在我突出显示的内容中处于睡眠状态,并且实际上正在运行?

如您所见,我不确定突出显示的时间段是在告诉我什么,这是我需要帮助的地方。我不知道为什么此时代码中的等待百分比如此之高,或者从这里何处去进一步诊断问题。

编辑:我对Stopwatch类进行了一些粗略的剖析,以查看导致尖峰的位置,并且尖峰来自计算部分。OpenGL调用均不会导致任何延迟。它纯粹是在执行数学运算和访问数据的功能的函数内部发生的,或者写入预先分配的结构数组中。


额外说明:

这也让我好奇是否有办法让我强制使用,以使C#虚拟机获得尽可能多的CPU使用率?

没有产生垃圾。这不是 GC问题。我不能在申请期间运行GC,所以不会产生垃圾。渲染函数中的所有内容都是堆栈上的所有结构,唯一一次进入堆管理对象的是池化数组,其大小足以容纳所有渲染数据。它在探查器中出现的唯一时间是在开始和结束时,但是在渲染阶段不会运行。

c# performance opentk

11
推荐指数
1
解决办法
412
查看次数

使用Linq的Where/Select过滤掉null并将类型转换为不可为空的方法不能做成扩展方法

假设我有

List<MyObject?> list = ...;
Run Code Online (Sandbox Code Playgroud)

我想把它变成List<MyObject>,但我无法删除可为空的引用。

下面是一个 MCVE。在我的项目中,我将可空引用警告转换为错误,因此下面注释掉的行将无法编译。

如果我这样做,.Where(e => e != null).Select(e => e!)那么在最新的 .NET Core 3.1.100 中就可以了,但是我无法将其提取到扩展方法中。

我尝试添加此扩展方法

    public static IEnumerable<T> NotNull<T>(this IEnumerable<T> enumerable)
    {
        return enumerable.Where(e => e != null).Select(e => e!);
    }
Run Code Online (Sandbox Code Playgroud)

但是它不会转换IEnumerable<MyObject?>IEnumerable<MyObject>,我不确定为什么。这导致我出现如下错误:

[CS8619] 类型“列表”的值中引用类型的可空性与目标类型“列表”不匹配。

有没有办法让NotNull上面的功能以某种方式工作?

c# linq c#-8.0 nullable-reference-types

11
推荐指数
3
解决办法
2800
查看次数

Vulkan 可以做哪些 OpenGL 4.6+ 不能做的具体事情?

我正在研究继续使用 OpenGL 还是考虑使用 Vulkan 迁移来进行密集的瓶颈渲染对我来说是否更好。

但是,我不想在没有被告知的情况下进行跳跃。我一直在寻找 Vulkan 为我提供的好处,但是通过大量的谷歌搜索,我无法确切地找到可以提高性能的原因。人们会抛出诸如“OpenGL 慢,Vulkan 快得多!”之类的术语。或“低功耗!” 对这个话题不再多说。

因此,我很难评估我面临的问题是否是 Vulkan 可以帮助我解决的问题,或者我的问题是否是由于数量和计算造成的(在这种情况下,Vulkan 对我帮助不大) .

我假设 Vulkan 不会神奇地使管道中的事情变得更快(因为对于相同的缓冲区、制服和着色器,OpenGL 和 Vulkan 之间的三角形着色将大致相同)。我假设在 OpenGL 中导致悲伤的所有事情(例如:帧缓冲区和着色器程序更改)在任何一个 API 中都将同样痛苦。

我认为 Vulkan 提供了一些基于在线阅读无数内容的想法(我猜这肯定不是所有优点,或者这些是否属实):

  • 没有[多?任何?] 绑定(或者更确切地说是“无绑定纹理”的更好版本),当我切换到无绑定纹理时我注意到我获得了显着的性能提升,但如果无绑定纹理有效,这甚至可能不值得作为一个点这样做,因此我不确定 Vulkan 是否在这里添加了任何内容

  • 通过组合某种可以在 GPU 上执行而无需发送大量数据的命令列表来减少 CPU/GPU 通信

  • 能够以 OpenGL 无法实现的多线程方式进行接口

但是,我不知道人们在现实世界中遇到哪些需要这些的情况,以及 OpenGL 如何限制这些情况。到目前为止,网上的所有例子都说“你可以跑得更快!” 但我还没有看到人们如何使用它来跑得更快。

我在哪里可以找到回答这个问题的信息?或者你知道一些具体的例子可以为我回答这个问题吗?也许更好的问题是人们在使用 OpenGL(或 D3D)时导致 Vulkan 成为一种东西的典型痛点在哪里?

一个不令人满意的答案的例子是这样的回应

您可以多线程并更快地向 Vulkan 提交内容。

但更令人满意的回应将类似于

在 Vulkan 中,您可以多线程处理您对 GPU 的提交。在 OpenGL 中,您不能这样做,因为您依靠实现来代表您进行适当的锁定和放置围栏,这可能最终会造成瓶颈。一个简单的例子是[这里的简短示例,OpenGL 没有针对情况 X 切断它],而在 Vulkan 中,它由 [动作 Y] 解决。

上面的最后一段可能并不准确,但我试图举例说明我要寻找的内容,而不会试图写出非常错误的东西。

opengl vulkan

9
推荐指数
2
解决办法
1751
查看次数

C#10 的只读记录结构是否保证与显式实现具有相同的大小和字段对齐方式?

我做需要连续数据的事情。现在使用 C# 10,我们可以执行public readonly record struct.

我喜欢记录所具有的自动 ToString 功能,所以为我完成这个功能真是太好了。

因此,以下等价吗?

[StructLayout(LayoutKind.Sequential, Pack = 4)]
public readonly struct MyVector
{
    public readonly float X;
    public readonly float Y;
    public readonly float Z;

    public MyVector(float x, float y, float z)
    {
        X = x;
        Y = y;
        Z = z;
    }
}
Run Code Online (Sandbox Code Playgroud)

与简洁的 C# 10 版本相比

[StructLayout(LayoutKind.Sequential, Pack = 4)]
public readonly record struct MyVectorRecord(float X, float Y, float Z)
{
}
Run Code Online (Sandbox Code Playgroud)

或者我这样做会不小心踩到任何地雷吗?我的意思是,是否有任何事情在幕后进行,使得record我上面写的内容不能达到我想要的连续包装效果?我不能让记录插入填充、间距或做任何奇怪的事情。

我没有使用带有记录结构的向量类,而是将其用于说明目的。您可以忽略“浮点相等比较”之类的内容,因为我只关心是否可以将其传递给需要 X/Y/Z 连续序列的库。

c# structlayout c#-10.0

8
推荐指数
1
解决办法
6074
查看次数

使用JavaFX Tasks正确执行多线程和线程池

我有一个选项,用户可以从FileChooser提交多个文件,以便由某些代码处理.结果将是用于读取文件的IO,然后是对存储数据的实际繁重计算.允许用户选择多个文件,并且由于文件处理不依赖于所选择的任何其他文件,因此使用线程更容易处理此问题.

此外,用户需要有一个按钮列表,每个要取消的任务一个,以及"全部取消"按钮.因此,我必须考虑选择性地或集体地杀死一个或所有任务的能力.

最后一个要求是我不会让用户通过打开大量文件来阻塞系统.因此,我想到了一个线程池数量有限的线程池(让我们假装我将它设置为4,任意数字).

我不确定如何正确地设置这一切.我有我需要做的逻辑,但使用正确的类是我被困的地方.

我已经检查了这个资源,所以如果答案是某种方式,那么我就误读了这篇文章.

  • 是否有任何JavaFX类可以帮助我解决这种情况?

  • 如果没有,我将如何将任务与某种线程池混合?我是否必须创建自己的线程池,或者是否已经为我提供了一个?

  • 我是否在一个包含我愿意允许用户的最大线程数的单个地方?

我更喜欢使用已经在Java库中的一个,因为我不是多线程专家,并且担心我可能做错了.由于线程错误似乎是这个星球调试上最邪恶的东西,我想非常努力,以确保我这样做尽可能正确.

如果没有办法做到这一点,我必须推出自己的实现,那么最好的方法是做什么?

编辑:我应该注意,我通常是线程的新手,我之前使用过它们并且我正在阅读它们的书籍,但这将是我对它们的第一次主要用途,我真的很想做到这一点.

java multithreading javafx

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

Spring 的 @PreDestroy 导致随机记录而不记录

我正在使用 Spring,并且在终止时我让 @PreDestroy 清理 bean。我不明白为什么随机记录有时会成功,而在其他情况下会失败。

// Using Log4j2
Logger log = LogManager.getLogger(MyClass.class);

@PreDestroy
public void close() {
    log.warn("Test");
}
Run Code Online (Sandbox Code Playgroud)

有时我什么也得不到(没有记录“测试”),有时我会得到:

[13:48:44] INFO  MyClass: Test
Run Code Online (Sandbox Code Playgroud)

如果我包含System.out.println("Is this run?");在 close() 方法中,它将始终打印。

我实际上不确定发生了什么。我不知道是不是因为 JVM 正在关闭并且记录器被杀死......但我认为这会引发某种异常?

请注意,日志记录同时记录到文件 + 标准输出中,我不知道这是否会影响任何事情。日志记录适用于其他无数的数千行代码,但不是这个。

注意:如果它最终成为这个特定的库,我愿意切换日志库。

编辑: MyClass 将是 spring.xml 文档中的一个 bean。

java logging spring

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

当非原子时,C++成员更新临界区内的可见性

我偶然发现了以下Code Review StackExchange并决定阅读它以供练习.在代码中,有以下内容:

注意:我不是在寻找代码审查,这只是链接代码的复制粘贴,因此您可以专注于手头的问题而不会干扰其他代码.我对实现'智能指针'不感兴趣,只是了解内存模型:

// Copied from the link provided (all inside a class)

unsigned int count;
mutex m_Mutx;

void deref()
{
    m_Mutx.lock();
    count--;
    m_Mutx.unlock();
    if (count == 0)
    {
        delete rawObj;
        count = 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

看到这一点让我立刻想到"如果两个线程何时进入count == 1并且两者都没有看到彼此的更新怎么办?最终可以看到count为零和双重删除?并且两个线程可能导致count变为-1然后删除从不发生?

互斥锁将确保一个线程进入临界区,但这是否保证所有线程都会正确更新?C++内存模型告诉我什么,所以我可以说这是一个竞争条件?

我查看了内存模型cppreference页面std :: memory_order cppreference,但后一页似乎处理了一个原子参数.我找不到我想要的答案,或者我误解了它.任何人都可以告诉我,我所说的是错误还是正确,以及这段代码是否安全?

如果代码坏了则更正代码:

这是否正确的答案将计数变成原子成员?或者这是否有效并且在释放互斥锁上的锁之后,所有线程都看到了值?

如果这被认为是正确的答案,我也很好奇:

注意:我不是在寻找代码审查并试图查看这种解决方案是否能解决与C++内存模型相关的问题.

#include <atomic>
#include <mutex>

struct ClassNameHere {
    int* rawObj;
    std::atomic<unsigned int> count;
    std::mutex mutex;

    // ... …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading atomic

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

C# NET 5.0 源生成器基本示例不生成输出

我正在尽可能地复制Microsoft 网站示例中的所有内容,但没有生成任何内容。我创建了一个 MCVE 来尝试找出发生以下错误的原因:

Warning CS8034  
Unable to load Analyzer assembly C:\Users\me\source\repos\SourceGenTest\SourceGenerators\bin\Debug\netstandard2.0\SourceGenerators.dll: 
Could not find file 'C:\Users\me\source\repos\SourceGenTest\SourceGenerators\bin\Debug\netstandard2.0\SourceGenerators.dll'.
SourceGenLibrary        1   Active
Run Code Online (Sandbox Code Playgroud)

我已经检查了提供的路径,并且SourceGenerators.dll存在。这个错误对我来说毫无意义。

注意:在我提供的 MCVE 中,显然没有构建警告。不知道为什么,但源生成器仍然没有输出。

我的目标是拥有这样的工作流程:

SourceGenerators (class library)
    is consumed by
        SourceGenLibrary (class library)
            is consumed by
                SourceGenConsole (Console project)
Run Code Online (Sandbox Code Playgroud)

我希望分析器在类库中生成将在许多项目之间共享的定义。上述工作流程将其简化为一个依赖于一个库的项目,该库依赖于源生成器以尽可能保持 MCVE。

因为复制所有这些东西很烦人,如果你懒的话,这里有一个上传链接:下载链接 MCVE(据说发布后一周到期,但来源如下)。

相关信息:

$ dotnet --version
5.0.201

$ dotnet --list-sdks
5.0.103 [C:\Program Files\dotnet\sdk]
5.0.201 [C:\Program Files\dotnet\sdk]
Run Code Online (Sandbox Code Playgroud)

这些是源文件及其包含的内容。

/SourceGenTest.sln

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 …
Run Code Online (Sandbox Code Playgroud)

.net c# sourcegenerators

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

了解何时调用 glBindBufferBase

我有一些 SSBO 可以在着色器中访问。让我们说它是这样的

layout(std430, binding = 2) readonly buffer MyBuffer
{
    int myData[];
};
Run Code Online (Sandbox Code Playgroud)

什么时候打电话比较合适glBindBufferBase

现在我做类似的事情

glBindBuffer(GL_SHADER_STORAGE_BUFFER, name)
glBufferData(...)
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, name)
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0)
Run Code Online (Sandbox Code Playgroud)

我不知道这是否会设置一些全局状态,从而为我绑定和取消绑定的每个着色器设置索引 2。

你能告诉我这个想法是否有任何缺陷:

Create, Bind SSBO, upload data, unbind for the SSBO

Bind shader
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, name)
Draw arrays
Unbind shader
Run Code Online (Sandbox Code Playgroud)

这是预期的使用方式吗?我只绑定一次SSBO,上传,然后就不再绑定了。这似乎有效,但我不知道它是否“正常工作”,因为我的 GPU 试图对我来说变得聪明,或者我是否违反了规范(我经历过但找不到这个问题的答案)。我曾经遇到过这样的情况:我做了一些可以在我的 GPU 上运行的事情,但在另一个 GPU 上却失败了,这让我对自己正在做的事情犹豫不决。

理想情况下,我希望进行一次函数调用,将 SSBO 交换到某种绑定中,然后进行绘制。我不确定是否可以在绑定着色器之前执行此操作,或者是否必须绑定着色器。如果有更好的方法来做到这一点,请建议。

简而言之,最终目标是在某些索引准备好用于上传数据后将某些 SSBO 绑定到某个索引上的最小方法。

opengl

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