设为首页 收藏本站
查看: 910|回复: 0

[经验分享] Golang 效率初(粗)测

[复制链接]
累计签到:2 天
连续签到:1 天
发表于 2018-9-20 08:11:29 | 显示全部楼层 |阅读模式
  从接触 Golang 开始,断断续续已有差不多一年左右的时间了,都是业余自己学学看看,尚主要限于语法及语言特性,还没有用它写过实际的项目。
  关于 Golang 的语法及语言特性,网上有很多资源可以学习。后面某个时间,我也许会写一篇粗浅的文章,来比较一下 Golang 和 C++、Delphi 甚至 C# 等语言语法方面的特性。
  我算是个急性子的人(当然现在好一些了),于是作为码农,显而易见会对“效率”比较敏感。这里的效率不单单指编译器生成的机器码优化程度,也包括编译器的编译速度,所以我对 C++ 兴趣不算大,虽然它是我平时的工作语言。
  言归正传。

  分别用 Golang、C++、Delphi 写了四个小例子,包括普通的应用场景、字符串(串接)操作及数据密集计算(当然也会涉及到譬如库函数的优化等)。我的电脑软硬件环境为:Win7 64bit,Xeon E3-1230(8核),16G RAM。Golang 版本是 1.3.1 Windows/386,VC 则用的 VS 2012,而 Delphi 则用的 XE6 Update1。VC 和 Delphi 编译设置为 Win32 &>  所有测试计量单位均为毫秒(ms)。
  首先是计算 π 的例子,代码分别如下。
  Golang:
  

package main  

  
import (
  
"fmt"
  
"time"
  
)
  

  
const cNumMax = 999999999
  

  
func main() {
  
sign := 1.0
  
pi := 0.0
  
t1 := time.Now()
  
for i := 1; i < cNumMax+2; i += 2 {
  
pi += (1.0 / float64(i)) * sign
  
sign = -sign
  
}
  
pi *= 4
  
t2 := time.Now()
  
fmt.Printf("PI = %f; Time = %d\n", pi, t2.Sub(t1)/time.Millisecond)
  
}  
  

  

C++:  

  

#include "stdafx.h"  

  
#include
  
#include
  

  
int _tmain(int argc, _TCHAR* argv[])
  
{
  
const int cNumMax = 999999999;
  
double sign = 1.0;
  
double pi = 0;
  

  
clock_t t1 = clock();
  
for (int i = 1; i < cNumMax + 2; i += 2)
  
{
  
pi += (1.0f / (double)i) * sign;
  
sign = -sign;
  
}
  
pi *= 4;
  
clock_t t2 = clock();
  
printf("PI = %lf; Time = %d\n", pi, t2 - t1);
  

  
return 0;
  
}
  

  

  Delphi:
  

program PiCalcer;  

  
{$APPTYPE CONSOLE}
  

  
{$R *.res}
  

  
uses
  
System.SysUtils, System.DateUtils;
  

  
const
  
cNumMax = 999999999;
  

  
var
  
Sign: Double = 1.0;
  
Pi  : Double = 0.0;
  
I   : Integer;
  
T1  : Double;
  
T2  : Double;
  
S   : string;
  

  
begin
  
T1 := Now;
  
I := 1;
  
while I < cNumMax + 2 do
  
begin
  
Pi := Pi + (1.0 / I) * Sign;
  
Sign := -Sign;
  
I := I + 2;
  
end;
  
Pi := Pi * 4;
  
T2 := Now;
  
S := Format('PI = %.6f; Time = %d', [Pi, MilliSecondsBetween(T2, T1)]);
  
Writeln(S);
  
Readln;
  
end.
  

  

  分别执行 10 次,结果如下。
  Golang:2038 2028 2036 2024 2034 2015 2034 2018 2024 2018,平均:2026.9;
  C++     :2041 2052 2062 2036 2033 2049 2039 2026 2037 2038,平均:2041.3;
  Delphi :2594 2572 2574 2584 2574 2564 2575 2575 2571 2563,平均:2574.6。
  结果居然很不错,比 VC 还快,而 Delphi,大家都懂,优化向来不是它的“强项”。
  然后是个质数生成例子。
  Golang:
  

package main  

  
import (
  
"fmt"
  
"time"
  
)
  

  
const cNumMax = 10000000
  

  
func main() {
  
t1 := time.Now()
  

  
var nums [cNumMax + 1]int
  
var i, j int
  
for i = 2; i < cNumMax+1; i++ {
  
nums = i
  
}
  
for i = 2; i < cNumMax+1; i++ {
  
j = 2
  
for j*i < cNumMax+1 {
  
nums[j*i] = 0
  
j++
  
}
  
}
  
cnt := 0
  
for i = 2; i < cNumMax+1; i++ {
  
if nums != 0 {
  
cnt++
  
}
  
}
  

  
t2 := time.Now()
  
fmt.Println("Time:", t2.Sub(t1), " Count:", cnt)
  
}  
  

  

C++:  

  

#include "stdafx.h"  

  
#include
  
#include
  

  
const int cNumMax = 10000000;
  

  
int _tmain(int argc, _TCHAR* argv[])
  
{
  
clock_t t1 = clock();
  

  
int *nums = (int*)malloc(sizeof(int) * (cNumMax + 1));
  

  
int i;
  
for (i = 2; i < cNumMax + 1; i++)
  
{
  
nums = i;
  
}
  

  
int j;
  
for (i = 2; i < cNumMax + 1; i++)
  
{
  
j = 2;
  
while (j * i < cNumMax + 1)
  
{
  
nums[j * i] = 0;
  
j++;
  
}
  
}
  

  
int cnt = 0;
  
for (i = 2; i < cNumMax + 1; i++)
  
{
  
if (nums != 0)
  
{
  
cnt++;
  
}
  
}
  

  
free(nums);
  

  
clock_t t2 = clock();
  
printf("Time: %dms; Count: %d\n", t2 - t1, cnt);
  
} 
  

  Delphi:
  

program PrimeSieve;  

  
{$APPTYPE CONSOLE}
  

  
{$R *.res}
  

  
uses
  
System.SysUtils, System.DateUtils;
  

  
const
  
cNumMax = 10000000;
  

  
var
  
T1, T2: Double;
  
I, J  : Integer;
  
Cnt   : Integer;
  
Nums  : array of Integer;
  

  
begin
  
T1 := Now;
  

  
SetLength(Nums, cNumMax + 1);
  
for I := 2 to cNumMax do
  
Nums[I] := I;
  

  
for I := 2 to cNumMax do
  
begin
  
J := 2;
  

  
while J * I < cNumMax + 1 do
  
begin
  
Nums[J * I] := 0;
  
Inc(J);
  
end;
  
end;
  

  
Cnt := 0;
  
for I := 2 to cNumMax do
  
begin
  
if Nums[I]  0 then
  
Inc(Cnt);
  
end;
  

  
SetLength(Nums, 0);
  

  
T2 := Now;
  

  
Writeln(Format('Cnt = %d; Time = %d', [Cnt, MilliSecondsBetween(T2, T1)]));
  
Readln;
  
end.  
  

  同样分别执行 10 次,结果如下。
  Golang:959 957 959 953 961 951 948 956 956 956,平均:955.6;
  C++     :965 965 967 953 961 964 963 960 956 956,平均:961;
  Delphi : 973 976 973 982 981 970 977 979 971 977,平均:975.9;
  仍然,Golang 看上去最快,而 Delphi 则很正常地居末。
  所以我忍不住想要来一个能展现 Delphi 优点的例子,这个例子几乎毫无疑问,和字符串操作(及内存管理器)相关,所以有如下字符串串接的示例(其中涉及到了譬如 IntToStr / itoa 这样的函数调用,我自己实现了个 C++ 版的 IntToStr)。
  Golang:
  

package main  

  
import (
  
"bytes"
  
"fmt"
  
"strconv"
  
"time"
  
)
  

  
const cNumMax = 1000000
  

  
// bytes.Buffer(7.2.6)
  
func testViaBuffer() string {
  
var buf bytes.Buffer
  
for i := 0; i < cNumMax; i++ {
  
buf.WriteString(strconv.Itoa(i))
  
}
  
return buf.String()
  
}
  

  
// +=
  
func testViaNormal() string {
  
var ret string
  
for i := 0; i < cNumMax; i++ {
  
ret += strconv.Itoa(i)
  
}
  
return ret
  
}
  

  
func main() {
  
fmt.Println("Test via bytes.Buffer...")
  
t1 := time.Now()
  
s := testViaBuffer()
  
t2 := time.Now()
  
fmt.Printf("Result: %s...(Length = %d); Time: %dms\n", s[2000:2005], len(s), t2.Sub(t1)/time.Millisecond)
  

  
/*
  
fmt.Println("Test via normal way...")
  
t1 = time.Now()
  
s = testViaNormal()
  
t2 = time.Now()
  
fmt.Printf("Result: %s...(Length = %d); Time: %dms\n", s[2000:2005], len(s), t2.Sub(t1)/time.Millisecond)
  
*/
  
}  
  

  

C++:  

  

#include "stdafx.h"  

  
#include
  
#include
  
#include
  
#include
  
using namespace std;
  

  
const int cNumMax = 1000000;
  

  
wstring FormatV(const wchar_t* pwcFormat, va_list argList)
  
{
  
wstring ws;
  
int nLen = _vscwprintf(pwcFormat, argList);
  
if (nLen > 0)
  
{
  
ws.resize(nLen);
  
vswprintf_s(&ws[0], nLen + 1, pwcFormat, argList);
  
}
  
return ws;
  
}
  

  
wstring __cdecl Format(const wchar_t* pwcFormat, ...)
  
{
  
va_list argList;
  
va_start(argList, pwcFormat);
  
wstring ws = FormatV(pwcFormat, argList);
  
va_end(argList);
  
return ws;
  
}
  

  
string FormatVA(const char* pcFormat, va_list argList)
  
{
  
string s;
  
int nLen = _vscprintf(pcFormat, argList);
  
if (nLen > 0)
  
{
  
s.resize(nLen);
  
vsprintf_s(&s[0], nLen + 1, pcFormat, argList);
  
}
  
return s;
  
}
  

  
string __cdecl FormatA(const char* pcFormat, ...)
  
{
  
va_list argList;
  
va_start(argList, pcFormat);
  
string s = FormatVA(pcFormat, argList);
  
va_end(argList);
  
return s;
  
}
  

  
wstring IntToStr(int nValue)
  
{
  
return Format(L"%d", nValue);
  
}
  

  
string IntToStrA(int nValue)
  
{
  
return FormatA("%d", nValue);
  
}
  

  
wstring testW()
  
{
  
wstring ret = L"";
  
for (int i = 0; i < cNumMax; i++)
  
{
  
ret += IntToStr(i);
  
}
  
return ret;
  
}
  

  
string test()
  
{
  
string ret = "";
  
for (int i = 0; i < cNumMax; i++)
  
{
  
ret += IntToStrA(i);
  
}
  
return ret;
  
}
  

  
int _tmain(int argc, _TCHAR* argv[])
  
{
  
cout

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-598368-1-1.html 上篇帖子: golang自定义路由控制实现(一) 下篇帖子: GoLang之基础
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表