标签 编程语言 下的文章

Stack Overflow Jobs 上,你可以创建你自己的 开发者故事 Developer Story 来展示你的成就,表现你的职业生涯进步。在创建开发者故事时,你可以对你使用的技术/编程语言添加喜欢或不喜欢的标签,如下图:

你可以对你使用的技术/编程语言添加喜欢或不喜欢的标签

这就给了我们一个机会可以观察到这数十万开发者的喜好和厌恶。有许多方法可以评估一个语言的流行程度,举个栗子说,我们经常使用 Stack Overflow 访问数或问题查看数来评估这样的趋势。但是,当技术人员在他们的简历中表达他们不喜欢某种技术时,这个数据集就是一个找出技术人群不喜欢某种技术的独有方式。

(我两年前曾经在我的个人博客上发表过一些这类分析,不过这篇文章使用了更新的数据集,以及有更多可视化结果和说明。)

编程语言

作为测量每个编程语言有多流行的指标,我们将看看它出现在某人“不喜欢”标签的时间与其出现在其他人的“喜欢”或“不喜欢”标签的频率相比。那么 50% 就意味着该语言喜欢与不喜欢各占一半,而 1% 则意味着 99 个人喜欢它而剩下 1 个人不喜欢它。(我们使用了这篇文章中描述的 经验贝叶斯 empirical Bayes 方法来计算平均值,并使用这个方法来计算得到 95% 置信区间)

让我们开始看看选出的语言列表(而不是像 Android 这样的平台或像 jQuery 这样的库),所有这些都曾在开发者故事中至少提及了 2000 次以上。

每个语言有多不招人喜欢

最不喜欢的语言是 Perl、Delphi 和 VBA ,它们远远把其它语言抛下。接着的第二梯队是 PHP、Objective-C、 Coffeescript 和 Ruby。我们的团队很高兴地看到,R 语言相对于喜欢它的人数来说,对它不喜欢的人数是最少的。

如果你读过我们另外一些关于编程语言增长或萎缩的文章,你也许会注意到那些较少被不喜欢的语言往往是增长较快的。 在 Stack Overflow 上,R、Python、Typescript、Go 和 Rust 全是快速增长的编程语言(我们之前专门对 PythonR 做过分析),而且它们全都属于看法比较 分化 polarizing 的语言。类似的,大量萎缩的语言,比如 Perl、Objective-C 和 Ruby,如我们之前观察到的那样,在我们网站上它处于快速萎缩状况。

我们可以通过将每种语言的规模和增长与不喜欢它的人的百分比进行比较来进行调查,橙色点代表最不喜欢的语言。 为了使我们的分析与前几个帖子保持一致,我们将统计数据限制在高收入国家(如美国,英国,德国和加拿大)。

语言的增长率与对该语言的不喜欢进行对比

一般来说,编程语言的增长率和它有多不招人喜欢方面存在相关性。几乎每个在开发者故事中提及不喜欢的比率超过 3% 的语言都在 Stack Overflow 流量上处于萎缩状态(除了十分两极化的 VBA,它仍有轻度增长)。而不喜欢数量较少的语言,如 R、Rust、 Typescript 和 Kotlin,它们全处于快速增长领域(Typescript 和 Kotlin 增长的太快,以至于都跑出了上图范围)。

一个突出的编程语言是函数式编程语言 Clojure;几乎没有人表示过不喜欢它,但是它仍然处于快速萎缩中(根据问题查看情况,它在去年才开始萎缩)。另外一个例外是 MATLAB,它处于快速萎缩,但是没有很多人表示过不喜欢它。这可能是由于调查样本的数据所限:任何一个 Web 开发人员都可能对 PHP、C# 或 Ruby 有意见,但是不从事数据分析的人没理由对 MATLAB 不满意。(这也可能是 R 较少被提及“不喜欢”的部分原因)

我们不一定说这里存在因果关系——部分程序员不喜欢就会导致该语言会被抛弃。 另一种可能是,如果人们觉得这种语言已经越来越不流行,那么人们就会觉得很自然地表达他们也不喜欢了。 同样可以想象的是,开发人员经常使用这个字段来记录他们曾经使用的技术,但是不会再使用该技术了。 这将导致那些自然而然地“被替代的”技术就一直停留在“不喜欢”标签里面。

最不喜欢的和最喜欢的

上面的分析仅考虑了编程语言,不涉及操作系统、平台或库(框架)。那么就整体而言,最不喜欢的技术是什么?为了专注于我们有足够数据的更主要的技术,我们其限制为至少提及了 1000 次的技术。

最不喜欢的技术

最不喜欢的其中有几个是微软的技术,特别是 IE 和 VB,以及 “微软” 标签(“评估” 也出现在这个列表中,但是没那么糟糕)。有个好消息是,大多数人都不喜欢 Flash。此外,较老的语言,比如 COBOL、 Fortran 和 Pascal 也出现在此处。

值得再次强调的是,这不是对技术及其品质或受欢迎程度的批评。 这只是衡量哪些技术激起了强烈的消极情绪,至少在一部分愿意公开分享其感受的开发人员中如此。

我们也集中观察了那些最流行的技术、那些最不可能被不喜欢的技术(这次,由于喜欢标签出现的比较多,我们仅关注那些被提及至少 10000 次的)。

哪些技术最令人喜欢

Git 也许是许多开发者的沮丧源头(绝对包括我!),但人们很少在简历中承认这一点,这是因为它是我们的开发者故事中最受欢迎的标签之一。 R 也出现在了这个列表,但它并不是唯一一个没有争议的与数据科学相关的语言。 机器学习被 23000 人所喜欢,而且很少被人不喜欢。 诸如 Python-3.X、CSS3 和 HTML5 等标签可能表明开发者很少指定他们不喜欢技术的特定版本(如果他们会指定的话)。 当然,jQuery 在 Stack Overflow 上一直是如此受欢迎

分化的标签网络

我们可以把所有这些标签组合成一个网络。在最近的一篇文章中,Julia Silge 展示了我们如何构建一个代表整个软件生态系统的技术网络。 如果我们根据每个标签不喜欢的程度对节点进行着色,我们可以了解该生态系统的哪些部分比其它部分更有争议。

分化的标签网络

通过将开发者故事的标签放置到次生态系统中,该网络揭示了哪些类型的标签趋于两级分化。 在微软(以 C# 和 .NET 为中心,左上角),PHP(与 WordPress 和 Drupal 一起,左下角)以及移动开发(特别是 Objective-C,右下角)的子生态系统中都有一些意见分化的标签聚合。 在操作系统聚合中(右下),我们可以看到诸如 OSX 之类的系统,以及特别是 Windows 都有不喜欢的人,但是像 Linux、Ubuntu 和 Unix 这样的标签却没有。

竞争

如果某人喜欢某个特定的标签,是否意味着通常他们喜欢或不喜欢另外的标签呢?

我们可以使用出现在特定喜欢标签之间的 phi 系数来衡量它。 (当计算这些相关性时,我们只考虑那些至少有一个不喜欢标签的人。)

技术竞争程度

这突出显示了软件生态系统的一些“竞争”:Linux 和 OSX vs Windows,Git vs SVN,vim vs emacs 以及(对我来说)R vs SAS。 这些配对中的大多数并不代表“相反”的技术,而是反映了两种解决类似问题的方法。 它们中的许多表明了从以前流行的技术发展到更现代的技术(SVN 由 Git 取代,XML 由 JSON 取代,VB 由 C# 取代)。 这对于人们想在简历中列出的内容是有意义的;开发者通常会表明他们不愿意使用他们认为过时的东西。

总结

我对“语言战争”没有任何兴趣,我也不会对用户分享的喜欢或不喜欢的任何技术进行裁断。 对微软技术的两级分化的看法通常会鼓励我分享我的个人经验。 我是一个 Mac 和 UNIX 终身拥趸,几乎我所有的大学和研究生的编程学习都围绕着 Python 和 R。尽管如此,我很高兴能够加入一个 .NET 栈的公司,我很高兴我来了 —— 因为我喜欢这个团队、产品和数据。 我不能代表其他人说话,但我很高兴自己可以从事于自己想做的事情,而不是那些不想要做的事情。

如果您有兴趣分享您喜欢和不喜欢的技术,并想找到您职业生涯的下一份工作,那么您可以创建自己的开发者故事

想找一份你喜欢的技术的工作? 在 Stack Overflow Jobs 找到你的下一份工作,在那里你可以搜索你喜欢做的技术工作。

应用程序的领域在不断发展。底层的 Linux 做了很多工作,而且还在继续,但是在过去几年里,应用程序领域开始增长。在这种情况下,开发人员使用哪种语言构建这些应用程序?简而言之,要看情况,我知道这个说法没啥稀奇的。但是,通过我们拥有的数据,我们可以确定哪些语言领先。

站在山顶的语言是 Java。它已经出现在开源软件领域 15 年以上,但它并不是一直在顶峰。在早期,我们没有看到那么多对 java 开发者感兴趣的,但现在情况已经改变了。它是目前应用领域的权威领导者。虽然这个数字在过去六个季度没有明显增长,但其整体数量却令人印象深刻。平均而言,关注于开源软件的公司发布的职位中有超过 1/3 的职位要求 Java 技能。这对几年前没有在榜单上出现的语言而言是一个非凡的成就。而且,由于它在 Android 中的大量使用,未来这个数字进一步增加也并不奇怪。

在应用程序领域中使用的另一种语言是 C++。虽然它的数量不能与 Java 竞争,但它仍然在这个领域占据了很大的市场份额。而且每 3 个招聘中有一个要求 Java,C++ 则是每 4 个中有一个要求它。与 Java 非常类似,其数量在过去六个季度中保持相对稳定。C++ 一直被大量使用,即使 Java 已经取代它,它仍然是一种高度相关的语言。

进入到网络应用领域,多年来一直在城头变幻大王旗。在早期,大多数 Web 程序毫无疑问地选择使用 PHP 开发。正如之前关于脚本的文章所讨论的,这几年来已经发生了变化。在过去几年中,PHP 的使用似乎有所恶化。在过去一年半的时间里,已经急剧下降了 30% 以上。这是一个令人震惊的数字,只有时间才能告诉我们趋势是否持续。

最初打破 PHP 领导地位的是 Ruby on Rails。多年来,我看到公司们和开发者们进行了这一转型。Ruby on Rails 经历了一段时间,在这个时期它是这个领域的首选语言。然而,从我们收集的数字来看,它的光泽似乎已经失去了一点。虽然没有像 PHP 这样的衰退,但其数量一直保持相对平稳,它曾经有过的增长似乎停滞不前。

目前在网络应用程序领域的王者似乎是 Javascript。它获得了最大的总数。虽然它的数量保持平坦,这很像 Ruby on Rails,但它已经吸引了更多的观众。平均来说,过去六个季度,公司在分析的 10,000 份工作清单中有 1,500 份需要 Javascript 技能。这比 PHP 或 Ruby on Rails 多了 70%。

随着 PHP 的衰落以及 Ruby on Rails 和 Javascript 停滞不前,是谁在 Web 程序领域保持增长呢?这个群体的突出者似乎是 Golang。它在 2007 年由 Google 内的几位开发人员创建,似乎这种语言开始获得更广泛的受众群体。虽然与我们讨论的其它三个的总数相比不多,但看起来这一年半以来增长了 50%。如果这种趋势继续下去,那将是非常有趣的。在我看来,我预计我们会继续看到 Golang 挤占 其它三个的群体份额。

如往常一样,我们会监测这些语言的各种前进方向,以观察市场趋势。而且,榜单的任何新进入者都会被密切关注。这是一个令人兴奋和动态的发展领域。一个会提供随时间不断变化的结果。


via: https://www.linuxcareer.com/do-you-have-what-it-takes-to-be-a-software-developer

作者:Brent Marinaccio 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

想学编程的原因有很多,你也许是想要做一个程序,又或者你只是想投身于这个行业,所以,在选择你的第一门编程语言之前,问问你自己:你想要在哪里运行程序?你想要程序来完成什么工作?

你学习编程的原因将会决定你的第一门编程语言的选择。

在这篇文章里,我会交替使用 “编码” code “编程” program “开发” develop 等动词, “代码” code “程序” program “应用程序” application “应用” app 等名词。这是考虑到了你可能听过的语言用法。

了解你的设备

在你编程语言的选择上,你的程序将运行在何处是个决定性因素。

桌面应用是运行在台式机或者笔记本电脑上的传统软件程序。这样你编写的代码在同一时间内只能在一台电脑上运行。移动应用,也就是我们所熟知的“app”,运行在使用 IOS 、Android 或者其他操作系统的移动设备上。网页应用是功能像应用的网页。

按互联网的 客户-服务器(C/S)架构分,网页开发者经常被分为两类:

  • 前端开发,就是编写运行在浏览器里面的代码。这是个面对用户的部分,或者说是程序的前脸。有时候被称为“客户端编程”,因为浏览器是网站的客户-服务器架构的客户端部分。浏览器会运行在你本地的电脑或者设备上。
  • 后台开发,也就是大家所熟知的“服务器端开发”,编写的代码运行在你无法实际接触的服务器上。

创造什么

编程是一门广泛的学科,能应用在不同的领域。常见的应用有:

  • 数据科学
  • 网页开发
  • 游戏开发,以及
  • 不同类型的工作自动化

现在我们已经讨论了为什么你要编程,你要程序运行在哪里,让我们看一下两门对于新手来说不错的编程语言吧。

Python

Python 是对于第一次编程的人来说是最为流行的编程语言之一,而且这不是巧合。Python 是一门通用的编程语言。这意味着它能应用在广泛的编程任务上。几乎没有你不能用 Python 完成的工作。这一点使得很多新手能在实际中应用这门编程语言。另外, Python 有两个重要的设计特征,使得其对于新手更友好:清晰、类似于英语的语法,和强调代码的可读性

从本质上讲,一门编程语言的语法就是你所输入的能让这编程语言执行的内容。这包括单词,特殊字符(例如 ;$% 或者 {}),空格或者以上任意的组合。Python 尽可能地使用英语,不像其他编程语言那样经常使用标点符号或者特殊的字符。所以,Python 阅读起来更自然、更像是人类语言。这一点帮助新的编程人员可以聚焦于解决问题,而能花费更少的时间纠结于语言自身的特性上。

清晰语法的同时注重于可读性。在编写代码的时候,你所创造的代码的逻辑“块”,就是一些为了相关联目标而共同工作的代码。在许多编程语言里,这些块用特殊字符所标记(或限定)。它们或许被 {} 或者其他字符所包住。块分割字符和你写代码的能力,这两者不管怎么结合起来都会降低可读性。让我们来看一个例子。

这有个被称为 fun 的简短函数。它要求输入一个数字,x 就是它的输入。如果 x 等于 0,它将会运行另一个被称为no_fun 的函数(这函数做了些很无趣的事情)。新函数不需要输入。反之,简短函数将会运行一个使用输入 x 的名为 big_fun 的函数。

这个函数用 C 语言 将会是这样写的:

void fun(int x)
{
    if (x == 0) {
        no_fun();
    } else {
        big_fun(x);
    }
}

或者,像是这样:

void fun(int x) { if (x == 0) {no_fun(); } else {big_fun(x); }}

功能上两者等价,而且都能运行。{}; 告诉我们哪里是代码块的不同部分。然而,第一个对于人们来说明显更容易阅读。相比之下完成相同功能的 Python 是这样的:

def fun(x):
    if x == 0:
        no_fun()
    else:
        big_fun(x)

在这里,只有一个选择。如果代码不是这样排列的,它将无法工作。如果你编写了可以工作的代码,你就有了可阅读的代码。同样也留意一下两者在语法上的差异。不同的是 def ,在 Python 代码中这个词是英语单词,大家都很熟悉这单词的含义(LCTT 译注:def 是 definition 的缩写,定义的意思)。在 C 语言的例子中 voidint 就没有那么直观。

Python 也有个优秀的生态系统。这有两层意思,第一,你有一个使用该语言的庞大、活跃的社区,当你需要帮助指导的时候,你能向他们求助。第二,它有大量早已存在的库,库是指完成特定功能的代码集合。从高级数学运算、图形到计算机视觉,甚至是你能想象到的任何事情。

Python 作为你第一门编程语言有两个缺点。第一是它有时候安装起来很复杂,特别是在运行着 Windows 的电脑上。(如果你有一台 Mac 或者 Linux 的电脑,Python 默认已经安装好了。)虽然这问题不是不能克服,而且情况总在改善,但是这对于一些人来说还是个阻碍。第二个缺点是,对于那些明确想要建设网站的人来讲,虽然有很多用 Python 写的项目(例如 DjangoFlask ),但是编写运行在浏览器上的 Python 代码却没有什么好的选择。它主要是后台或者服务器端语言。

JavaScript

如果你知道你学习编程的主要原因是建设网站的话,JavaScript 或许是你的最佳选择。 JavaScript 是关于网页的编程语言。除了是网页的默认编程语言之外, JavaScript 作为初学的语言有几点优点。

第一,无须安装任何东西。你可以打开文本编辑器(例如 Windows 上的记事本,但不是一个文字处理软件,例如 Microsoft Word)然后开始输入 JavaScript 。代码将在你的浏览器中运行。最顶尖的浏览器内置了JavaScript 引擎,所以你的代码将可以运行在几乎所有的电脑和很多的移动设备上。事实上,能马上在浏览器中运行代码为编程人员提供了一个非常的反馈,这对于新手来说是很好的。你能尝试一些事情然后很快地看到结果。

开始 JavaScript 是作为前端语言的,不过一个名为 Node.js 的环境能让你编写运行在浏览器或者服务器上的代码。现在 JavaScript 能当作前端或者后台语言使用。这增加了它的使用人数。JavaScript 也有大量能提供除核心功能外的额外功能的包,这使得它能当作一门通用语言来使用。JavaScript 不只是网页开发语言,就像 Python 那样,它也有个充满生气的、活跃的生态系统。

尽管有这些优点,但是 JavaScript 对于新手来说并非十全十美。JavaScript 的语法并不像 Python 那样清晰,也不怎么像英语。更像是之前例子里提到的 C 语言。它并不是把可读性当作主要的设计特性。

做出选择

选 Python 或者 JavaScript 作为入门语言都没有问题。关键是你打算做什么。为什么你要学习编程?你的回答很大程度上影响你的决定。如果你是想为开源做贡献,你将会找到大量用这两门语言编写的项目。另外,许多主要不是用 JavaScript 写的项目仍使用 JavaScript 用作前端组件。当你做决定时,别忘了你本地的社区。你有在使用其中一门语言的朋友或者同事吗?对于一个新手来说,有实时的帮助是非常重要的。

祝好运,开心编程。


作者简介:

Kojo Idrissa - 我是一个新晋的软件开发者(1 年),从会计和大学教学转型而来。自从有开源软件以来,我就是它的一个粉丝。但是在我之前的事业中并不需要做很多的编程工作。技术上,我专注于 Python ,自动化测试和学习 Django 。我希望我能尽快地学更多的 JavaScript 。话题上,我专注于帮助刚开始学习编程或想参与为开源项目做贡献的人们。我也关注在技术领域的包容文化。


via: https://opensource.com/article/17/1/choosing-your-first-programming-language

作者:Kojo Idrissa 译者:ypingcn 校对:bestony

本文由 LCTT 原创编译,Linux中国 荣誉推出

几个星期前,我一个朋友问我:“为什么要关心 Go 语言”? 因为他们知道我热衷于 Go 语言,但他们想知道为什么我认为其他人也应该关心。本文包含三个我认为 Go 是重要的编程语言的原因。

安全

个人而言,你和我或许完全有能力在 C 中编写程序,既不会泄漏内存,也不会不安全地重复使用内存。然而,整体上,即使有超过 40 年)的经验,用 C 的程序员也无法可靠地这样做。

尽管静态代码分析、valgrind、tsan 以及 “-Werror” 已经存在了几十年,却很少有证据表明这些工具被广泛认可,更不用说广泛采用。总而言之,事实表明,程序员根本无法安全地管理自己的内存。现在是离开 C 的时候了。

Go 不需要程序员直接管理内存,所有内存分配都由语言运行时自行管理,使用前初始化,必要时检查边界。它肯定不是提供这些安全保障的第一个主流语言,Java(1995)可能是该冠军的竞争者。关键是,世界对不安全的编程语言没有胃口,所以人们默认认为,Go 是内存安全的。

开发人员生产力

从 20 世纪 70 年代末,开发人员的时间变得比硬件所耗费的时间更昂贵了。开发人员的生产力是一个不断扩展的话题,但它归结为这一点:你花了多少时间做有用的工作,又有多少时间等待编译器或者失望地迷失在外部代码库中。

有个笑话说 Go 是在等待 C ++ 程序编译时开发的。快速编译是 Go 的一个重要功能,也是吸引新开发人员的关键工具。虽然编译速度仍然是一个永久的战场,但公平地说,在其他语言中需要几分钟的编译,在 Go 中只需要几秒钟。

Go 程序员意识到生产力的更根本的问题是代码是为了读而写的,所以将代码的阅读行为放在编写之上。Go 通过工具和自定义来强制所有代码格式化成特定的样式。这消除了学习项目特定语言的方言时的困难,并有助于发现错误,因为它们看上去就是不正确。

由于专注于分析和机器辅助,Go 开发人员开始采用越来越多的工具来发现常见的编码错误,这种工具从来没有在 C 语言开发者中产生共鸣 - Go 开发人员希望工具帮助他们保持代码清洁。

并发性

十多年来,芯片设计师一直在警告免费午餐将会结束。从最低端的手机到最耗电的服务器,硬件的并行性以更多、更慢、堆砌 cpu 内核的形式出现,但只有你的语言可以利用它们才有意义。因此,并发特性需要内置到我们编写的要在今天的硬件上运行的软件中。

通过提供一种基于协程的轻量级并发模型,或者是 Go 中已知的 goroutines,Go 超越了那些暴露操作系统的多进程或多线程并行模型的语言。goroutines 允许程序员避开复杂的回调,而语言运行时确保有足够的线程来保持你的内核的活跃。

总结

我给朋友推荐 Go 有三个原因:安全性、生产力和并发性。有些语言可以涵盖一个也有可能是两个方面,但是这三个方面的结合使得 Go 成为主流程序员的绝佳选择。

相关文章:

  1. 为什么 Go 和 Rust 不是竞争对手
  2. 听听我在 OSCON 上谈 Go 语言性能
  3. 我在 GopherChina 和 GopherCon Singapore 中的演讲
  4. 压力测试你 Go 包

via: https://dave.cheney.net/2017/03/20/why-go

作者:Dave Cheney 译者:geekpi 校对:jasminepeng

本文由 LCTT 原创编译,Linux中国 荣誉推出

在近一两个月中,我多次的和线上线下的朋友讨论了这个话题,所以我干脆直接把它写在博客中,以便以后查阅。

大部分高级语言运行效率较慢的原因通常有两点:

  1. 没有很好的利用缓存;
  2. 垃圾回收机制性能消耗高。

但事实上,这两个原因可以归因于:高级语言强烈地鼓励编程人员分配很多的内存。

首先,下文内容主要讨论客户端应用。如果你的程序有 99.9% 的时间都在等待网络 I/O,那么这很可能不是拖慢语言运行效率的原因——优先考虑的问题当然是优化网络。在本文中,我们主要讨论程序在本地执行的速度。

我将选用 C# 语言作为本文的参考语言,其原因有二:首先它是我常用的高级语言;其次如果我使用 Java 语言,许多使用 C# 的朋友会告诉我 C# 不会有这些问题,因为它有值类型(但这是错误的)。

接下来我将会讨论,出于编程习惯编写的代码、使用 普遍编程方法 with the grain 的代码或使用库或教程中提到的常用代码来编写程序时会发生什么。我对那些使用难搞的办法来解决语言自身毛病以“证明”语言没毛病这事没兴趣,当然你可以和语言抗争来避免它的毛病,但这并不能说明语言本身是没有问题的。

回顾缓存消耗问题

首先我们先来回顾一下合理使用缓存的重要性。下图是基于在 Haswell 架构下内存延迟对 CPU 影响的 数据

针对这款 CPU 读取内存的延迟,CPU 需要消耗近 230 个运算周期从内存读取数据,同时需要消耗 4 个运算周期来读取 L1 缓冲区。因此错误的去使用缓存可导致运行速度拖慢近 50 倍。还好这并不是最糟糕的——在现代 CPU 中它们能同时地做多种操作,所以当你加载 L1 缓冲区内容的同时这个内容已经进入到了寄存器,因此数据从 L1 缓冲区加载这个过程的性能消耗就被部分或完整的掩盖了起来。

撇开选择合理的算法不谈,不夸张地讲,在性能优化中你要考虑的最主要因素其实是缓存未命中。当你能够有效的访问一个数据时候,你才需要考虑优化你的每个具体的操作。与缓存未命中的问题相比,那些次要的低效问题对运行速度并没有什么过多的影响。

这对于编程语言的设计者来说是一个好消息!你都不必去编写一个最高效的编译器,你可以完全摆脱一些额外的开销(比如:数组边界检查),你只需要专注怎么设计语言能高效地编写代码来访问数据,而不用担心与 C 语言代码比较运行速度。

为什么 C# 存在缓存未命中问题

坦率地讲 C# 在设计时就没打算在现代缓存中实现高效运行。我又一次提到程序语言设计的局限性以及其带给程序员无法编写高效的代码的“压力”。大部分的理论上的解决方法其实都非常的不便,这里我说的是那些编程语言“希望”你这样编写的惯用写法。

C# 最基本的问题是对 基础值类型 value-based 低下的支持性。其大部分的数据结构都是“内置”在语言内定义的(例如:栈,或其他内置对象)。但这些具有帮助性的内置结构体有一些大问题,以至于更像是创可贴而不是解决方案。

  • 你得把自己定义的结构体类型在最先声明——这意味着你如果需要用到这个类型作为堆分配,那么所有的结构体都会被堆分配。你也可以使用一些类包装器来打包你的结构体和其中的成员变量,但这十分的痛苦。如果类和结构体可以相同的方式声明,并且可根据具体情况来使用,这将是更好的。当数据可以作为值地存储在自定义的栈中,当这个数据需要被堆分配时你就可以将其定义为一个对象,比如 C++ 就是这样工作的。因为只有少数的内容需要被堆分配,所以我们不鼓励所有的内容都被定义为对象类型。
  • 引用 值被苛刻的限制。你可以将一个引用值传给函数,但只能这样。你不能直接引用 List<int> 中的元素,你必须先把所有的引用和索引全部存储下来。你不能直接取得指向栈、对象中的变量(或其他变量)的指针。你只能把它们复制一份,除了将它们传给一个函数(使用引用的方式)。当然这也是可以理解的。如果类型安全是一个先驱条件,灵活的引用变量和保证类型安全这两项要同时支持太难了(虽然不是不可能)。这些限制背后的理念并不能改变限制存在的事实。
  • 固定大小的缓冲区.aspx) 不支持自定义类型,而且还必须使用 unsafe 关键字。
  • 有限的“数组切片”功能。虽然有提供 ArraySegment 类,但并没有人会使用它,这意味着如果只需要传递数组的一部分,你必须去创建一个 IEnumerable 对象,也就意味着要分配大小(包装)。就算接口接受 ArraySegment 对象作为参数,也是不够的——你只能用普通数组,而不能用 List<T>,也不能用 栈数组.aspx) 等等。

最重要的是,除了非常简单的情况之外,C# 非常惯用堆分配。如果所有的数据都被堆分配,这意味着被访问时会造成缓存未命中(从你无法决定对象是如何在堆中存储开始)。所以当 C++ 程序面临着如何有效的组织数据在缓存中的存储这个挑战时,C# 则鼓励程序员去将数据分开地存放在一个个堆分配空间中。这就意味着程序员无法控制数据存储方式了,也开始产生不必要的缓存未命中问题,而导致性能急速的下降。C# 已经支持原生编译 也不会提升太多性能——毕竟在内存不足的情况下,提高代码质量本就杯水车薪。

再加上存储是有开销的。在 64 位的机器上每个地址值占 8 位内存,而每次分配都会有存储元数据而产生的开销。与存储着少量大数据(以固定偏移的方式存储在其中)的堆相比,存储着大量小数据的堆(并且其中的数据到处都被引用)会产生更多的内存开销。尽管你可能不怎么关心内存怎么用,但事实上就是那些头部内容和地址信息导致堆变得臃肿,也就是在浪费缓存了,所以也造成了更多的缓存未命中,降低了代码性能。

当然有些时候也是有办法的,比如你可以使用一个很大的 List<T> 来构造数据池以存储分配你需要的数据和自己的结构体。这样你就可以方便的遍历或者批量更新你的数据池中的数据了。但这也会很混乱,因为无论你在哪要引用什么对象都要先能引用这个池,然后每次引用都需要做数组索引。从上文可以得出,在 C# 中做类似这样的处理的痛感比在 C++ 中做来的更痛,因为 C# 在设计时就是这样。此外,通过这种方式来访问池中的单个对象比直接将这个对象分配到内存来访问更加的昂贵——前者你得先访问池(这是个类)的地址,这意味着可能产生 2 次缓存未命中。你还可以通过复制 List<T> 的结构形式来避免更多的缓存未命中问题,但这就更难搞了。我就写过很多类似的代码,自然这样的代码只会水平很低而且容易出错。

最后,我想说我指出的问题不仅是那些“热门”的代码。惯用手段编写的 C# 代码倾向于几乎所有地方都用类和引用。意思就是在你的代码中会频率均匀地随机出现数百次的运算周期损耗,使得操作的损耗似乎降低了。这虽然也可以被找出来,但你优化了这问题后,这还是一个 均匀变慢 的程序。

垃圾回收

在读下文之前我会假设你已经知道为什么在许多用例中垃圾回收是影响性能问题的重要原因。播放动画时总是随机的暂停通常都是大家都不能接受的吧。我会继续解释为什么设计语言时还加剧了这个问题。

因为 C# 在处理变量上的一些局限性,它强烈不建议你去使用大内存块分配来存储很多里面是内置对象的变量(可能存在栈中),这就使得你必须使用很多分配在堆中的小型类对象。说白了就是内存分配越多会导致花在垃圾回收上的时间就越多。

有些测评说 C# 或者 Java 是怎么在一些特定的例子中打败 C++ 的,其实是因为内存分配器都基于一种吞吐还算不错的垃圾回收机制(廉价的分配,允许统一的释放分配)。然而,这些测试场景都太特殊了。想要使 C# 的程序的内存分配率变得和那些非常普通的 C++ 程序都能达到的一样就必须要耗费更大的精力来编写它,所以这种比较就像是拿一个高度优化的管理程序和一个最简单原生的程序相比较一样。当你花同样的精力来写一个 C++ 程序时,肯定比你用 C# 来写性能好的多。

我还是相信你可以写出一套适用于高性能低延迟的应用的垃圾回收机制的(比如维护一个增量的垃圾回收,每次消耗固定的时间来做回收),但这还是不够的,大部分的高级语言在设计时就没考虑程序启动时就会产生大量的垃圾,这将会是最大的问题。当你就像写 C 一样习惯的去少去在 C# 分配内存,垃圾回收在高性能应用中可能就不会暴露出很多的问题了。而就算你 真的 去实现了一个增量垃圾回收机制,这意味着你还可能需要为其做一个写屏障——这就相当于又消耗了一些性能了。

看看 .Net 库里那些基本类,内存分配几乎无处不在!我数了下,在 .Net 核心框架 中公共类比结构体的数量多出 19 倍之多,为了使用它们,你就得把这些东西全都弄到内存中去。就算是 .Net 框架的创造者们也无法抵抗设计语言时的警告啊!我都不知道怎么去统计了,使用基础类库时,你会很快意识到这不仅仅是值或对象的选择问题了,就算如此也还是 伴随 着超级多的内存分配。这一切都让你觉得分配内存好像很容易一样,其实怎么可能呢,没有内存分配你连一个整型值都没法输出!不说这个,就算你使用预分配的 StringBuilder,你要是不用标准库来分配内存,也还不是连个整型都存不住。你要这么问我那就挺蠢的了。

当然还不仅仅是标准库,其他的 C# 库也一样。就算是 Unity(一个 游戏引擎,可能能更多的关心平均性能问题)也会有一些全局返回已分配对象(或数组)的接口,或者强制调用时先将其分配内存再使用。举个例子,在一个 GameObject 中要使用 GetComponents 来调用一个数组,Unity 会强制地分配一个数组以便调用。就此而言,其实有许多的接口可以采用,但他们不选择,而去走常规路线来直接使用内存分配。写 Unity 的同胞们写的一手“好 C#”呀,但就是不那么高性能罢了。

结语

如果你在设计一门新的语言,拜托你可以考虑一下我提到的那些性能问题。在你创造出一款“足够聪明的编译器”之后这些都不是什么难题了。当然,没有垃圾回收器就要求类型安全很难。当然,没有一个规范的数据表示就创造一个垃圾回收器很难。当然,出现指向随机值的指针时难以去推出其作用域规则。当然,还有大把大把的问题摆在那里,然而解决了这些所有的问题,设计出来的语言就会是我们想的那样吗?那为什么这么多主要的语言都是在那些六十年代就已经被设计出的语言的基础上迭代的呢?

尽管你不能修复这些问题,但也许你可以尽可能的靠近?或者可以使用域类型(比如 Rust 语言)去保证其类型安全。或者也许可以考虑直接放弃“类型安全成本”去使用更多的运行时检查(如果这不会造成更多的缓存未命中的话,这其实没什么所谓。其实 C# 也有类似的东西,叫协变式数组,严格上讲是违背系统数据类型的,会导致一些运行时异常)。

如果你想在高性能场景中替代 C++,最基本的一点就是要考虑数据的存放布局和存储方式。


作者简介:

我叫 Sebastian Sylvan。我来自瑞典,目前居住在西雅图。我在微软工作,研究全息透镜。诚然我的观点仅代表本人,与微软公司无关。

我的博客以图像、编程语言、性能等内容为主。联系我请点击我的 Twitter 或 E-mail。


via: https://www.sebastiansylvan.com/post/why-most-high-level-languages-are-slow

作者:Sebastian Sylvan 译者:kenxx 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

回顾年度最热门的 AI 项目和容器的编程语言、新出现的编程语言,和更多编程趋势。

技术在不断前进 - 可能不总是向前,但总是在变动。但即使对于那些关注发展趋势及其对程序员的影响的人来说,确切地了解技术的方向也是一个挑战。我们总是在每年秋季才能够清晰地看出当年开源编程趋势,那时我与我的同事,Kelsey Hightower 和 Scott Hanselman,以及我们非常棒的编程委员会,正在筹备来年的 OSCON(O'Reilly 开源大会)。我们获得的建议和对特定主题的关注数量是反映开源世界热门趋势的良好指标。以下是我们在 2016 年看到的顶级编程趋势的概述。

编程语言驱动 AI

走出 20 世纪 90 年代的人工智能冬季,人工智能随着它所依赖的计算能力的提升再次出现,它影响着我们如何构建软件。机器学习、深度学习、自然语言处理和自动语音识别覆盖了世界各地 - 从 GitHub 的项目和工作岗位,到新公司成立背后的原因,以及清除我们杂乱的台面(Hey, Alexa!)。(LCTT 译注:Alexa 是预装在亚马逊 Echo 内的个人虚拟助手,可以接收及响应语音命令,可被看成是亚马逊版的 Siri 语音助手。用户只需要说一声“Alexa”,就可以创建各种任务,还可以和各种智能家居设备进行交互。) 是的,即使像 OSCON 这样的会议都处处提及 “万物皆智能” all things AI 。虽然计算能力的提升已经铺平了道路,所有关于 all things AI 的开源已经引起了行业广泛开放的创新和竞争。谷歌的 TensorFlowOpenAIApache Spark 使用强大框架成为行业领导者,但也有较小的参与者,如 NervanaNeonTheano

AI 的兴起已经影响到了软件开发者的前景?没错,现在是了解 Python 的好时机 - 它给数据工程师和科学家带来的敏捷性和流行性使它成为最流行的 AI 编程语言,其次是 R、Java 和 Scala。

容器和 Go 的结合就像花生、黄油和果冻

(花生、黄油和果冻 —— LCTT译注:最佳组合)

Go 1.0 发布于 2012 年 3 月。紧接着 Docker 在一年后发布,Kubernetes 在另外一年后发布。总之,Go 并不是如我们所知的那样专为基础设施的未来而设计的,但 Go 似乎是为了填充编程世界的一个主要的空洞而出现。对于一个高度联网的世界、一个必须拥有一流并发性的世界而言,Go 是以 Java 或 C++ 永远不会有的方式专门设计的。如果你在做运维或者类似的事,你应该至少稍微了解下 Go ,因为它正在发展中,它将会被使用多年,并成为许多程序的骨干。

Swift 超越了 Apple 的生态系统

Swift 是 Apple 在 2015 年启动该编程语言不久之后就开源的。Swift 已经成为 iOS 和 Mac OS X 开发人员的热门话题。这种语言很容易理解,因此很快流行起来,并且它比它要取代的语言 - Objective-C 和 C++ 赢得了一个更安全的声誉。在 JavaScript 框架和其他新语言的世界中,Swift 是否成功仍有待观察,但如果它能继续获得苹果忠实用户的欢迎,Swift 将有机会成为伟大的网络世界中最有望成功的竞争者和超越者。

Java 8 vs 使用 JVM 的函数式语言

Java 8 的函数式能力(即引入 Lambdas )的出现使得 JVM 语言(如 Scala 和 Clojure)得到了关注。最近,很大程度上由于 Apache Spark 的增长使得 Scala 有一点小爆发。现在,因为新、老开发人员都在积极关注 Java 8 所带来的东西,至少目前,Scala 和 Clojure 似乎被搁置了。Java 现在能够解决并发和大数据相关的事,而那些专门为满足此方面要求而构建的其他编程语言已经做了多年。在 2017 年,OSCON 几乎没有 Scala 和 Clojure 的提案,不是因为我们这样计划的,而是那些提交提案的发言者似乎没有什么兴趣。

新兴语言

和往常一样,世上总是在不停出现新兴语言,目的是比之前的语言做得更好,可以响应从前的语言出现时没有的需求,或者开始只是疯狂思想,最终却改变了我们对编程的看法。今年有五种语言即将进入大时代:Rust、Elixir、Elm、Kotlin 和 Perl 6。

这 5 个热门会给行业带来什么?

  • Rust:兼顾速度和一定安全的系统编程语言。
  • Elixir:函数式、动态和容错,适用于那些规模越来越大的应用程序。
  • Elm:更多函数式的乐趣,使用 JavaScript,学习成为一种乐趣。
  • Kotlin:这一个是为使用 Java 和 JVM 的人设计的语言 - 静态类型、安全,此外我提到 Java 兼容了吗?
  • Perl 6:它还活着!Perl 6 碰巧是一种新的语言,它胜在富有表现力和功能丰富。

时间会告诉他们是否会如约发布。尝试他们,为他们贡献,成为未来的一部分!


作者简介:

Rachel Roumeliotis - O'Reilly Media,Inc. 的战略内容总监,领导了一个编辑团队,其涵盖各种各样的编程主题,从全栈 web 开发到企业中的开源到新兴的编程语言。她是 OSCON(O'Reilly 软件架构会议)和 Fluent 的编程主席。 她从事技术出版工作超过 10 年,出版了许多领域的内容,包括移动编程、UX、计算机安全。


via: https://opensource.com/article/16/12/yearbook-top-programming-trends-2016

作者:Rachel Roumeliotis 译者:geekpi 校对:jasminepeng

本文由 LCTT 原创编译,Linux中国 荣誉推出