从接触 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 & Release,Golang 则使用默认配置。

所有测试计量单位均为毫秒(ms)。

首先是计算 π 的例子,代码分别如下。

Golang:

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "time"
  6. )
  7.  
  8. const cNumMax = 999999999
  9.  
  10. func main() {
  11. sign := 1.0
  12. pi := 0.0
  13. t1 := time.Now()
  14. for i := 1; i < cNumMax+2; i += 2 {
  15. pi += (1.0 / float64(i)) * sign
  16. sign = -sign
  17. }
  18. pi *= 4
  19. t2 := time.Now()
  20. fmt.Printf("PI = %f; Time = %d\n", pi, t2.Sub(t1)/time.Millisecond)
  21. }  
  1. C++:
  1. #include "stdafx.h"
  2.  
  3. #include <stdio.h>
  4. #include <time.h>
  5.  
  6. int _tmain(int argc, _TCHAR* argv[])
  7. {
  8. const int cNumMax = 999999999;
  9. double sign = 1.0;
  10. double pi = 0;
  11.  
  12. clock_t t1 = clock();
  13. for (int i = 1; i < cNumMax + 2; i += 2)
  14. {
  15. pi += (1.0f / (double)i) * sign;
  16. sign = -sign;
  17. }
  18. pi *= 4;
  19. clock_t t2 = clock();
  20. printf("PI = %lf; Time = %d\n", pi, t2 - t1);
  21.  
  22. return 0;
  23. }

Delphi:

  1. program PiCalcer;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. {$R *.res}
  6.  
  7. uses
  8. System.SysUtils, System.DateUtils;
  9.  
  10. const
  11. cNumMax = 999999999;
  12.  
  13. var
  14. Sign: Double = 1.0;
  15. Pi : Double = 0.0;
  16. I : Integer;
  17. T1 : Double;
  18. T2 : Double;
  19. S : string;
  20.  
  21. begin
  22. T1 := Now;
  23. I := 1;
  24. while I < cNumMax + 2 do
  25. begin
  26. Pi := Pi + (1.0 / I) * Sign;
  27. Sign := -Sign;
  28. I := I + 2;
  29. end;
  30. Pi := Pi * 4;
  31. T2 := Now;
  32. S := Format('PI = %.6f; Time = %d', [Pi, MilliSecondsBetween(T2, T1)]);
  33. Writeln(S);
  34. Readln;
  35. 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:

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "time"
  6. )
  7.  
  8. const cNumMax = 10000000
  9.  
  10. func main() {
  11. t1 := time.Now()
  12.  
  13. var nums [cNumMax + 1]int
  14. var i, j int
  15. for i = 2; i < cNumMax+1; i++ {
  16. nums[i] = i
  17. }
  18. for i = 2; i < cNumMax+1; i++ {
  19. j = 2
  20. for j*i < cNumMax+1 {
  21. nums[j*i] = 0
  22. j++
  23. }
  24. }
  25. cnt := 0
  26. for i = 2; i < cNumMax+1; i++ {
  27. if nums[i] != 0 {
  28. cnt++
  29. }
  30. }
  31.  
  32. t2 := time.Now()
  33. fmt.Println("Time:", t2.Sub(t1), " Count:", cnt)
  34. }  
  1. C++:
  1. #include "stdafx.h"
  2.  
  3. #include <stdlib.h>
  4. #include <time.h>
  5.  
  6. const int cNumMax = 10000000;
  7.  
  8. int _tmain(int argc, _TCHAR* argv[])
  9. {
  10. clock_t t1 = clock();
  11.  
  12. int *nums = (int*)malloc(sizeof(int) * (cNumMax + 1));
  13.  
  14. int i;
  15. for (i = 2; i < cNumMax + 1; i++)
  16. {
  17. nums[i] = i;
  18. }
  19.  
  20. int j;
  21. for (i = 2; i < cNumMax + 1; i++)
  22. {
  23. j = 2;
  24. while (j * i < cNumMax + 1)
  25. {
  26. nums[j * i] = 0;
  27. j++;
  28. }
  29. }
  30.  
  31. int cnt = 0;
  32. for (i = 2; i < cNumMax + 1; i++)
  33. {
  34. if (nums[i] != 0)
  35. {
  36. cnt++;
  37. }
  38. }
  39.  
  40. free(nums);
  41.  
  42. clock_t t2 = clock();
  43. printf("Time: %dms; Count: %d\n", t2 - t1, cnt);
  44. } 

Delphi:

  1. program PrimeSieve;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. {$R *.res}
  6.  
  7. uses
  8. System.SysUtils, System.DateUtils;
  9.  
  10. const
  11. cNumMax = 10000000;
  12.  
  13. var
  14. T1, T2: Double;
  15. I, J : Integer;
  16. Cnt : Integer;
  17. Nums : array of Integer;
  18.  
  19. begin
  20. T1 := Now;
  21.  
  22. SetLength(Nums, cNumMax + 1);
  23. for I := 2 to cNumMax do
  24. Nums[I] := I;
  25.  
  26. for I := 2 to cNumMax do
  27. begin
  28. J := 2;
  29.  
  30. while J * I < cNumMax + 1 do
  31. begin
  32. Nums[J * I] := 0;
  33. Inc(J);
  34. end;
  35. end;
  36.  
  37. Cnt := 0;
  38. for I := 2 to cNumMax do
  39. begin
  40. if Nums[I] <> 0 then
  41. Inc(Cnt);
  42. end;
  43.  
  44. SetLength(Nums, 0);
  45.  
  46. T2 := Now;
  47.  
  48. Writeln(Format('Cnt = %d; Time = %d', [Cnt, MilliSecondsBetween(T2, T1)]));
  49. Readln;
  50. 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:

  1. package main
  2.  
  3. import (
  4. "bytes"
  5. "fmt"
  6. "strconv"
  7. "time"
  8. )
  9.  
  10. const cNumMax = 1000000
  11.  
  12. // bytes.Buffer(7.2.6)
  13. func testViaBuffer() string {
  14. var buf bytes.Buffer
  15. for i := 0; i < cNumMax; i++ {
  16. buf.WriteString(strconv.Itoa(i))
  17. }
  18. return buf.String()
  19. }
  20.  
  21. // +=
  22. func testViaNormal() string {
  23. var ret string
  24. for i := 0; i < cNumMax; i++ {
  25. ret += strconv.Itoa(i)
  26. }
  27. return ret
  28. }
  29.  
  30. func main() {
  31. fmt.Println("Test via bytes.Buffer...")
  32. t1 := time.Now()
  33. s := testViaBuffer()
  34. t2 := time.Now()
  35. fmt.Printf("Result: %s...(Length = %d); Time: %dms\n", s[2000:2005], len(s), t2.Sub(t1)/time.Millisecond)
  36.  
  37. /*
  38. fmt.Println("Test via normal way...")
  39. t1 = time.Now()
  40. s = testViaNormal()
  41. t2 = time.Now()
  42. fmt.Printf("Result: %s...(Length = %d); Time: %dms\n", s[2000:2005], len(s), t2.Sub(t1)/time.Millisecond)
  43. */
  44. }  
  1. C++:
  1. #include "stdafx.h"
  2.  
  3. #include <time.h>
  4. #include <stdarg.h>
  5. #include <string>
  6. #include <iostream>
  7. using namespace std;
  8.  
  9. const int cNumMax = 1000000;
  10.  
  11. wstring FormatV(const wchar_t* pwcFormat, va_list argList)
  12. {
  13. wstring ws;
  14. int nLen = _vscwprintf(pwcFormat, argList);
  15. if (nLen > 0)
  16. {
  17. ws.resize(nLen);
  18. vswprintf_s(&ws[0], nLen + 1, pwcFormat, argList);
  19. }
  20. return ws;
  21. }
  22.  
  23. wstring __cdecl Format(const wchar_t* pwcFormat, ...)
  24. {
  25. va_list argList;
  26. va_start(argList, pwcFormat);
  27. wstring ws = FormatV(pwcFormat, argList);
  28. va_end(argList);
  29. return ws;
  30. }
  31.  
  32. string FormatVA(const char* pcFormat, va_list argList)
  33. {
  34. string s;
  35. int nLen = _vscprintf(pcFormat, argList);
  36. if (nLen > 0)
  37. {
  38. s.resize(nLen);
  39. vsprintf_s(&s[0], nLen + 1, pcFormat, argList);
  40. }
  41. return s;
  42. }
  43.  
  44. string __cdecl FormatA(const char* pcFormat, ...)
  45. {
  46. va_list argList;
  47. va_start(argList, pcFormat);
  48. string s = FormatVA(pcFormat, argList);
  49. va_end(argList);
  50. return s;
  51. }
  52.  
  53. wstring IntToStr(int nValue)
  54. {
  55. return Format(L"%d", nValue);
  56. }
  57.  
  58. string IntToStrA(int nValue)
  59. {
  60. return FormatA("%d", nValue);
  61. }
  62.  
  63. wstring testW()
  64. {
  65. wstring ret = L"";
  66. for (int i = 0; i < cNumMax; i++)
  67. {
  68. ret += IntToStr(i);
  69. }
  70. return ret;
  71. }
  72.  
  73. string test()
  74. {
  75. string ret = "";
  76. for (int i = 0; i < cNumMax; i++)
  77. {
  78. ret += IntToStrA(i);
  79. }
  80. return ret;
  81. }
  82.  
  83. int _tmain(int argc, _TCHAR* argv[])
  84. {
  85. cout << "Starting test with a loop num of " << cNumMax << endl;
  86. clock_t t1 = clock();
  87. string s = test();
  88. clock_t t2 = clock();
  89. cout << "Result: " << s.substr(2000, 5) << "..." << "; Size: " << s.size() << "; Time: " << t2 - t1 << "ms" << endl;
  90.  
  91. cout << endl;
  92.  
  93. cout << "Starting test for WSTRING with a loop num of " << cNumMax << endl;
  94. t1 = clock();
  95. wstring ws = testW();
  96. t2 = clock();
  97. wcout << "Result: " << ws.substr(2000, 5) << "..." << "; Size: " << ws.size() << "; Time: " << t2 - t1 << "ms" << endl;
  98.  
  99. return 0;
  100. }  

Delphi:

  1. program StrPerformanceTest;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. {$R *.res}
  6.  
  7. uses
  8. System.SysUtils, System.DateUtils;
  9.  
  10. const
  11. cNumMax = 1000000;
  12.  
  13. function TestViaStringBuilder: string;
  14. var
  15. SB: TStringBuilder;
  16. I : Integer;
  17. begin
  18. SB := TStringBuilder.Create;
  19. for I := 0 to cNumMax - 1 do
  20. SB.Append(IntToStr(I));
  21. Result := SB.ToString;
  22. FreeAndNil(SB);
  23. end;
  24.  
  25. function TestViaNormal: string;
  26. var
  27. I : Integer;
  28. begin
  29. Result := '';
  30. for I := 0 to cNumMax - 1 do
  31. Result := Result + IntToStr(I);
  32. end;
  33.  
  34. var
  35. T1: Double;
  36. T2: Double;
  37. S : string;
  38. begin
  39. Writeln('Starting test with a loop num of ', cNumMax, '...');
  40. T1 := Now;
  41. S := TestViaStringBuilder;
  42. T2 := Now;
  43. Writeln(Format('Test via TStringBuilder result: %s...(Length = %d); Time: %dms', [Copy(S, 2001, 5), Length(S), MilliSecondsBetween(T2, T1)]));
  44.  
  45. T1 := Now;
  46. S := TestViaNormal;
  47. T2 := Now;
  48. Writeln(Format('Test via normal-way(+=) result: %s...(Length = %d); Time: %dms', [Copy(S, 2001, 5), Length(S), MilliSecondsBetween(T2, T1)]));
  49. Readln;
  50. end.

 分别执行 10 次。悲剧的是,Golang 里的字符串 += 操作实在太慢了,我实在不想等下去,所以只给出了其官方推荐的使用 bytes.Buffer 的结果。而在这个例子中,Delphi 使用 TStringBuilder 并未显示出什么优化(FastMM 实在太强悍了!),所以我也只给出了普通的串接结果(AnsiString 和 string 都是 Delphi 的原生类型,有着类同的内存布局,效率上应没有什么差别,所以这里只测试了 string)。

Golang                    :141 148 134 119 133 123 145 127 122 132,平均:132.4;

C++(std::string)   :384 400 384 385 389 391 389 384 390 383,平均:387.9;

C++(std::wstring) :519 521 522 521 519 522 518 519 518 518,平均:519.7;

Delphi(string)       :41 41 41 41 41 41 41 41 44 41,平均:41.3;

果然,Delphi 大幅领先,当然这主要归功于 FastMM,这个开源的 Pascal 家族的内存管理器实在太强大了!

当然这个测试对 C++ 并不公平,因为 Golang 的写法并非普通的串接,只是我不知道 STL 或 Boost 里有无类似 StringBuilder 这样的利器呢?

最后是个数据密集计算型的例子。

Golang:

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "time"
  6. )
  7.  
  8. const cSize int = 30
  9.  
  10. type mymatrix [cSize][cSize]int
  11.  
  12. func mkmatrix(rows, cols int, mx *mymatrix) {
  13. rows--
  14. cols--
  15. count := 1
  16. for r := 0; r <= rows; r++ {
  17. for c := 0; c <= cols; c++ {
  18. mx[r][c] = count
  19. count++
  20. }
  21. }
  22. }
  23.  
  24. func multmatrix(rows, cols int, m1, m2 *mymatrix, mm *mymatrix) {
  25. rows--
  26. cols--
  27. for i := 0; i <= rows; i++ {
  28. for j := 0; j <= cols; j++ {
  29. val := 0
  30. for k := 0; k <= cols; k++ {
  31. val += m1[i][k] * m2[k][j]
  32. mm[i][j] = val
  33. }
  34. }
  35. }
  36. }
  37.  
  38. func main() {
  39. var m1, m2, mm mymatrix
  40. mkmatrix(cSize, cSize, &m1)
  41. mkmatrix(cSize, cSize, &m2)
  42. t0 := time.Now()
  43. for i := 0; i <= 100000; i++ {
  44. multmatrix(cSize, cSize, &m1, &m2, &mm)
  45. }
  46. t := time.Since(t0)
  47. fmt.Println(mm[0][0], mm[2][3], mm[3][2], mm[4][4], mm[29][29])
  48. fmt.Println("tick = ", t)
  49. }  
  1. C++:
  1. #include "stdafx.h"
  2.  
  3. #include <time.h>
  4. #include <iostream>
  5.  
  6. using namespace std;
  7.  
  8. const int MATRIX_SIZE = 30;
  9.  
  10. int Matrix[MATRIX_SIZE][MATRIX_SIZE];
  11.  
  12. void MakeMatrix(int rows, int cols, int mx[MATRIX_SIZE][MATRIX_SIZE])
  13. {
  14. rows--;
  15. cols--;
  16. int count = 1;
  17. for (int r = 0; r <= rows; r++)
  18. {
  19. for (int c = 0; c <= cols; c++)
  20. {
  21. mx[r][c] = count;
  22. count++;
  23. }
  24. }
  25. }
  26.  
  27. void MatrixMult(int rows, int cols, const int m1[MATRIX_SIZE][MATRIX_SIZE], const int m2[MATRIX_SIZE][MATRIX_SIZE], int mx[MATRIX_SIZE][MATRIX_SIZE])
  28. {
  29. rows--;
  30. cols--;
  31.  
  32. int val;
  33. for (int i = 0; i <= rows; i++)
  34. {
  35. for (int j = 0; j <= cols; j++)
  36. {
  37. val = 0;
  38. for (int k = 0; k <= cols; k++)
  39. {
  40. val += m1[i][k] * m2[k][j];
  41. mx[i][j] = val;
  42. }
  43. }
  44. }
  45. }
  46.  
  47. int _tmain(int argc, _TCHAR* argv[])
  48. {
  49. int num = 100000;
  50.  
  51. int m1[MATRIX_SIZE][MATRIX_SIZE], m2[MATRIX_SIZE][MATRIX_SIZE], mx[MATRIX_SIZE][MATRIX_SIZE];
  52. MakeMatrix(MATRIX_SIZE, MATRIX_SIZE, m1);
  53. MakeMatrix(MATRIX_SIZE, MATRIX_SIZE, m2);
  54.  
  55. clock_t t1 = clock();
  56. for (int i = 0; i <= num; i++)
  57. {
  58. MatrixMult(MATRIX_SIZE, MATRIX_SIZE, m1, m2, mx);
  59. }
  60. clock_t t2 = clock();
  61. cout << mx[0][0] << " " << mx[2][3] << " " << mx[3][2] << " " << mx[4][4] << endl;
  62. cout << t2 - t1 << " ms" << endl;
  63.  
  64. return 0;
  65. }

Delphi:

  1. program Project1;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. {$R *.res}
  6.  
  7. uses
  8. System.SysUtils, System.DateUtils;
  9.  
  10. const
  11. cSize = 30;
  12.  
  13. type
  14. TMatrix = array[0..cSize - 1, 0..cSize - 1] of Integer;
  15.  
  16. procedure MakeMatrix(Rows, Cols: Integer; var Mx: TMatrix);
  17. var
  18. R, C, Count: Integer;
  19. begin
  20. Dec(Rows);
  21. Dec(Cols);
  22. Count := 1;
  23. for R := 0 to Rows do
  24. for C := 0 to Cols do
  25. begin
  26. Mx[R, C] := Count;
  27. Inc(Count);
  28. end;
  29. end;
  30.  
  31. procedure MatrixMult(Rows, Cols: Integer; const M1, M2: TMatrix; var Mx: TMatrix); inline;
  32. var
  33. I, J, K, Val: Integer;
  34. begin
  35. Dec(Rows);
  36. Dec(Cols);
  37. for I := 0 to Rows do
  38. for J := 0 to Cols do
  39. begin
  40. Val := 0;
  41. for K := 0 to Cols do
  42. Inc(Val, M1[I, K] * M2[K, J]);
  43. Mx[I, J] := Val;
  44. end;
  45. end;
  46.  
  47. var
  48. Num, I : Integer;
  49. M1, M2, Mx: TMatrix;
  50. T1, T2 : Double;
  51.  
  52. begin
  53. Num := 100000;
  54. MakeMatrix(cSize, cSize, M1);
  55. MakeMatrix(cSize, cSize, M2);
  56. T1 := Now;
  57. for I := 0 to Num do
  58. MatrixMult(cSize, cSize, M1, M2, Mx);
  59. T2 := Now;
  60. WriteLn(Mx[0, 0], ' ', Mx[2, 3], ' ', Mx[3, 2], ' ', Mx[4, 4], ' ', mx[29, 29]);
  61. WriteLn(' C = ', MilliSecondsBetween(T2, T1), ' ms');
  62. end.  

分别执行 10 次后结果如下。

Golang:8757 8790 8713 8748 8737 8744 8752 8752 8746 8754,平均:8749.3;

C++     :1723 1735 1714 1707 1713 1725 1708 1723 1720 1725,平均:1719.3;

Delphi :2384 2362 2359 2389 2362 2351 2340 2352 2356 2352,平均:2360.7;

在这样的密集运算例子里,Golang 的表现实在很差,Golang 的编译器优化还有很长的路。而 Delphi 则不出意外,不温不火,勉强也还算能接受吧。

至此,或许大致可以这样初步评断,Golang 在大部分应用场景下在效率方面是满足要求的,而若涉及到密集运算,当前比较好的方法应该是要通过 CGo 了。考虑到 Golang 强大的 goroutine 和 channel、丰富的标准库(譬如网络方面)、精简的语法和非常快速的编译速度(几乎媲美 Delphi),后端开发尝试下 Golang 应是比较可行的,而也确实有不少早已用 Golang 作后端开发的项目实例了。

注:关于 Golang 的语言语法及并发方面的特性,过段时间再浅叙。

经由 Colin 同学建议,测试字符串串接中使用的自实现版 IntToStr 效率不行,对 C++ 很不公平,于是我用回了 _itoa_s 和 _itow_s 这俩库函数,如下:

  1. #include "stdafx.h"
  2.  
  3. #include <time.h>
  4. #include <stdarg.h>
  5. #include <string>
  6. #include <iostream>
  7. using namespace std;
  8.  
  9. const int cNumMax = 1000000;
  10.  
  11. wstring testW()
  12. {
  13. wstring ret = L"";
  14. wchar_t ws[10];
  15. for (int i = 0; i < cNumMax; i++)
  16. {
  17. _itow_s(i, ws, 10);
  18. ret += ws;
  19. }
  20. return ret;
  21. }
  22.  
  23. string test()
  24. {
  25. string ret = "";
  26. char s[10];
  27. for (int i = 0; i < cNumMax; i++)
  28. {
  29. _itoa_s(i, s, 10);
  30. ret += s;
  31. }
  32. return ret;
  33. }
  34.  
  35. int _tmain(int argc, _TCHAR* argv[])
  36. {
  37. cout << "Starting test with a loop num of " << cNumMax << endl;
  38. clock_t t1 = clock();
  39. string s = test();
  40. clock_t t2 = clock();
  41. cout << "Result: " << s.substr(2000, 5) << "..." << "; Size: " << s.size() << "; Time: " << t2 - t1 << "ms" << endl;
  42.  
  43. cout << endl;
  44.  
  45. cout << "Starting test for WSTRING with a loop num of " << cNumMax << endl;
  46. t1 = clock();
  47. wstring ws = testW();
  48. t2 = clock();
  49. wcout << "Result: " << ws.substr(2000, 5) << "..." << "; Size: " << ws.size() << "; Time: " << t2 - t1 << "ms" << endl;
  50.  
  51. return 0;
  52. }

  测试 10 次,效率果然大幅提升,平均大约分别是:std::string - 70ms、std::wstring - 75ms,相当快速!不过还是比 Delphi 慢了 40% 左右。

Golang 效率初(粗)测的更多相关文章

  1. golang语言初体验

    Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型.编译型语言.Go 语言语法与 C 相近,但功能上 ...

  2. 弱网络模拟测试工具---易测app

    易测功能介绍   易测是一款基于无线客户端研发场景的通用测试工具, 它通过在研发人员的自持机上提供各种辅助能力&标准化的专项测试服务来提升研发质量&效率.   易测app是阿里巴巴做的 ...

  3. CArray CList CMap 插入与遍历效率对比

    前言:程序中经常用到不定量数组,选择上可以使用CArray,CList,CMap,而这三者插入及遍历的效率,未测试过,随着数据量越来越大,需要做程序上的优化,于是比较下三种类型的插入盒遍历的效率. 一 ...

  4. 空间划分的数据结构(网格/四叉树/八叉树/BSP树/k-d树/BVH/自定义划分)

    目录 网格 (Grid) 网格的应用 四叉树/八叉树 (Quadtree/Octree) 四叉树/八叉树的应用 BSP树 (Binary Space Partitioning Tree) 判断点在平面 ...

  5. PHP Framework MVC Benchmark 基准测试

    身边有朋友在用yaf框架,讨论的也声音也比较多,今天没事看鸟哥的博客,看到一篇现在PHP主流的几个框架性能对比,比较有意思,给大家分享一下! Yaf是用PHP扩展的形式写的一个PHP框架,也就是以C语 ...

  6. Lua 中的 RSA 加解密实现

    记得之前,部门某款游戏陆陆续续收到一些玩家反馈,抱怨在登录游戏时会等待很久.初步排查后基本断定可能是此游戏的登录服务器程序某块代码有问题,于是即安排了服务器同事作排查分析但一直无果. 之后我时间有了空 ...

  7. Havok Physics 2012(1)

    目录 Chapter 1. Introduction 1. What is a Physics Engine? Chapter 1. Introduction ​ 欢迎来到Havok Physics ...

  8. 最好的IDEA debug长文?看完我佛了

    前言 你好,我是A哥(YourBatman). 最近写了几篇IntelliJ IDEA系列的文章,反响蛮好.我想了下,因为并非是分享什么破解方法.推荐插件.主题这种蛋炒饭式哗众取宠的文章,而是真实对工 ...

  9. Java下好用的开源库推荐

    作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文想介绍下自己在Java下做开发使用到的一些开源的优秀编程库,会不定 ...

随机推荐

  1. Linq to Sql : 并发冲突及处理策略

    原文:Linq to Sql : 并发冲突及处理策略 1. 通过覆盖数据库值解决并发冲突 try { db.SubmitChanges(ConflictMode.ContinueOnConflict) ...

  2. Json 学习

    json 格式: 1) 并列的数据之间用逗号(", ")分隔. 2) 映射用冒号(": ")表示. 3) 并列数据的集合(数组)用方括号("[]&qu ...

  3. 怎样使java程序减少内存占用(转载)

    本文收集网上关于减少java程序占用的一些小知识点 (1)别用new Boolean(). 在很多场景中Boolean类型是必须的,比如JDBC中boolean类型的set与get都是通过Boolea ...

  4. ajax交互方法实现

    AJAX = 异步 JavaScript 和 XML. AJAX 是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个 ...

  5. Ubuntu 16.04 LTS发布

    [Ubuntu 16.04 LTS发布]Ubuntu 16.04 LTS 发布日期已正式确定为 2016 年 4 月 21 日,代号为 Xenial Xerus.Ubuntu16.04 将是非常受欢迎 ...

  6. sed处理url编码解码=== web日志的url处理

    URL 编码/解码方法(linux  shell实现),方法如下: 1.编码的两种方法: admin@~ 11:14:29>echo '手机' | tr -d '\n' | xxd -plain ...

  7. SpringMVC常用配置-文件上传-基于Servlet 3.0

    [2] http://www.cnblogs.com/weilu2/p/springmvc_MultipartConfigElement_tomcat_webapps_work.html

  8. 点击切换panel

    //点击标题切换 $("li[class^='fore-']").click(function(){ var nomber = $(this).index();//点击的第几个 $ ...

  9. java.sql.Connection解决插入数据库中文乱码问题

    import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public clas ...

  10. leetcode bugfree note

    463. Island Perimeterhttps://leetcode.com/problems/island-perimeter/就是逐一遍历所有的cell,用分离的cell总的的边数减去重叠的 ...