热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

go语言对硬件,go语言主要做什么

Go语言中恰到好处的内存对齐在开始之前,希望你计算一下Part1共占用的大小是多少呢?输出结果:这么一算,Part1这一个结构体的占用内存大小为1+4+1+8+115个字节。相信有

Go语言中恰到好处的内存对齐

在开始之前,希望你计算一下 Part1 共占用的大小是多少呢?

输出结果:

这么一算, Part1 这一个结构体的占用内存大小为 1+4+1+8+1 = 15 个字节。相信有的小伙伴是这么算的,看上去也没什么毛病

真实情况是怎么样的呢?我们实际调用看看,如下:

输出结果:

最终输出为占用 32 个字节。这与前面所预期的结果完全不一样。这充分地说明了先前的计算方式是错误的。为什么呢?

在这里要提到 “内存对齐” 这一概念,才能够用正确的姿势去计算,接下来我们详细的讲讲它是什么

有的小伙伴可能会认为内存读取,就是一个简单的字节数组摆放

上图表示一个坑一个萝卜的内存读取方式。但实际上 CPU 并不会以一个一个字节去读取和写入内存。相反 CPU 读取内存是 一块一块读取 的,块的大小可以为 2、4、6、8、16 字节等大小。块大小我们称其为 内存访问粒度 。如下图:

在样例中,假设访问粒度为 4。 CPU 是以每 4 个字节大小的访问粒度去读取和写入内存的。这才是正确的姿势

另外作为一个工程师,你也很有必要学习这块知识点哦 :)

在上图中,假设从 Index 1 开始读取,将会出现很崩溃的问题。因为它的内存访问边界是不对齐的。因此 CPU 会做一些额外的处理工作。如下:

从上述流程可得出,不做 “内存对齐” 是一件有点 "麻烦" 的事。因为它会增加许多耗费时间的动作

而假设做了内存对齐,从 Index 0 开始读取 4 个字节,只需要读取一次,也不需要额外的运算。这显然高效很多,是标准的 空间换时间 做法

在不同平台上的编译器都有自己默认的 “对齐系数”,可通过预编译命令 #pragma pack(n) 进行变更,n 就是代指 “对齐系数”。一般来讲,我们常用的平台的系数如下:

另外要注意,不同硬件平台占用的大小和对齐值都可能是不一样的。因此本文的值不是唯一的,调试的时候需按本机的实际情况考虑

输出结果:

在 Go 中可以调用 unsafe.Alignof 来返回相应类型的对齐系数。通过观察输出结果,可得知基本都是 2^n ,最大也不会超过 8。这是因为我手提(64 位)编译器默认对齐系数是 8,因此最大值不会超过这个数

在上小节中,提到了结构体中的成员变量要做字节对齐。那么想当然身为最终结果的结构体,也是需要做字节对齐的

接下来我们一起分析一下,“它” 到底经历了些什么,影响了 “预期” 结果

在每个成员变量进行对齐后,根据规则 2,整个结构体本身也要进行字节对齐,因为可发现它可能并不是 2^n ,不是偶数倍。显然不符合对齐的规则

根据规则 2,可得出对齐值为 8。现在的偏移量为 25,不是 8 的整倍数。因此确定偏移量为 32。对结构体进行对齐

Part1 内存布局:axxx|bbbb|cxxx|xxxx|dddd|dddd|exxx|xxxx

通过本节的分析,可得知先前的 “推算” 为什么错误?

是因为实际内存管理并非 “一个萝卜一个坑” 的思想。而是一块一块。通过空间换时间(效率)的思想来完成这块读取、写入。另外也需要兼顾不同平台的内存操作情况

在上一小节,可得知根据成员变量的类型不同,其结构体的内存会产生对齐等动作。那假设字段顺序不同,会不会有什么变化呢?我们一起来试试吧 :-)

输出结果:

通过结果可以惊喜的发现,只是 “简单” 对成员变量的字段顺序进行改变,就改变了结构体占用大小

接下来我们一起剖析一下 Part2 ,看看它的内部到底和上一位之间有什么区别,才导致了这样的结果?

符合规则 2,不需要额外对齐

Part2 内存布局:ecax|bbbb|dddd|dddd

通过对比 Part1 和 Part2 的内存布局,你会发现两者有很大的不同。如下:

仔细一看, Part1 存在许多 Padding。显然它占据了不少空间,那么 Padding 是怎么出现的呢?

通过本文的介绍,可得知是由于不同类型导致需要进行字节对齐,以此保证内存的访问边界

那么也不难理解,为什么 调整结构体内成员变量的字段顺序 就能达到缩小结构体占用大小的疑问了,是因为巧妙地减少了 Padding 的存在。让它们更 “紧凑” 了。这一点对于加深 Go 的内存布局印象和大对象的优化非常有帮

golang 对XP支持怎么样

总体还说还是非常有效而且实用的。

1.为什么golang的开发效率高?

golang是一编译型的强类型语言,它在开发上的高效率主要来自于后发优势,不用考虑旧有恶心的历史,又有一个较高的工程视角。良好的避免了程序员因为“ { 需不需要独占一行 ”这种革命问题打架,也解决了一部分趁编译时间找产品妹妹搭讪的阶级敌人。

它有自己的包管理机制,工具链成熟,从开发、调试到发布都很简单方便;

有反向接口、defer、coroutine等大量的syntactic sugar;

编译速度快,因为是强类型语言又有gc,只要通过编译,非业务毛病就很少了;

它在语法级别上支持了goroutine,这是大家说到最多的内容,这里重点提一下。首先,coroutine并不稀罕,语言并不能超越硬件、操作系统实现神乎其神的功能。golang可以做到事情,其他语言也可以做到,譬如c++,在boost库里面自己就有的coroutine实现(当然用起来跟其他boost库一样恶心)。golang做的事情,是把这一套东西的使用过程简化了,并且提供了一套channel的通信模式,使得程序员可以忽略诸如死锁等问题。

goroutine的目的是描述并发编程模型。并发与并行不同,它并不需要多核的硬件支持,它不是一种物理运行状态,而是一种程序逻辑流程。它的主要目的不是利用多核提高运行效率,而是提供一种更容易理解、不容易出错的语言来描述问题。

实际上golang默认就是运行在单OS进程上面的,通过指定环境变量GOMAXPROCS才能转身跑在多OS进程上面。有人提到了网易的pomelo,开源本来是一件很不错的事情,但是基于自己对callback hell的偏见,我一直持有这种态度:敢用nodejs写大规模游戏服务器的人,都是真正的勇士 : ) 。

2、Erlang与Golang的coroutine有啥区别,coroutine是啥?

coroutine本质上是语言开发者自己实现的、处于user space内的线程,无论是erlang、还是golang都是这样。需要解决没有时钟中断;碰着阻塞式i\o,整个进程都会被操作系统主动挂起;需要自己拥有调度控制能力(放在并行环境下面还是挺麻烦的一件事)等等问题。那为啥要废老大的劲自己做一套线程放user space里面呢?

并发是服务器语言必须要解决的问题;

system space的进程还有线程调度都太慢了、占用的空间也太大了。

把线程放到user space的可以避免了陷入system call进行上下文切换以及高速缓冲更新,线程本身以及切换等操作可以做得非常的轻量。这也就是golang这类语言反复提及的超高并发能力,分分钟给你开上几千个线程不费力。

不同的是,golang的并发调度在i/o等易发阻塞的时候才会发生,一般是内封在库函数内;erlang则更夸张,对每个coroutine维持一个计数器,常用语句都会导致这个计数器进行reduction,一旦到点,立即切换调度函数。

中断介入程度的不同,导致erlang看上去拥有了preemptive scheduling的能力,而golang则是cooperative shceduling的。golang一旦写出纯计算死循环,进程内所有会话必死无疑;要有大计算量少i\o的函数还得自己主动叫runtime.Sched()来进行调度切换。

3、golang的运行效率怎么样?

我是相当反感所谓的ping\pong式benchmark,运行效率需要放到具体的工作环境下面考虑。

首先,它再快也是快不过c的,毕竟底下做了那么多工作,又有调度,又有gc什么的。那为什么在那些benchmark里面,golang、nodejs、erlang的响应效率看上去那么优秀呢,响应快,并发强?并发能力强的原因上面已经提到了,响应快是因为大量非阻塞式i\o操作出现的原因。这一点c也可以做到,并且能力更强,但是得多写不少优质代码。

然后,针对游戏服务器这种高实时性的运行环境,GC所造成的跳帧问题确实比较麻烦,前面的大神 @达达 有比较详细的论述和缓解方案,就不累述了 。随着golang的持续开发,相信应该会有非常大的改进。一是屏蔽内存操作是现代语言的大势所趋,它肯定是需要被实现的;二是GC算法已经相当的成熟,效率勉勉强强过得去;三是可以通过incremental的操作来均摊cpu消耗。

用这一点点效率损失换取一个更高的生产能力是不是值得呢?我觉得是值得的,硬件已经很便宜了,人生苦短,让自己的生活更轻松一点吧: )。

4、基于以上的论述,我认为采用go进行小范围的MMORPG开发是可行的。

GO语言和C++比优缺点在那?

C++适合本地程序的开发。Go语言适合网络程序和本地程序的开发。Go的优点:垃圾回收,语意明确,格式统一。 Go的缺点:效率目前没有C++高,但对于桌面程序而言,效率问题不大,因为硬件已经很快了。c++过于复杂了,加入很多炫技的内容。这些内容脱离了事情的本质。

最明显的就是所谓的面向对象。基于面向对象的工程如果足够大的情况下,会带来很大的耦合度,如果再加上内存管理,多线程等等。项目后期基本上没办法维护和增加功能。

关于c++的语言复杂性,你可以问知乎上的任何一位高手。没一个敢说自己精通c++。你也可以去看一下所有的c++编绎器,没有任何一个敢说自己完全实现了c++的标准。不同的编绎器之间实现细节又不同。所以功能再强大没有实用性,就失去了意义,只会制造更多的问题。

c#和go语言的区别

c:面向过程,语法太麻烦c#:面向对象(跟java很像如果你对java了解估计你就会明白c&c#之间的区别了),是ms.netframework的主力之一,它的代码运行是安全的,里面没有指针,像java一样有垃圾回收机制。语法基本没有区别,个人感觉首先c#不必对指针进行太多的研究,然后可遗址性等,其它的区别相当大。可以说不是一个方向的。开发环境跟开发语言也是两个不同的概念学习c#并不必须有c语言的基础,不过,如果你学过c语言,那会事半功倍的,因为他们之间有很多语法是一样的。作为初学者,并没有必要先去学习c语言,你只需要有c#的完整的教程就行了。举个简单的例子,你想学开高档的轿车并不需要先去学习开低档的面包车。但如果你已经会开面包车的话,那么学开轿车就一定会容易一些了,因为他们有很多相同的地方。C语言:C语言是国际上广泛流行的、很有发展前途的计算机高级语言。它适合作为系统描述语言,即可用来编写系统软件,也可用来编写应用软件。早期的操作系统等系统软件主要是用汇编语言编写的(包括UNIX操作系统在内)。由于汇编语言依赖于计算机硬件,程序的可读性和可移植性都比较差。为了提高可读性和可移植性,最好改用高级语言,但一般的高级语言难以实现汇编语言的某些功能(汇编语言可以直接对硬件进行操作),例如:对内存地址的操作、位操作等)。人们设想能否找到一种既具有一般高级语言特性,又具有低级语言特性的语言,集它们的优点于一身。于是,C语言就在这种情况下应运而生了。C语言是在B语言的基础上发展起来的,它的根源可以追溯到ALGOL60。1960年出现的ALGOL60是一种面向问题的高级语言,它离硬件比较远,不宜用来编写系统程序。1963年英国的剑桥大学推出了CPL(CombinedProgram-mingLanguage)语言。CPL语言在ALGOL60的基础上接近了硬件一些,但规模比较大,难以实现。1967年英国剑桥大学的MatinRichards对CPL语言作了简化,推出了BCPL(BasicCombinedProgrammingLanguage)语言。1970年美国贝尔实验室的KenThompson以BCPL语言为基础,又作了进一步简化,设计出了很简单的而且很接近硬件的B语言(取BCPL的第一个字母),并用B语言写第一个UNIX操作系统,在PDP-7上实现。1971年在PDP-11/20上实现了B语言,并写了UNIX操作系统。但B语言过于简单,功能有限。1972年至1973年间,贝尔实验室的D.M.Ritchie在B语言的基础上设计出了C语言(取BCPL的第二个字母)。C语言既保持了BCPL和B语言的优点(精练、接近硬件),又克服了它们的缺点(过于简单、数据无类型等)。最初的C语言只是为描述和实现UNIX操作系统提供一种工作语言而设计的。1973年,K.Thom-pson和D.M.ritchie两人合作把UNIX的90%以上用C改写(UNIX第5版。原来的UNIX操作系统是1969年由美国的贝尔实验室的K.Thompson和D.M.Ritchie开发成功的,是用汇编语言写的)。后来,C语言多次作了改进,但主要还是在贝尔实验室内部使用。直到1-975年UNIX第6版公布后,C语言的突出优点才引起人们普遍注意。1977年出现了不依赖于具体机器的C语言编译文本《可移植C语言编译程序》,使C移植到其它机器时所做的工作大大简化了,这也推动了UNIX操作系统迅速地在各种机器上实现。例如,VAX,ATT等计算机系统都相继开发了UNIX。随着UNIX的日益广泛使用,C语言也迅速得到推广。C语言和UNIX可以说是一对孪生兄弟,在发展过程中相辅相成。1978年以后,C语言已先后移植到大、中、小、微型机上,已独立于UNIX和PDP了。现在C语言已风靡全世界,成为世界上应用最广泛的几种计算机语言之一。以1978年发表的UNIX第7版中的C编译程序为基础,BrianW.Kernighan和DennisM.Ritchie(合称KR)合著了影响深远了名著《TheCProgrammingLan-guage》,这本书中介绍的C语言成为后来广泛使用的C语言版本的基础,它被称为标准C。1983年,美国国家标准化协会(ANSI)根据C语言问世以来各种版本对C的发展和扩充,制定了新的标准,称为ANSIC。ANSIC比原来的标准C有了很大的发展。KR在1988年修改了他们的经典著作《TheCProgra-mmingLanguage》,按照ANSIC的标准重新写了该书。1987年,ANSIC又公布了新标准--87ANSIC。目前流行的C编译系统都是以它为基础的。C#:C#是Microsoft公司设计的一种编程语言。它松散地基于C/C++,并且有很多方面和Java类似。Microsoft是这样描述C#的:“C#是从C和C++派生来的一种简单、现代、面向对象和类型安全的编程语言。C#(读做‘Csharp’)主要是从C/C++编程语言家族移植过来的,C和C++的程序员会马上熟悉它。C#试图结合VisualBasic的快速开发能力和C++的强大灵活的能力。”附:一个简单的C#程序是怎样的?可以是这样:classCApplication{publicstaticvoidMain(){System.Console.Write(“Hello,new.NETworld!”);}}(你不能将Main()作为全局函数——C#没有全局函数)C#是面向对象的吗?是的,C#像Java和C++一样,是一个面向对象的语言。C#有自己的类库吗?不,就像所有的.NET语言(VB.Net,JScript.Net)一样,C#访问.NET类库,C#没有自己的类库。C#提供什么标准类型?C#支持的基本类型和C++很相似,包括int,long,float,double,char,string,arrays,structs和classes。然而,不要假设太多,名字可能很形似,但是一些细节不相同。例如C#中的long是64位的,而C++的long取决于平台,32位的平台上是32位的,64位的平台上是64位的。class和struct在C++中几乎完全一样,但在C#中并不是这样的。

go语言能做什么 关于go语言的介绍

1、Go作为Google2009年推出的语言,其被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。

2、对于高性能分布式系统领域而言,Go 语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持,这对于游戏服务端的开发而言是再好不过了。

3、到现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。


推荐阅读
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 本文详细介绍了如何使用OpenSSL自建CA证书的步骤,包括准备工作、生成CA证书、生成服务器待签证书以及证书签名等过程。 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • 重要知识点有:函数参数默许值、盈余参数、扩大运算符、new.target属性、块级函数、箭头函数以及尾挪用优化《深切明白ES6》笔记目次函数的默许参数在ES5中,我们给函数传参数, ... [详细]
  • 字节流(InputStream和OutputStream),字节流读写文件,字节流的缓冲区,字节缓冲流
    字节流抽象类InputStream和OutputStream是字节流的顶级父类所有的字节输入流都继承自InputStream,所有的输出流都继承子OutputStreamInput ... [详细]
  • V8不仅是一款著名的八缸发动机,广泛应用于道奇Charger、宾利Continental GT和BossHoss摩托车中。自2008年以来,作为Chromium项目的一部分,V8 JavaScript引擎在性能优化和技术创新方面取得了显著进展。该引擎通过先进的编译技术和高效的垃圾回收机制,显著提升了JavaScript的执行效率,为现代Web应用提供了强大的支持。持续的优化和创新使得V8在处理复杂计算和大规模数据时表现更加出色,成为众多开发者和企业的首选。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 本文探讨了如何利用 jQuery 的 JSONP 技术实现跨域调用外部 Web 服务。通过详细解析 JSONP 的工作原理及其在 jQuery 中的应用,本文提供了实用的代码示例和最佳实践,帮助开发者解决跨域请求中的常见问题。 ... [详细]
  • 《精通 jQuery》第六章:深入解析与实战应用
    《精通 jQuery》第六章:深入解析与实战应用本章详细探讨了 Ajax 技术的核心机制及其实际应用。Ajax 通过 XMLHttpRequest 对象实现客户端与服务器之间的异步数据交换,从而在不重新加载整个页面的情况下更新部分内容。这种技术不仅提升了用户体验,还提高了应用的响应速度和效率。此外,本章还介绍了如何利用 jQuery 简化 Ajax 操作,并提供了多个实战案例,帮助读者更好地理解和掌握这一重要技术。 ... [详细]
  • 本文详细介绍了在 Ubuntu 系统上搭建 Hadoop 集群时遇到的 SSH 密钥认证问题及其解决方案。通过本文,读者可以了解如何在多台虚拟机之间实现无密码 SSH 登录,从而顺利启动 Hadoop 集群。 ... [详细]
  • 结城浩(1963年7月出生),日本资深程序员和技术作家,居住在东京武藏野市。他开发了著名的YukiWiki软件,并在杂志上发表了大量程序入门文章和技术翻译作品。结城浩著有30多本关于编程和数学的书籍,其中许多被翻译成英文和韩文。 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 本文详细介绍了MySQL数据库的基础语法与核心操作,涵盖从基础概念到具体应用的多个方面。首先,文章从基础知识入手,逐步深入到创建和修改数据表的操作。接着,详细讲解了如何进行数据的插入、更新与删除。在查询部分,不仅介绍了DISTINCT和LIMIT的使用方法,还探讨了排序、过滤和通配符的应用。此外,文章还涵盖了计算字段以及多种函数的使用,包括文本处理、日期和时间处理及数值处理等。通过这些内容,读者可以全面掌握MySQL数据库的核心操作技巧。 ... [详细]
  • 阿里巴巴终面技术挑战:如何利用 UDP 实现 TCP 功能?
    在阿里巴巴的技术面试中,技术总监曾提出一道关于如何利用 UDP 实现 TCP 功能的问题。当时回答得不够理想,因此事后进行了详细总结。通过与总监的进一步交流,了解到这是一道常见的阿里面试题。面试官的主要目的是考察应聘者对 UDP 和 TCP 在原理上的差异的理解,以及如何通过 UDP 实现类似 TCP 的可靠传输机制。 ... [详细]
author-avatar
园园哚
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有