小编Ale*_*lex的帖子

如果语句的计算结果为false,但仍然分支,就好像它是真的一样

我很难过.在异步方法中,我有一些初始保护语句,如果满足特定条件则抛出异常.

其中之一是以下内容:

var txPagesCount = _transactionPages.Count;
if (txPagesCount == 0)
    throw new InvalidOperationException(string.Format("Cannot commit transaction {0}. It is empty.", _txId));
Run Code Online (Sandbox Code Playgroud)

这应该确保_transactionPages字典中有页面,如果没有则抛出.

这是我运行时发生的事情(发布和调试版本,附加调试器):

页数为3

所以字典中的页数是3.

if语句的计算结果为false

因此,正如预期的那样,将3比0的if语句评估为false.

但是,当进一步迈进时:

进入分支的步骤

它进入分支,好像if语句计算为true,并抛出异常.

我在这里错过了什么?

UPDATE

当我这样做:

private static readonly object _globalLock = new object();

public async Task<Checkpoint> CommitAsync(PageNumber dataRoot, PageNumber firstUnusedPage)
{
    lock (_globalLock)
    {
        if (IsCompleted)
            throw new InvalidOperationException(string.Format("Cannot commit completed transaction {0}", _txId));
        var txPagesCount = _transactionPages.Count;
        if (txPagesCount == 0)
            throw new InvalidOperationException(string.Format("Cannot commit transaction {0}. It is empty.", _txId));
    }
Run Code Online (Sandbox Code Playgroud)

if语句不分支以抛出异常.调试和发布版本都是这种情况.是什么搞砸了调用堆栈?另外,如果不是我 …

c# debugging exception-handling exception

18
推荐指数
1
解决办法
757
查看次数

如何防止在Windows临时删除关闭文件上打开的内存映射刷新到磁盘

更新2/TL; DR

是否有一些方法可以防止由于关闭在这些文件上打开的内存映射而刷新Windows临时删除关闭文件的脏页.

是.如果您在初始创建后不需要对文件本身执行任何操作,并且实现了一些命名约定,则可以通过本答案中说明的策略实现.

注意:我仍然非常有兴趣找出导致行为有如此大的差异的原因,具体取决于地图的创建方式和处理/取消映射的顺序.


我一直在研究一些进程间共享内存数据结构的策略,它允许通过使用一系列"内存块"来增加和缩小它在Windows上的承诺容量.

一种可能的方法是使用页面文件支持的命名内存映射作为块内存.这种策略的一个优点是可以用来SEC_RESERVE保留一大块内存地址空间并使用VirtualAllocwith 逐步分配它MEM_COMMIT.缺点似乎是(a)要求具有SeCreateGlobalPrivilege允许在Global\命名空间中使用可共享名称的权限,以及(b)所有提交的内存都有助于系统提交费用的事实.

为了克服这些缺点,我开始研究使用临时文件支持的内存映射.即内存映射在使用FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY标志组合创建的文件上.这似乎是一种推荐的策略,根据例如此博客文章应该防止将映射的内存刷新到磁盘(除非内存压力导致脏映射页面被分页).

然而,我观察到在拥有进程退出之前关闭映射/文件句柄会导致脏页被刷新到磁盘.即使视图/文件句柄不是创建脏页面的那个句柄以及在不同视图中页面被"弄脏"之后打开这些视图/文件句柄时,也会发生这种情况.

似乎更改处理顺序(即首先取消映射视图或首先关闭文件句柄)对启动磁盘刷新的时间有一些影响,但不会影响发生刷新的事实.

所以我的问题是:

  • 有没有办法使用临时文件支持的内存映射,并防止它们在关闭映射/文件时刷新脏页,考虑到进程/多个进程中的多个线程可能有这样一个文件的打开句柄/视图?
  • 如果不是,观察到的行为的原因是什么?
  • 你知道我可能忽略的另一种策略吗?


更新 一些附加信息:在两个独立(独立)进程中运行下面示例代码的"arena1"和"arena2"部分时,"arena1"是创建共享内存区域的进程,"arena2"是打开的进程它们,对于具有脏页的地图/块,观察到以下行为:

  • 如果在"arena1"过程中的文件句柄之前关闭视图,它刷新这些块在磁盘的什么似乎(部分)的同步过程(即它会阻止几秒钟的处置线程),独立与否的"arena2"流程开始了.
  • 如果在视图之前关闭文件句柄,则只对那些在"arena1"进程中关闭的地图/块进行磁盘刷新,而"arena2"进程仍然具有对这些块的打开句柄,并且它们看起来是"异步"的,即不阻止应用程序线程.

请参阅下面的(c ++)示例代码,该代码允许在我的系统上重现问题(x64,Win7):

static uint64_t start_ts;
static uint64_t elapsed() {
    return ::GetTickCount64() - start_ts;
}

class PageArena {
public:
    typedef uint8_t* pointer;

    PageArena(int id, const char* base_name, size_t page_sz, size_t chunk_sz, size_t n_chunks, bool dispose_handle_first) : …
Run Code Online (Sandbox Code Playgroud)

language-agnostic windows winapi temporary-files memory-mapped-files

15
推荐指数
1
解决办法
1510
查看次数

专有XML文件中的二进制字段编码/序列化格式(Roche LC480 .ixo文件)

我最近收到了由Roche LightCycler 480仪器生成的示例导出文件.它使用专有的XML格式,我还没有找到规范.

从这些类型的文件中,我想提取一些与我的目的相关的信息.尽管大部分内容都可以轻松解析和解释,但它包含许多(未填充)基本64位编码字段的二进制/序列化数据,表示整数和/或浮点数的数组.可以在此要点中找到示例文件的链接.

我在这篇文章的最后加入了一些片段.它AcquisitionTable包含总共19这样的编码item条目.这可能代表integer(SampleNo)和浮点(Fluor1)值的数组.

如何将解码的字节转换为整数或浮点值仍然不清楚.当base 64解码时,每个项以下面的(十六进制)6字节序列开始:

42 41 52 5A 00 00 ...    // ['B','A','R','Z','\0','\0', ...]
Run Code Online (Sandbox Code Playgroud)

请注意,虽然我期望每个"项目"包含相同数量的数字(或此表中的"行"),但我观察到类似项目的不同数量的已解码字节:5654 for Fluor1和5530 for Fluor2.

另外,对于那些我怀疑包含(顺序)整数的数组,可以观察到一个模式:

SampleNo : ... 1F F5 1F 07 2F 19 2F 2B 2F 3D 2F 4F 2F 61 2F 00 73 2F 85 2F 97 2F A9 2F BB 2F CD 2F DF 2F F1 2F 00 03 3F 15 3F 27 ...
Cycles …
Run Code Online (Sandbox Code Playgroud)

java encoding serialization mfc binary-data

10
推荐指数
1
解决办法
510
查看次数

如何从Fenwick树中有效地找到连续的已用/空闲插槽范围

假设我正在跟踪Fenwick树中插槽的使用情况.例如,让我们考虑跟踪32个插槽,导致Fenwick树布局,如下图所示,其中网格中的数字表示底层数组中的索引,其中计数由Fenwick树操纵,其中每个单元格中的值为该段中"已使用"项的总和(即阵列单元23存储范围[16-23]中使用的时隙量).最低级别的项目(即单元格0,2,4,...)只能具有值"1"(使用的槽)或"0"(空闲槽).

Fenwick树布局示例

我正在寻找的是一种有效的算法来查找给定数量的连续空闲时隙的第一个范围.

为了说明,假设我有如下图所示的Fenwick树,其中总共使用了9个插槽(请注意,为了清晰起见,仅添加浅灰色数字,而不是实际存储在树的数组单元中).

示例树

现在我想找到例如10个空闲插槽的第一个连续范围,它应该找到这个范围:

搜索结果示例

我似乎无法找到一种有效的方法,这让我有点头疼.请注意,由于所需的存储空间量对我的目的而言至关重要,因此我不希望将设计扩展为细分树.

对O(log N)类型的解决方案的任何想法和建议都将非常受欢迎.

编辑

赏金期限到期后的更新时间.感谢所有意见,问题,建议和答案.他们让我重新思考问题,教会了我很多并向我指出(再一次,有一天我可以学到这一课),我应该更多地关注我在提问时要解决的问题.

由于@Erik P是唯一一个对包含所请求的代码/伪代码的问题提供合理答案的人,因此他将获得赏金.

他还正确地指出使用这种结构的O(log N)搜索是不可能的.荣誉对@DanBjorge提供一个证明,让我想想最坏情况下的性能.

@EvgenyKluev的评论和回答让我意识到我应该以不同的方式提出我的问题.事实上,我已经在很大程度上做了他的建议(参见https://gist.github.com/anonymous/7594508 - 显示我在发布此问题之前遇到的问题),并问这个问题,希望能有效率搜索连续范围的方法,从而防止将此设计更改为段树(这将需要额外的1024字节).然而,似乎这种改变可能是明智之举.

对于任何感兴趣的人,可以在这里找到与此问题中使用的示例匹配的二进制编码Fenwick树(以64位编码的32插槽fenwick树):https://gist.github.com/anonymous/7594245 .

algorithm data-structures fenwick-tree range-query

9
推荐指数
1
解决办法
1604
查看次数

在Windows 10 Universal App中尝试使用JSON.NET反序列化对象失败,并出现FileNotFoundException

我正在使用Windows 10 Preview SDK,并尝试移植一些依赖于JSON.NET的代码.它失败了以下例外:

{"无法加载文件或程序集'System.Runtime.Serialization,Version = 2.0.5.0,Culture = neutral,PublicKeyToken = 7cec85d7bea7798e,Retargetable = Yes'或其中一个依赖项.系统找不到指定的文件.":" System.Runtime.Serialization,Version = 2.0.5.0,Culture = neutral,PublicKeyToken = 7cec85d7bea7798e,Retargetable = Yes"}

我可以看到对象浏览器中存在该命名空间,因此我不确定缺少什么或如何解决此错误.这似乎阻止了我的应用程序移动.

c# json.net windows-runtime windows-10

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

如何暂停BackgroundWorker?或类似的东西

BackgroundWorker通过WebClient.DownloadString在循环内调用来使用a 来下载一些网站.我希望用户在下载内容时取消选项,所以CancelAsync每当我发现CancellationPending在循环中间打开时我都会打电话.

但是现在我注意到函数DownloadString有时会冻结,所以我决定使用DownloadStringAsync(所有这些都在创建的其他线程中BackgroundWorker).因为我不想通过在调用之后退出循环和函数来重写我的整个代码,所以在调用DownloadStringAsync之后我做了一个while循环,它什么也没做,只是检查一个变量bool Stop,我在DownloadStringCompleted事件处理程序时变为true 被叫或当用户请求取消操作时.

现在,奇怪的是它在调试版本上运行良好; 但是在第一个版本中,程序会在while循环中冻结,就好像它是主线程一样.

c# backgroundworker request-cancelling cancellation

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

Windows fsync(FlushFileBuffers)与大文件的性能

从确保数据在磁盘上的信息(http://winntfs.com/2012/11/29/windows-write-caching-part-2-an-overview-for-application-developers/),即使是在例如停电,似乎在Windows平台上,您需要依靠其"fsync"版本FlushFileBuffers来最好地保证缓冲区实际上是从磁盘设备缓存刷新到存储介质本身.如果此信息正确,则FILE_FLAG_NO_BUFFERINGwith 的组合FILE_FLAG_WRITE_THROUGH不会确保刷新设备缓存,而只会影响文件系统缓存.

鉴于我将使用相当大的文件,需要"事务性地"更新,这意味着在事务提交结束时执行"fsync".所以我创建了一个小应用来测试这样做的性能.它基本上使用8次写入执行一批8个内存页大小的随机字节的顺序写入,然后刷新.批处理循环重复,在每隔这么多的书面页面之后记录性能.此外,它有两个可配置的选项:在开始页面写入之前,对刷新进行fsync以及是否将字节写入文件的最后位置.

// Code updated to reflect new results as discussed in answer below.
// 26/Aug/2013: Code updated again to reflect results as discussed in follow up question.
// 28/Aug/2012: Increased file stream buffer to ensure 8 page flushes.
class Program
{
    static void Main(string[] args)
    {
        BenchSequentialWrites(reuseExistingFile:false);
    }
    public static void BenchSequentialWrites(bool reuseExistingFile = false)
    {
        Tuple<string, bool, bool, bool, bool>[] scenarios = new Tuple<string, bool, bool, bool, bool>[]
        { …
Run Code Online (Sandbox Code Playgroud)

c# windows performance fsync

7
推荐指数
2
解决办法
5677
查看次数

寻求的解释/信息:Windows使用"fsync"(FlushFileBuffers)写入I/O性能

这个问题是我发布的早期问题的后续跟进:Windows fsync(FlushFileBuffers)与大文件的性能.在哪里我找到了可能的解决方案,但也有新问题.

在对不同的情节进行基准测试时,我发现了许多令人惊讶的结果.我希望有人可以帮助解释或指出我解释这些结果的信息方向.

这个基准测试的作用是按顺序将8个页面(32 K)的随机块(大4096字节)写入文件,然后刷新写入.它总共写了200000页,总计800 MB和25000次刷新.在开始写入之前,文件的大小设置为其最终长度.

它支持总共4个选项,其中运行所有组合:

  • FlushFileBuffers在写入批处理或正常刷新(NS)之后执行"fsync"/ 操作(FS).
  • 在开始写入(LB)或将文件保留为空(E)之前将单个字节写入文件的最后位置.
  • 使用正常缓冲的写入(B)或无缓冲/写通式(WT)写入(使用FILE_FLAG_NO_BUFFERING和FILE_FLAG_WRITE_THROUGH).
  • 直接写入文件流,即通过文件句柄(F)或使用存储器映射(MM)间接写入文件.

下表总结了我对我的系统(具有慢速主轴磁盘的64位Win 7笔记本电脑)的所有这些选项组合的发现.

所有选项组合的基准测试结果

我发现的是,"fsynced"缓冲写入的性能与文件的一个令人难以置信的低吞吐量的大小,使大型文件这样做不可行组合呈指数下降.如果文件的最后一个字节写入(选项LB),吞吐量甚至更低,所以我担心在随机而不是顺序写入情况下,性能将更加显着.

然而令人惊讶的是,对于无缓冲/写入I/O,吞吐量保持不变,与文件大小无关.最初(前100-200 MB)它的吞吐量低于缓冲写入,但之后平均吞吐量迅速赶上并且完成写入800 MB的速度更快.更令人惊讶的是,如果文件的最后一个字节写入,吞吐量会增加2倍.

通过内存映射文件写入文件时,可以看到相同的指数性能下降,同样在使用无缓冲/写入标志打开文件的情况下.在这里,如果文件有一个字节写入其最后位置,性能会更差.

UPDATE 基于霍华德的解释这里这里,我重新测试,而无需启动之前写创建一个新的文件(即打开现有的,充分的书面文件,并覆盖它).我已更新原始问题中的代码,以反映此测试所做的更改.结果部分符合他对Linux的解释和发现.但有一些值得注意的例外.下表给出了结果,红色亮点显著的变化,蓝色的亮点,其中的变化并没有出现,这是令人惊讶的(即不符合预期,如果在霍华德的解释中提到的效应在作怪唯一的).

覆盖现有文件时的结果

对于具有"fsync"刷新的缓冲写入文件(即不通过memmap),性能现在已经从指数衰减变为恒定趋势.但是,它现在比以前的测试场景需要更长的时间.吞吐量是一个恒定的1.5 MB/s,在它开始之前大约20 MB/s,指数衰减到1.5 MB/s左右.看起来可能的解释是文件元数据也会在每次刷新时被刷新,从而导致完整的磁盘革命以寻找元数据的位置.

对于"直写"到文件场景,写入最后一个字节的结果现在是相同的,与霍华德的解释所期望的一致.

然而,对存储器映射的写入,有一个值得注意的例外,并没有真正改变,这是令人惊讶的.它们在写入性能方面仍然表现出相同的指数衰减(从大约20 MB/s衰减到1.8 MB/s开始).这表明正在发挥不同的机制.一个值得注意的例外是如果基础文件是在没有FILE_FLAG_WRITE_THROUGH的情况下创建的,则执行"fsync"刷新.此方案现在显示恒定(差)性能,吞吐量约为1.6 MB/s.由于我有些疑惑,我多次重复这种情况,每次给出相同的结果.

为了找出多一点,我也使用较小的文件(50000页,共计200 MB),以确认,该FSYNC性能(缓冲I/O)实际上是不依赖于文件大小重新运行该测试.结果显示如下,值得特别注意的结果用红色突出显示.

较小文件的结果

这些结果与较大文件的结果很好地相关.值得注意的变化是,对于那些突出显示的内容,写入更有效,它们似乎达到了大约7 MB/s的限制.

总结为基于对我的系统的观察到目前为止的高度推测性结论:

  • "FSYNC"在Windows上使用缓冲IO文件(即没有FILE_FLAG_WRITE_THROUGH标志)的性能呈指数和已经写入到文件的字节数减少.原因似乎是每次都需要刷新文件元数据,这会导致磁盘搜索到文件的开头.
  • 写入内存映射文件时,Windows上的"fsync"性能也会以指数方式降低性能.我目前没有解释造成这种情况的确切机制.

鉴于这种观察到的性能,至少在我的用例中,这两个I/O选项并不代表可行的解决方案.

根据Greg的建议,我将在关闭Windows磁盘缓存的情况下重新运行测试,并且我还将运行Howard提供的基准代码,以排除由于我自己的错误而导致结果偏差的可能性.

更新2 我已完成测试,目前正在编译结果.为了不写"完整的历史",我将用结果,发现和一些结论的摘要替换这个问题的当前内容.霍华德在这个问题上的答案,以及在.NET代码旁边运行他的c基准代码的能力是最有用的.应用程序的结果相关性很好.Rlb的回答帮助我更好地理解了与磁盘相关的"合理数字".谢谢.

问题的一部分仍未得到答复.特别与在写入存储器映射时观察到的降低(和依赖于文件大小)性能有关.这可能与寻找/元数据刷新,但目前尚不清楚,我为什么/如何.

c# windows performance mmap fsync

7
推荐指数
1
解决办法
1526
查看次数

c#SortedList <string,TValue> .ContainsKey表示成功添加的键返回false

检查下面的更新3 我发现我遇到的问题与.Net 4.0,4.0客户端和4.5的c#字符串比较器的已知严重问题有关,这将导致字符串列表的排序顺序不一致(导致输出依赖在输入的顺序和使用的排序算法).该问题于2012年12月向微软报告,并以"不会修复"结束.可以使用一种解决方法,但速度慢得多,对于大型集合来说几乎不实用.

在实现不可变的PatriciaTrie时,我想将其性能与System.Collections.Generic.SortedList进行比较.我使用以下文件https://github.com/rkapsi/patricia-trie/blob/master/src/test/resources/org/ardverk/collection/hamlet.txt来创建用于测试的输入词表.

当使用Comparer<string>.DefaultStringComparer.InvariantCulture作为密钥比较器插入c#SortedList中的每个单词时,使用常规搜索方法无法检索成功插入的多个条目(例如,ContainsKey返回false),但密钥在列表中显示为通过迭代列表观察.

更奇怪的是,比较器在将从排序列表中检索到的密钥与无法找到的搜索密钥进行比较时返回值"0" ContainsKey.

下面的完整示例演示了我的系统上的这个问题.

using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        // the problem is possibly related to comparison.
        var fail = true;
        var comparer = fail ? StringComparer.InvariantCulture : StringComparer.Ordinal;

        // read hamlet (contains duplicate words)
        var words = File
            .ReadAllLines("hamlet.txt")
            .SelectMany(l => l.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries))
            .Select(w => w.Trim())
            .Where(w => !string.IsNullOrEmpty(w))
            .Distinct(comparer) …
Run Code Online (Sandbox Code Playgroud)

c# sortedlist stringcomparer

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

将具体的Task <TImplementation>分配给Task <TInterface>类型的变量

考虑一个Foo完全实现的类IFoo.同时,考虑一项任务Task<IFoo>.

为什么在调用以下内容时会抛出编译错误;

Task<IFoo> task = Task.Factory.StartNew(() => new Foo());
Run Code Online (Sandbox Code Playgroud)

编译器声明它无法从源类型转换Task<Foo>Task<IFoo>.虽然这是有道理的,因为它们本质上是两种不同的类型,它不会与IList<IFoo> list = new List<IFoo>{new Foo(/* construct */)};其他类似的任务处于相同的前提下吗?

目前我正在强迫演员进入界面,但这感觉不必要.

c# inheritance casting interface task-parallel-library

4
推荐指数
1
解决办法
264
查看次数