2017年3月

这篇文章是关于一个鲜为人知的让 Go 在编译期断言的方法。你可能不会使用它,但是了解一下也很有趣。

作为一个热身,来看一个在 Go 中熟知的编译期断言:接口满意度检查。

在这段代码(playground)中,var _ = 行确保类型 W 是一个 stringWriter,其由 io.WriteString 检查。

package main

import "io"

type W struct{}

func (w W) Write(b []byte) (int, error)       { return len(b), nil }
func (w W) WriteString(s string) (int, error) { return len(s), nil }

type stringWriter interface {
    WriteString(string) (int, error)
}

var _ stringWriter = W{}

func main() {
    var w W
    io.WriteString(w, "very long string")
}

如果你注释掉了 WWriteString 方法,代码将无法编译:

main.go:14: cannot use W literal (type W) as type stringWriter in assignment:
    W does not implement stringWriter (missing WriteString method)

这是很有用的。对于大多数同时满足 io.WriterstringWriter 的类型,如果你删除 WriteString 方法,一切都会像以前一样继续工作,但性能较差。

你可以使用编译期断言保护你的代码,而不是试图使用`testing.T.AllocsPerRun'为性能回归编写一个脆弱的测试。

这是一个实际的 io 包中的技术例子


好的,让我们低调一点!

接口满意检查是很棒的。但是如果你想检查一个简单的布尔表达式,如 1 + 1 == 2

考虑这个代码(playground):

package main

import "crypto/md5"

type Hash [16]byte

func init() {
    if len(Hash{}) < md5.Size {
        panic("Hash is too small")
    }
}

func main() {
    // ...
}

Hash 可能是某种抽象的哈希结果。init 函数确保它将与 crypto/md5 一起工作。如果你改变 Hash 为(比如说)[8]byte,它会在进程启动时发生崩溃。但是,这是一个运行时检查。如果我们想要早点发现怎么办?

如下。(没有 playground 链接,因为这在 playground 上不起作用。)

package main

import "C"

import "crypto/md5"

type Hash [16]byte

func hashIsTooSmall()

func init() {
    if len(Hash{}) < md5.Size {
        hashIsTooSmall()
    }
}

func main() {
    // ...
}

现在如果你改变 Hash[8]byte,它将在编译过程中失败。(实际上,它在链接过程中失败。足够接近我们的目标了。)

$ go build .
# demo
main.hashIsTooSmall: call to external function
main.init.1: relocation target main.hashIsTooSmall not defined
main.init.1: undefined: "main.hashIsTooSmall"

这里发生了什么?

hashIsTooSmall一个没有函数体的声明。编译器假定别人将提供一个实现,也许是一个汇编程序。

当编译器可以证明 len(Hash {})< md5.Size 时,它消除了 if 语句中的代码。结果,没有人使用函数 hashIsTooSmall,所以链接器会消除它。没有其他损害。一旦断言失败,if 语句中的代码将被保留。不会消除 hashIsTooSmall。链接器然后注意到没有人提供了函数的实现然后链接失败,并出现错误,这是我们的目标。

最后一个奇怪的点:为什么是 import "C"? go 工具知道在正常的 Go 代码中,所有函数都必须有主体,并指示编译器强制执行。通过切换到 cgo,我们删除该检查。(如果你在上面的代码中运行 go build -x,而没有添加 import "C" 这行,你会看到编译器是用 -complete 标志调用的。)另一种方法是添加 import "C"向包中添加一个名为 foo.s 的空文件

我仅见过一次这种技术的使用,是在编译器测试套件中。还有其他可以发挥想象力的使用,但我还没见到过。

可能就是这样吧。 :)


via: http://commaok.xyz/post/compile-time-assertions

作者:Josh Bleecher Snyder 译者:geekpi 校对:wxy

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

Linux 上使用 Xfce 桌面环境或许是又快又灵活的 — 但是它目前在遭受着一个很严重的缺陷影响。

使用这个轻量级 GNOME 和 KDE 替代品 Xfce 桌面的用户报告说,其选用的默认壁纸会造成笔记本电脑显示器和液晶显示器的损坏!!!

有确凿的照片证据来支持此观点。

Xfce Bug #12117

“桌面默认开机画面造成显示器损坏!” 某用户在 Xfce 的 Bugzilla Bug 提交区尖叫道。

“默认桌面壁纸导致我的动物去抓它,从我的液晶显示器掉落下来塑料!能让我们选择不同的壁纸吗?我不想再有划痕,谁想呢?让我们结束这老鼠游戏吧。” (LCTT 译注:原文是 whu not,可能想打 who not,也许因屏幕坏了太激动打错字了)

缺陷 flaw — 或者说是这 爪爪 claw ? — 不是个别用户的桌面遇到问题。其他用户也重现了这个问题,尽管不太一样,在这第二个例子,是 红迪网友 Redditor 的不同图片证实的:

目前不知道这锅是 Xfce 的还是猫猫的。如果是后者就没希望修复了,就像便宜的 Android 手机商品(LCTT 译注:原文这里是用 cats 这个单词,是 catalogues 的缩写,一语双关“猫”。原文作者也是个猫奴,#TeamCat 成员)从来得不到他们的 OEM 厂商的升级。

值得庆幸的是 Xubuntu 用户们并没有受到这“爪爪”问题的影响。这是因为它这个基于 Xfce 的 Ubuntu 特色版带有自己的非老鼠的桌面壁纸。

对其他 Linux 发行版的 Xfce 用户来说,“爪爪们”显然对其桌面倒不是那么感兴趣。

已经有人已经提出了一个补丁修复这个问题,但是上游尚未接受。如果你们关注了 bug #12117 ,就可以在你们自己的系统上手动应用这个补丁,去下载以下图片并设置成桌面壁纸。


via: http://www.omgubuntu.co.uk/2017/03/xfce-wallpaper-cat-bug

作者:JOEY SNEDDON 译者:ddvio 校对:jasminepeng

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

不用我说,你也知道 GIF 动画在过去几年发展迅速。人们经常在线上文字交流时使用动画增添趣味,同时这些动画在很多其他地方也显得非常有用。

在技术领域使用动画能够很快的描述出现的问题或者返回的错误。它也能很好的展现出一个软件应用产品的特性。你可以在进行线上座谈会或者在进行公司展示时使用 GIF 动画,当然,你可以在更多的地方用到它。

现在,假设你的电脑桌面上打开了多个应用程序,或者无论出于什么目的,你想制作一个 GIF 动画来记录桌面上一个应用程序窗口的操作过程。你应该怎么做呢?显然,你需要一个工具来完成这件事。

如果你正在寻找了这样一个可以记录桌面上部分区域的工具,并且它可以自动把录屏转化成 GIF 动画; 现在,本教程会介绍一个 Linux 命令行工具来实现你的需求。

开始之前,你必须知道在本教程中所有的例子都是在 Ubuntu 14.04 上测试过的,它的 Bash 版本是 4.3.11(1) 。

Gifine

这个工具的主页是 Gifine 。它基于 GTK 工具包,是用 MoonScript 使用 lgi 库编写的。Gifine 不仅能够录屏、创建动画或视频,而且能够用它来把几个小型动画或视频拼接在一起。

引述这个工具的开发者的话:“你可以加载一个视频帧的目录或者选择一个桌面的区域进行录屏。你加载了一些视频帧后,可以连续查看它们,并裁剪掉不需要的部分。最终完成录屏后可以导出为 gif 或者 mp4 文件。”

Gifine 下载/安装/配置

在指引你下载和安装 Gifine 之前,应该指出安装这个工具时需要安装的依赖包。

首先需要安装的依赖包是 FFmpeg , 这个软件包是一种记录、转化和流化音频以及视频的跨平台解决方案。使用下列命令安装这个工具;

sudo apt-get install ffmpeg

接下来是图像处理系统 GraphicsMagick。这个工具的官网说:“它提供了一个稳健且高效的工具和库的集合,支持读写并且可以操作超过 88 种主要的图像格式,比如:DPX、 GIF、 JPEG、 JPEG-2000、 PNG、 PDF、 PNM 以及 TIFF 等。”

通过下面的命令安装:

sudo apt-get install graphicsmagick

接下来的需要的工具是 XrectSel 。在你移动鼠标选择区域的时候,它会显示矩形区域的坐标位置。我们只能通过源码安装 XrectSel ,你可以从 这里 下载它。

如果你下载了源码,接下来就可以解压下载的文件,进入解压后的目录中。然后,运行下列命令:

./bootstrap

如果 configure 文件不存在,就需要使用上面的命令

./configure --prefix /usr

make

make DESTDIR="$directory" install

最后的依赖包是 Gifsicle 。这是一个命令行工具,可以创建、编辑、查看 GIF 图像和动画的属性信息。下载和安装 Gifsicle 相当容易,你只需要运行下列命令:

sudo apt-get install gifsicle

这些是所有的依赖包。现在,我们开始安装 Gifine 。使用下面的命令完成安装。

sudo apt-get install luarocks

sudo luarocks install --server=http://luarocks.org/dev gifine

请注意第二个命令可能会返回下列错误:

No package 'gobject-introspection-1.0' found

你可以用下列命令安装这个包:

sudo apt-get install libgirepository1.0-dev

然后,再一次运行 luarocks install 命令。

Gifine 使用

完成安装之后可以使用下面的命令运行这个工具:

gifine

这个应用程序的 UI 是这样的:

Gifine UI

这里你可以进行两种操作:录视频帧或者加载视频帧。如果你单击了 录制矩形区域 Record rectange 按钮,你的鼠标指针处会变成一个 + ,这样便可以在你的屏幕上选择一个矩形区域。一旦你选择了一个区域,录屏就开始了, 录制矩形区域 Record rectange 按钮就会变成 停止录制 Stop recording 按钮。

Gifine screen recording

单击 停止录制 Stop recording 完成录屏,会在 Gifine 窗口出现一些按钮。

Gifine preview

用户界面的上半部分显示已经录制的视频帧,你可以使用它下面的滑块进行逐帧浏览。如果你想要删除第 5 帧之前或第 50 帧之后的所有帧数,你可以使用 裁剪左边 Trim left of 裁剪右边 Trim rigth of 按钮进行裁剪。也有可以删除特定帧数和减半删除帧数的按钮,当然,你可以重置所有的裁剪操作。

完成了所有的裁剪后,可以使用 保存 GIF Save GIF... 保存 MP4 Save MP4... 按钮将录屏保存为动画或者视频;你会看到可以设置帧延迟、帧率以及循环次数的选项。

记住,“录屏帧不会自动清除。如果你想重新加载,可以在初始屏幕中使用 加载目录 load directory 按钮在 '/tmp' 目录中找到它们。“

总结

Gifine 的学习曲线并不陡峭 —— 所有的功能都会以按钮、文本的形式体现出来。

对我来说,最大的问题是安装 —— 需要一个个安装它的依赖包,还要处理可能出现的错误,这会困扰很多人。否则,从整体上看,Gifine 绝对称得上是一个不错的工具,如果你正在寻找这样的工具,不妨一试。

已经是 Gifine 用户?到目前为止你得到了什么经验?在评论区告诉我们。


via: https://www.howtoforge.com/tutorial/record-screen-to-animated-gif-on-linux/

作者:Ansh 译者:vim-kakali 校对:wxy

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

LCTT/comic 组成立之前,已有几篇 turnoff.us 漫画发布于 Linux.中国。随着之前的“消沉的程序员”系列漫画的汉化完成,LCTT/comic 翻译仓库也随之建立完成。

那么,本期是 GHLandy 给大家带来的 turnoff.us 上 “ Vi 还是不 Vi,这是个问题 to vi or not to vi ” 的汉化版漫画。如下:

to-vi-or-not-to-vi

上图展示了一个小伙子在有人注视自己工作的时候,使用 Vi 来编辑配置文件,装了一波十三。然后,在人离开后有赶紧拿起趁手的 Sublime 来使用。可能这幅漫画也是很多人的真实写照吧。

相信大家都有各自喜爱的文本编辑器,或者说是开发环境吧。就 GHLandy 本人,也就在文本模式下使用 Vim,然后 GUI 模式使用 Atom 和 notepad++。那么,各位小伙伴,你们各自使用的什么编辑器呢。

感觉这幅漫画要引发激烈争论,快来畅所欲言吧!


via: http://turnoff.us/geek/to-vi-or-not-to-vi/

作者:Daniel Stori 译者:GHLandy 校对:wxy

本文由 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中国 荣誉推出

编者注:本文原文完成于 2014 年,现在的深度 Linux 发行版已经在此基础上获得更多改进,翻译分享此文是为了让大家看看国外的开源社区对一款来自中国的发行版是如何看的。

这是本系列的第六篇 Linux Deepin。这个发行版真的是非常有意思,它有着许多吸引眼球的地方。许许多多的发行版,它们仅仅将已有的应用放入它的应用市场中,使得它们的应用市场十分冷清。但是 Deepin 却将一切变得不同,虽然这个发行版是基于 Debian 的,但是它提供了属它自己的桌面环境。只有很少的发行版能够将它自己创造的软件做得很好。上次我们曾经提到了 Elementary OS 有着自己的 Pantheon 桌面环境。让我们来看看 Deepin 做得怎么样。

首先,在你登录你的账户后,你会在你设计良好的桌面上看到一个欢迎界面和一个精美的 Dock。这个 Dock 是可定制的,根据你放到上面的软件,它可以有着各种特效。

可以看到 Dock 上有着一个启动器图标,但是还有一个办法可以打开启动器,就是将指针移动到左上角。启动器界面优雅,并且可以分类浏览。

你可以做上面的截图中看到,启动器中的应用被分类得井井有条。还有一个好的地方是当你用鼠标点击到左下角,所有桌面上的应用将会最小化。再次点击则会回复原样。

如果你点击右下角,它将会滑出控制中心。这里可以更改所有电脑上的设置。

你可以看到截屏中的控制中心,设计得非常棒而且也是分类得井井有条,你可以在这里设置所有电脑上的项目。甚至可以自定义你的启动界面的壁纸。

Deepin 有一个自己的应用市场。你可以在这里找到绝大多数软件,并且它们很容易安装。应用市场也被设计得很好,分类齐全易于导航。

另一个亮点是 Deepin 的游戏。它提供许多免费的可联网玩耍的游戏,它们非常的有意思可以很好的用于消磨时光。

Deepin 也提供一个好用的音乐播放软件,它有着网络电台点播功能。如果你本地没有音乐你也不用害怕,你可以调到网络电台模式来享受音乐。

总的来说,Deepin 知道如何让用户享受它的产品。就像它们的座右铭那样:“要做,就做出风格”。它们提供的支持服务也非常棒。尽管是个中国的发行版,但是英语支持得也很好,不用担心语言问题。它的安装镜像大约 1.5 GB。你的访问它们的官网来获得更多信息或者下载。我们非常的推荐你试试这个发行版。

这就是本篇 Linux 发行版介绍的全部内容了,我们将会继续介绍其它的发行版。下次再见!


via: http://www.techphylum.com/2014/08/linux-deepin-distro-with-unique-style.html

作者:sumit rohankar 译者:Chao-zhi 校对:wxy

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