如何成功进行系统编程,这是您需要了解和理解的,尤其是如果您已经工作了三十年了? C#和性能-是否值得重写您在C#中看到的所有内容? 低级编译器技术等着我们的未来是什么?
今天,在我们的虚拟工作室中,
Alexandre Mutel回答了问题。

Alexandre Mutel是Unity Technologies的首席软件架构师。 此外,他还是知名的开源开发人员,为SharpDX,Markdig,Zio和其他项目做出了贡献,并且自2014年以来,他是Visual Studio和开发技术类别的MVP。
Alexandre致力于实时图形渲染,GPGPU,声音合成,托管语言的有效使用和体系结构,代码生成和文档编制等领域的各种低层和高层问题。
与往常一样,JUG.ru集团的Evgeny Trifonov(
phillennium )和Oleg Chirukhin(
olegchir )进行了采访。

帖子结尾处,另一个著名的捐助者Dylan Beatty感到惊讶-我们自己没想到。
E .:您的职业生涯很长,已经有三十年了-对于初学者,您可以简要谈一下吗?这一切都始于童年-我有了Amstrad PC464。当我开始在这台计算机上编程时,我当时11岁或12岁,我记不清了。 我很快掌握了BASIC编程,并购买了有关游戏开发的书籍:那时似乎很有趣。 我玩过很少的游戏,开发和编写代码更有趣。 然后,我继续为Amstrad编写汇编代码。
16岁时,我得到了Amiga500。我遇到了正在编写演示的家伙-根本不是现在。 现在是WebGL,这是一个完全不同的场景。 我开始写很多演示,但并不总是展示出来,但我只是喜欢用汇编器编写。 就这么简单。
然后他去了一所技术学院学习计算机工程。 与游戏和汇编程序相比,这已经完全不同了。 我喜欢学习以前不知道的东西:操作系统,UNIX,使用C语言(在此之前,我只使用BASIC或汇编程序,因为我没有钱买C / C ++编译器)。
大学毕业后,他开始在货币市场行业工作。 这是纽约一家法国公司的工作。 两年后,我回到了银行。 实际上,我不想在银行工作,我想在游戏开发人员中工作。 但是结果,卡在了一个新的领域,可以学到很多东西。 因此,我在那里呆了8-9年,主要从事Java和C ++的工作。 很多分布式服务器和SQL数据库,正在复制数据库...根本不是我现在正在做的事情。
然后,我休了一些创意假,然后环游世界:我在非洲,南美,亚洲一整年。 旅途改变了我,使我震惊。 当我回来时,我再也无法在IT领域使用计算机了,无法在银行工作。 我辞掉工作,在社会工作者课程中度过了四年,以便与儿童,无家可归者,残疾人和老人一起工作。 我研究了三年,这非常有趣,因为我一生的大部分时间都从事精确科学领域的工作:数学,项目,抽象。 然后他突然带走并搬到了一个非常人道主义的地区。 经过培训,我什至尝试在该领域工作,但是就在这段时间里,我与一个小时候与我一起做过演示的朋友暗示我们可以再做一次。
我开始在业余时间练习演示,很快,与在街上与孩子们一起工作所花的时间很快。 不好 人们说:“我们需要尝试在游戏开发人员中找到工作,为什么不呢? 您可以做到。” 但是我认为这是不可能的,因为我已经很长时间没有使用计算机了,并且很难用我的简历找到IT工作。
我开始研究开源应用程序,并发布了一些公司开始使用的项目。 有一次,这些公司之一与我联系,他们使用了称为SharpDX的最新项目之一。 我和家人一起去了日本-因为我已经有两个孩子了。 我们在日本生活了5年。 这时,我正在使用C#从头开始创建游戏引擎。
大约两年前,我回到法国,开始在Unity工作。 这干扰了我以前的工作,但是他们提出要进行一项非常复杂而有趣的任务,一个真正的测试:制作一个从IL .NET代码生成本机代码的本机编译器。 这正是我一直想做的事情,但是不能做,因为我不会为此而得到报酬。 然后是一个机会,一个巨大的机会。 我在这个项目上工作了2年。
是的,故事似乎不是很短。
E .:没什么,这样的职业值得一试。 基于您的经验,我想问您这个问题。 现在有人说:“摩尔定律不再有效,计算机无法更快运行,我们注定要失败。” 其他人则回答:“来吧,尽管他们没有以相同的速度加速发展,但仍在增长,因此没有理由恐慌。” 既然生产率这个话题就在您身边,并且您一直在关注这个行业很长一段时间,那么您的立场是什么?我坚持这个中庸之道。
(笑)我相信我们开发的许多(即使不是大多数)应用程序从一开始就适应性能要求,从而带来了可能的最佳质量。
亲眼目睹IT行业中发生的一切。 例如,多年来Windows变慢了-Windows Vista等。 实际上,已经做了自然的工作来提高性能,因为多年来对此并不特别担心。 Windows 8发布时,它已经好了一点。 然后Windows 10出现了,它有了一些改进。 因此,与以前相比,我们拥有一个运行良好的系统。 对他们来说,进行这些优化非常重要,因为一旦人们必然会“超出其承受能力”并开始说:“哦! 该软件不再起作用,我们正在切换到Linux,因为它速度更快,更简单。
对于我们开发的所有软件都可以这样说。 令人惊讶的是:一直都有使用本机代码的趋势,甚至在Windows中,他们甚至决定返回C ++,他们说:“ C ++是一种解决方案,.NET速度很慢,然后Garbage Collector等等…… ”。 同样,母语也变得有意义。
同时,借助JIT,Chrome中的V8重新启用了JavaScript。 JS是一种脚本语言,不是超快速的,但有时它的运行速度是C ++的两倍。 这足以使他得以生存,并且我们现在可以将其用于诸如在Visual Studio Code中编写代码之类的事情。 但是,如果您仔细观察,那都是因为性能要求从一开始就被放在这里。 即使在VSCode中,即使通常有很多JavaScript和脚本代码,其他所有内容-V8,渲染堆栈,JIT-所有这些都是使用旨在实现最高性能的语言编写的,即使用C ++。 一切都可以用另一种语言(不一定是C ++)编写,但事实是,所有这些软件都是从一开始就考虑到性能而开发的。
因此,是的,我们可以使用效率较低且生产效率较低的语言,但这仅仅是因为开发所有基础技术都是为了获得出色的
用户体验 。 例如,Visual Studio Code是出色的软件,非常适合开发人员并解决了他们的问题。 许多人说:“尽管我们喜欢使用更多的本机代码编辑器,但现在我们正在切换到Visual Studio Code”-因为他们认为它非常有效。 性能无处不在,但有时我们看不到它,因为它已经嵌入到我们使用的所有内容中。
我们认为:它用JavaScript编写,因为它足够快。 但是JavaScript之所以如此之快,是因为数百名开发工程师已经为优化JIT工作了多年。 现在,我们甚至可以使用脚本语言来编写非常复杂的应用程序。 没有所有准备工作的脚本语言要慢得多。 我们生活在陌生的时代。 我们可以选择,但是仍然有这种表演故事,对于每种语言都一遍又一遍。
因此,.NET是一个典型的例子。 在过去的三到四年中,那里已经做了巨大的工作。 如果您有时查看ASP.NET Core,如果您查看使用CoreCLR完成的所有工作……性能是一件很畅销的事情,它会花费金钱并让您实现更多。 试图满足严格的要求,您可以尝试提高生产力,可以节省电量,在月底节省一些钱-性能影响一切。 当我听到人们说:“一切都井井有条时,我正在开发我的应用程序,它的性能平均,可以做到……”,他们在想什么? 您需要花费一些时间来检查是否可以使您的应用程序更加高效。 如果您可以节省至少十分之一的资源或应用程序时间,那很好。
E .:部分存在一个哲学问题。 您认为Slack并不是技术解决方案的最佳选择,但是您可以在自己的站点上订阅老式RSS。 您是否认为即时通讯的新时代正在使开发人员的生产力下降?不,我不这么认为。 现在,我在远程工作。 在工作中,在Unity上,我们可以远程工作,因此我经常使用Slack与同事进行交流。 这是保持联系并保持生产力的最佳方式。 这需要花费大量时间,因为您需要检查频道等,但是我可以暂时关闭Slack并专注于工作。 当我在公司的露天场所工作时,我别无选择:如果有人想问一个问题,您必须立即回答,那会变得更加复杂。
至于Twitter和电子邮件,我不会经常检查它们。 我每天阅读一两次Twitter,这取决于多种因素:是否参加任何讨论以及讨论的内容。 如果使用诸如Slack之类的东西,则可以加入公司中的不同渠道,可以遵循许多单独工作将无法遵循的主题。 我们需要找到一个中间立场:我们都担心公司中发生的许多事情,但是我们必须要有选择性,因为您不能同时参加所有讨论。 某些人可以阅读这么多频道,我的能力简直让我感到惊讶,但我自己却不是那样。 今天我读了大约30个频道,还不算很多。
E。:谢谢您,抽出时间询问Oleg的问题!答:我的职业生涯与您的职业有些相似:我在一家银行工作,现在在一个完全不同的领域-组织会议,同时我试图弄清楚如何构建编译器。 您能为那些试图从简单的企业Web开发人员转向系统编程的人提供什么建议,对于这种过渡有什么技巧吗? 我敢肯定,我们这里的人不多,最多。不知道是否有准备进行这种过渡的路径。 如果您对此类技术感兴趣,那么您可以做一些普通的作业。 在家里,您可以编写解析器以及与编译器相关的内容。 无需从头到尾编写整个编译器,直到生成机器代码为止。 您开始对编写编译器基础结构感兴趣。 这就是我近年来在Unity工作的过程。 如果您对低层次的事物充满热情,那么这是您可以了解其在现实中如何工作的地方之一。 如何改进工作,值得改进性能的地方以及尚未完成的地方。 如果您担心性能,那么知道应用程序最终将运行在什么位置非常重要。
表演是我的主题,这一切对我来说都是一个很好的机会。 我想从核心(即编译器级别)着手解决问题。 在这里,我们可以在用户需要的那些地方将生产率提高数十倍。 如果我们运行游戏,应用程序,电影或类似的东西,有时可能相对容易达到这种效果。
我对低级事物和编译器组件的热情使我开始了目前的工作。 但这不是我特别想要做的。 有时,当您在使用不同语言方面有很多经验时,就会编写应用程序-您甚至想提出自己的语言。 我开始这样做,但由于工作量过多而停下来,而且我的空闲时间很少。 但是,您有一种潜意识,渴望回归“根源”,尝试做一些自己的事情以理解一切。 当然,我了解编译器的工作方式以及所有这些,但是我不了解需求的复杂性。 复杂的权衡需要处理,例如在内存管理领域。 同时选择要赋予应用程序开发人员更高生产率并有效的功能是非常困难的。 这个问题仍然没有解决到最后。 Rust或.NET将永远无法解决此问题。 Rust非常漂亮,令人惊叹,但是很难使用,尤其是当您使用JavaScript之类的工具切换到Rust时。 但是,有一些Python或JavaScript开发人员正在迁移到Rust的示例,尽管这有些令人惊讶。
答:您提到您最近10年使用C#编程,那么C#有什么用呢? 例如,为什么不使用C ++? C ++似乎是更系统的语言。老实说,我讨厌C ++,我讨厌C,但是我和他们一起工作。 我真诚地相信,它们会导致许多错误,从而导致巨大的开发效率低下。 许多人认为,由于您使用C进行编程,因此实际上您已经在编写快速代码,以使您的程序将面向性能。 这是不对的。 如果您雕刻malloc堆以及所有其他内容,即使与.NET编写的内容相比,它也会很慢。 优秀的C / C ++开发人员被迫使用
区域内存分配器之类的技巧。 您必须将自己埋在一堆没人听说过的奇怪事物中。 尽管在这里,游戏开发人员通常对此有所了解。 至少,AAA开发人员或使用C / C ++框架制作游戏的人。 一些问题源于语言本身的复杂性。 以前,我根本没有阅读过有关C ++的书籍,只是三,四年前,我才开始只阅读有关C ++的书籍,只是为了感受这种语言。 我对此进行了编程,但是我没有一个系统的,正式的方法,但是它的复杂性让我感到震惊,如果您编写不正确的所有内容,那么可能会毁掉的东西数量太多。
就在几个月前,Unity中出现了一个错误,有人在一段C ++代码中犯了一个错误,那是在构造函数中,有些东西是按值传递的,结果,我们从该值中获取了地址并查看了缓存。 实际上,我们所提到的值不再存在于内存中。 所有这些都是因为指针与非指示符混合在一起,并且进行此重构的人员并未检查所有使用位置。 一个完全不同的代码可以正常工作突然停止工作。 这似乎是一个小错误,但它破坏了一切。 实际上,这是使用内存的错误。 所以是的,当我看到这样的事情时,我深信我们必须限制对使用C和C ++的工作的访问,并尽量减少其使用。 在.NET部分,我确实将它们的使用仅限于特定于平台的事物。 但是,用C#编写所有内容非常沉闷。 为了访问API,您需要执行一堆dlopen。 尽管,例如,您可以尝试将所有这些内容封装在C的包装器中,并仅通过一个函数来组织访问。 我宁愿将这些东西隔离开并在C和C ++中进一步开发它们。 但这是关于互操作的狭topic话题,然后您仍使用普通的受控语言,大部分时间使用它,可以享受更快的编译速度。
我讨厌C ++编译器和链接器的错误,我讨厌需要在不同平台上工作,这一切非常非常困难。 您开始在MSVC上进行编译,然后应该切换到Clang,然后切换到GCC。 在Linux,Mac,Windows,Android,iOS等上。 使用C ++是一场噩梦!
我讨厌编辑器中的文件,.h文件和cpp。文件之间的分隔。 人们对语言完全感到困惑,并开始在宏上编程。 我喜欢元编程,但是在现代C ++中,我们可以做到完全疯狂。 这些东西本身就很棒,但实际上已经太多了。
总结一下:是的,我认为我们可以用C#开发有效的软件。 也许没有C ++快,但是可以。 这正是我们在Unity中要尝试的工作-例如,我们正在执行突发编译器来编译C#的特定子集,以实现最高性能,甚至在某些地方比C ++还要多-但仍保留在C#中。 这是完全安全的。 对于指针,您需要声明不安全,不要抛出异常,显式执行所有操作。 这是一次痛苦的经历。 但是仍然可以编写与C ++一样快的代码。 我认为这正是.NET值得发展的方向以及我们应该去的地方。
答:例如,如果我们谈论开放源代码,则.NET Core中有一个垃圾收集器,这是一个非常大且令人恐惧的C文件。 两兆字节的垃圾,最有可能是由某种形式的Lisp生成的(几乎没有多少字母值得手动编写)。 也许用C#重写这里的所有内容是否有意义?是的 我与Microsoft和社区中从事JIT的人聊天。 我确实相信某些东西。 我相信有一段时间,您的语言会变得更加成熟和基础,然后您就必须挑战并测试它的强度。 您需要能够将其用作基础。 证明您甚至可以使用它来创建对性能非常苛刻的内容。 这就是垃圾收集器和JIT的故事。 可以使用C#完成非常大比例的.NET运行时子系统,包括JIT和GC。 如果您制定了一个规则,即在C ++中只能描述基本平台的抽象,这将使大多数运行时平台独立。 如果发生这种情况,我将感到非常高兴。 但这是一项巨大的工作。
我特别喜欢这个主意是有原因的。
我已经谈论过这一点,在C / C ++中重构和改进代码库非常复杂,以至于您有时会停止进行此重构。它太疼了,以至于你不再碰它了。您将不得不手动传输和更改一些文件,因为IDE中的重构工作不佳,例如,模板太多-依此类推。使用C#进行开发时,您可能会对自己的愿望抱有更大的野心。仅仅因为编译时间减少了,添加新的优化程序将变得更快,更容易。减少了测试的迭代时间,等等。很好,例如,在CoreRT中,他们尝试尽可能多地使用C#而不是C ++。情况正在改变。但是我们距离用C#重写.NET GC还差一半。但是我们可以。例如,我知道我可以重写.NET GC,并以不同的方式重写它。几年前,我对GC非常感兴趣,读了有关它的书,写了一些实现GC的原型。 Java社区在Jikes RVM上的工作使我感到惊讶-他们在Java中完成了这项工作。后来,我发现在Golang中,编译器首先是用C编写的,然后是Golang编写的。当我开始阅读Golang编译器的源代码时,我对代码库的组织以及优化的结构感到惊讶。例如,有一个巨大的文件,它描述了可应用于某些指令的允许的优化。指令可以映射为更快的本机指令,所有这些都在一个巨大的文本文件中进行了描述。我在LLVM或.NET JIT中都没有看到这一点。总结一下,是的,使用托管语言应该给我们更多机会编写更好的运行时。答:您谈到了代码的复杂性,错误的危险等等。对我来说,最困难的部分是阅读并理解编译器源代码。例如,这是一个非常大的文件,包含数万行AST转换和中间表示。例如,这是来自Golang的文件。您如何为系统部件编写优质清晰的代码呢?怎么写呢?哈,你说,好像任何事情都有预先准备好的规则!与常规应用程序相比,编译器对代码的要求更高。首先:在设计基础架构时,您必须格外小心。您需要仔细监视重用和隔离性:如果您进行了某些更改,那么在其他地方,所有内容都不会浪费或破坏其余代码。第二:我坚信我们必须在代码中附带大量注释,以解释仅在查看代码时并不明显的内部依赖关系。当他们说:“代码必须自我描述时,我真的不喜欢它!应该很明显!”这是完全错误和误导的。工程师喜欢将这些故事告诉年轻的开发人员,您不应该这样做。例如,当我看到像LLVM这样的代码库时-可能不完美,但是那里有很多注释。例如,当头文件中有一个结构时,注释可以解释该结构的声明位置,为何如此声明,为何存在此类字段。所有这些都是有原因的。如果您不解释这个原因,那么没有人会理解您这样做的原因。如果您只是阅读代码,则任何事情都不会变得清楚。例如,对齐数据以进行有效的缓存,如果您未在注释中进行说明,那么其他人将如何理解所有这些都是为了提高效率?也许以后,甚至您自己也将不得不重新读取整个代码,还原应用程序的整个结构以及数据在内存中的布局,然后才能获得洞察力。但是,如果您没有在代码中添加注释并进行解释,然后其他人会看这一切,然后说:“哇,这里钉牢了,它不是很好用,我会在这里放另一个类并添加一个指针” –从而破坏了一切,因为我不明白,为什么在这里这样做我说这不仅关乎好事,而且关乎糟糕的工作。我不止一次要在代码中插入注释以表示我没有很好地完成这一部分,对此我并不感到骄傲,这个地方需要修复,因为现在我们将其保留为当前形式,但是总有一天有必要返回它并修复它。他解释了这样做的原因:例如,没有足够的时间去做好。您已记录到您仅做了一小部分必要的操作,这很正常。您在此处使用了这样的拐杖,如果尝试更正确地进行操作,则可能会损坏所有东西。但是,即使对于代码效果不佳的那些部分,也必须对其进行解释。因此,评论是第二位。对我来说,第三个是测试。需要做更多的单元测试。从较低级别开始,没有大型集成测试(即小型单元测试)来检查API的各个部分。因此,您的应用程序将随着时间的推移而改进。例如,我写的SharpDX完全没有测试。在撰写本文时,他还不错。但是事实是,在业余时间我不是为人们而是为我自己创建的。我想访问DirectX C ++ API,该API已经在C ++中可用。多年来,我已经验证了一切正常。但是每次进行任何更改时,都必须再次检查功能。最近几年,我转到了其他项目:没有时间了,我不再使用它了。然后一位来自开源社区的开发者来了,在单独的程序包中分配了编译器,并尝试与此做一些与SharpDX分离的操作。事实是,由于我们没有进行单个测试,因此我没有完全测试此PR。它只是冻结了他的拉动请求(看起来很完美)。他开始在单独的应用程序上对其存储库进行小型测试。但是我们没有考虑到某些因素,SharpDX本身在某些版本中完全损坏。立刻,人们出现了以下形式的问题:“为什么这种方法会导致异常?”在随后的项目(开源项目和工人项目)中,我尝试在测试方面非常有意识,甚至定期尝试扩大覆盖范围。但是,要达到90%的覆盖率是很沉闷的。有时候真实的测试结果太奇怪了,您只是为了调试而编写了它们,却无法将其存放在掩护之下,您不想将其拖到您的代码中。总的来说,是的,我相信这是需要非常仔细地处理的三件事:体系结构,注释,测试。答:编译器是一个完全古老的领域,对吗?这个故事始于上世纪中叶。您认为对于现代开发人员和编译器公司而言,最重要的挑战是什么?我认为当今的主要挑战是创建一个可以有效地使用SIMD的编译器。这确实是一个挑战,使编译器很难回答,因为通常会在以后添加SIMD和类似的优化,而不必一定从编译器的一开始就添加。 (对于LLVM,它们可能是从一开始就提供的)。事实是,这给优化器带来了许多新问题,他必须能够正确执行它们。如您所见,例如,编译器现在很难自动对代码进行矢量化处理。他们可以以某种形式做到这一点,但有时手动进行起来更容易。编译器无法确定所有要优化的位置,结果生成了效率低下的代码。这是一个困难的话题。英特尔中的一些公司正在努力为LLVM添加矢量化技术。该项目已经开发了好几年,总的来说,这只是对上游LLVM进行这些更改的准备。它们还不存在,这是非常困难的,并且将需要数年。 LLVM是一个非常好的系统,即使仅仅是因为它在.NET中缺少某些东西。利用SIMD,CPU和不同的内核-这将是最大的现代挑战。例如,这就是为什么将向量内在函数添加到.NET语言的原因-您可以显式使用向量化器和SIMD指令。但是在许多情况下,例如循环,人们可能期望自动向量化。CPU和不同的内核-这将是最大的现代挑战。例如,这就是为什么将向量内在函数添加到.NET语言的原因-您可以显式使用向量化器和SIMD指令。但是在许多情况下,例如循环,人们可能期望自动向量化。CPU和不同的内核-这将是最大的现代挑战。这就是为什么将向量内在函数添加到.NET语言的原因-您可以显式使用向量化器和SIMD指令。但是在许多情况下,例如循环,人们可能期望自动向量化。在此之前,我会说:“我们需要将编译器作为服务,将编译器作为库。”今天,它不再是一个问题。人们开始相信这些想法的用处。因此,LLVM变得如此著名:它从一开始就作为一个编译器库开发的,您可以在其中使用所需的任何语言。例如,与C#中的Roslyn相同,那里也有一个编译器。当然,该编译器不是同一类型,但是仍然可以在本机代码中使用。我认为现在每个人都已经了解了这些事情,人们已经意识到编译器很有用。因此,对我来说,兼容SIMD的代码更为重要。着眼于GPU,CPU进行编程,所使用的内核数量仅仅是个开始。我们有6、8、16、42个核心。在某个时候,它们的增长将开始,我们必须为此做好准备,尽可能高效地利用所有这些力量。.: Markdown Markdig, ? , Markdown? , ?是的,对我而言,Markdown是一种编写开发人员喜欢的文档的方式。最有可能的是,这并不适合那些仍然发现更容易使用Word或类似工具的普通人。但是对于开发人员来说,这是很好的。多年来,开发人员使用了什么?文本文件以不同的方式标记了其中的标题,依此类推。那是正常的。您知道,这是在Internet上阅读RFC的方法-一堆文本文件格式非常有限,制作得很好,但没有形式化。他们并不总是很容易阅读,没有图片,这太疯狂了。但是我们别无选择,甚至不得不使用ASCII艺术。然后出现Word,PDF等。在2000年,Word中有大量文档。要说服开发人员使用此类文档并不是一件容易的事-这不是时尚。更改链接的代码时,不方便查看文档中的更改,反之亦然。当Markdown出现时,这真是太神奇了,它有可能由此产生出非常漂亮的东西-例如HTML。而且这仍然是一种易于阅读并添加到您的代码库中的文本格式。即使您没有生成HTML,也可以在文本编辑器中方便地阅读Markdown。现在,当您在Github上打开一个项目时,它会定义Markdown文件并单独漂亮地显示它们。所有这些都位于您的代码旁边。代码中的文档是技术文档的最佳形式。例如,Microsoft将所有技术文档转移到Markdown,现在可以在GitHub上直接阅读该文档,他们接受PR-这是提供访问文档并组织每个人都可以使用的更改过程的好方法。在规范Markdown方面,有一个名为CommonMark的项目,该项目于几年前启动,其目标是使Markdown标准化。我认为CommonMark是今天的标准。人们开始尊重他,跟随他,但是还有许多其他的认识。例如,Github切换到CommonMark去年没有人注意到这一点-很好。但是他们能够切换到它。微软还将文档翻译成CommonMark,因为他们使用了我的Markdig。他们从多年前开始研究如何使用Markdig,在此之前,他们采用了自行式Markdown引擎,该引擎内部使用了常规函数。这还不错,但是据我所知,他们并没有真正遵循此引擎中的CommonMark规范,因此他们改用了Markdig。他们联系了我,这很酷。我写了Markdig以供使用,我想在自己的项目中使用它,但是后来我把它搁置了很长时间。我很高兴像Microsoft这样的公司决定选择它。.: , ? ?这不仅适用于编程,而且适用于任何领域。最主要的是做功课,自己学习。提出问题很重要。不必原样接受编程语言。并不是您需要更改它,而是了解为什么不同的事物以它们的工作方式起作用的重要性。您必须好奇并愿意研究原因,您必须提出好的问题。 “我不了解它的工作原理,但我想了解它。”您将如何提高自己的语言水平?您问您使用的语言的问题越多,您将获得更多帮助,改进它,学习新事物以及发现为什么以某种方式完成软件中某些内容的机会。所以你可以找到更多不仅仅是将“我想让X”导入Google并从github上的“做得好”功能中查找完成的项目。当我们编写一个真实的应用程序时,要深入了解所使用的每个依赖项的细节将非常困难-挑选细节将是一项艰巨的工作。但是在关心您的部分中,这对您个人而言很有趣,值得深入研究并提出问题。它是如何工作的,是否可以更快地完成,为什么某件事不能很好地工作-您必须理解为什么。 “也许我可以写点更好的东西?”值得深入研究并提出问题。它是如何工作的,是否可以更快地完成,为什么某件事不能很好地工作-您必须理解为什么。 “也许我可以写点更好的东西?”值得深入研究并提出问题。它是如何工作的,是否可以更快地完成,为什么某件事不能很好地工作-您必须理解为什么。 “也许我可以写点更好的东西?”与我合作的许多项目大部分都已完成。有时项目所有者不想更改它。这很可悲,因为您希望在开源中每个人都可以相互合作。开源的现实是有时您需要做其他事情。有时您提供的东西不错,但会带来太多变化。人们可能很难接受这样的建议-也许只会带来更多的错误和更多的支持,谁来支持所有这些呢?有人提出这个提议吗?可能不是。有时我也忘记了我需要问其他问题。简单的问题。我们可以做得更快吗?不是吗您需要采取行动,而不只是对缓慢移动的事物使用和咒骂,而对此不采取任何措施。需要挖掘,修复...在家做些事情,应对痛苦。每当您变得越来越准备去理解挑战并开发更复杂的程序时。也许最后,您对其他人的反应会有些失望,因为您将开始更好地了解他们的局限性。还有一件重要的事。不要害羞。试试吧!尝试做你想做的。如果您有想法,请尝试实现。即使这个想法很疯狂,有时您可能会得到一些疯狂的结果-也有一些东西。当您做这些事情时,您会遇到许多陌生而疯狂的人,从中您可以得到关于如何发展的深刻见解。您需要非常注意他们的讲话,他们的工作方式,他们的想法。不要复制它们,因为您有自己的道路和未来。当您可以在事业上遇到这样的人时,这很酷。我有几个这样的人。我并不总是意识到这一点,但是一段时间后我明白了:“为什么,这个家伙很酷!”我从他们那里学到了一些东西,但是也许可以了解更多。这是尝试自己思考和从周围最好的头脑中获取最好的东西之间的中间立场。它们可以很好地影响您,并可以帮助您开发更酷的东西。, , , , , , , - , .
下周五,亚历山德拉(Alexandra)将在莫斯科DotNext 2018上发表题为 “在突发编译器之后,通过使用LLVM将.NET IL转换为高度优化的本地代码”的演讲 。 该会议将于11月22日至23日在莫斯科举行,看来它将是所有会议中最大的DotNext。 我们会告诉您会议中还有什么期望,但是最好由她的另一位发言人Dylan Beatty完成-他录制了整首歌: