golang:
package main
import (
"fmt"
"os"
"reflect"
"runtime/pprof"
"runtime/trace"
"strconv"
"time"
"unsafe"
)
type CalcCollection struct {
}
func (c *CalcCollection) V0() {
arr := map[string]int64{}
for i := int64(0); i < 1000000; i++ {
value := time.Now().Unix()
key := strconv.FormatInt(i, 10) + "_" + strconv.FormatInt(value, 10)
arr[key] = value
}
}
func (c *CalcCollection) V1() {
nums := int64(1000000)
arr := make(map[string]int64, nums)
// key,放循环外,可以重复使用
key := make([]byte, 0)
for i := int64(0); i < nums; i++ {
key = key[:0]
value := time.Now().Unix()
// 改用appendInt,去掉strconv内部[]byte转string的开销
key = strconv.AppendInt(key, i, 10)
key = append(key, '_')
key = strconv.AppendInt(key, value, 10)
keyStr := string(key)
arr[keyStr] = value
}
}
func (c *CalcCollection) V2() {
nums := int64(1000000)
arr := make(map[string]int64, nums)
// 计算key长度,申请存下所有key的[]byte
keyLen := int64(len(strconv.FormatInt(nums, 10)) + 1 + 10)
totalLen := keyLen * nums
key := make([]byte, totalLen)
for i := int64(0); i < nums; i++ {
value := time.Now().Unix()
// 计算当前循环key的位置
pos := i * keyLen
b := key[pos:pos]
b = strconv.AppendInt(b, i, 10)
b = append(b, '_')
b = strconv.AppendInt(b, value, 10)
// 直接将[]byte转为string
arr[*(*string)(unsafe.Pointer(&b))] = value
}
}
// 以下代码请忽略, 作用如下:
// 根据参数决定调用CalcCollection.V{ver}
// 根据参数决定是否记录trace、profile
func main() {
ver := os.Args[len(os.Args)-2]
isRecord := os.Args[len(os.Args)-1] == "t"
calcReflect := reflect.ValueOf(&CalcCollection{})
methodName := "V" + ver
m := calcReflect.MethodByName(methodName)
if isRecord {
traceFile, err := os.Create(methodName + "_trace.out")
if err != nil {
panic(err.Error())
}
err = trace.Start(traceFile)
if err != nil {
panic("start trace fail :" + err.Error())
}
defer trace.Stop()
cpuFile, err := os.Create(methodName + "_cpu.out")
if err != nil {
panic(err.Error())
}
defer cpuFile.Close()
err = pprof.StartCPUProfile(cpuFile)
if err != nil {
panic("StartCPUProfile fail :" + err.Error())
}
defer pprof.StopCPUProfile()
memFile, err := os.Create(methodName + "_mem.out")
if err != nil {
panic(err.Error())
}
defer pprof.WriteHeapProfile(memFile)
}
t := time.Now()
m.Call(make([]reflect.Value, 0))
fmt.Println(methodName, time.Now().Sub(t))
}
php:
$startTime = microtime(true);
$arr = array();
for($i=0;$i<1000000;$i++){
$currentTime = time();
$key = $i . "_" .$currentTime;
$arr[$key] = $currentTime;
}
$endTime = microtime(true);
echo ($endTime - $startTime) * 1000 . "ms\r\n";
Node.js
let startTime = new Date().getTime();
let arr = {};
for (let i = 0; i < 1000000; i++) {
let currentTime = new Date().getTime();
let key = i + '_' + currentTime;
arr[key] = currentTime;
}
let endTime = new Date().getTime();
console.log((endTime - startTime) + "ms");
Python
#!/usr/bin/python
import time
import datetime
def currentTime():
return int(round(time.time() * 1000))
startTime = currentTime()
arr = {}
for i in range(0, 1000000):
cTime = currentTime()
key = str(i) + '_' + str(cTime)
arr[key] = cTime;
endTime = currentTime()
used = str(endTime - startTime)
print (used, "ms \r\n")
Rust:
use chrono::prelude::*;
use std::collections::HashMap;
extern crate chrono;
fn main() {
let start_time = Local::now().timestamp_millis();
let mut i = 0;
let mut arr = HashMap::new();
while i < 1000000 {
let current_time = Local::now().timestamp_millis();
let key = format!("{}_{}", i, current_time);
arr.insert(key, current_time);
i += 1;
}
let end_time = Local::now().timestamp_millis();
println!("{}ms", end_time - start_time);
}
虚拟机(Centos 8.2)下的测试结果:
[root@bogon tmp]# ./test -args 0 f
V0 614.601327ms
[root@bogon tmp]# ./test -args 1 f
V1 330.952331ms
[root@bogon tmp]# ./test -args 2 f
V2 256.896306ms
[root@bogon tmp]# php test.php
300.05478858948ms
[root@bogon tmp]# node --version
v14.15.0
[root@bogon tmp]# node test.js
1861ms
[root@bogon tmp]# python3 test.py
1563 ms
[root@bogon tmp]# cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/tmp`
3351ms
这个对比测试不能代表语言的优劣,有想法的朋友在下面留言
采用JetLua的建议,使用Date.new()直接读取时间,省一次时间对象构造。
let startTime = new Date().getTime();
let arr = {};
for (let i = 0; i < 1000000; i++) {
let currentTime = Date.now(); // new Date().getTime();
let key = i + '_' + currentTime;
arr[key] = currentTime;
}
let endTime = new Date().getTime();
console.log((endTime - startTime) + "ms");
运行:
[root@bogon tmp]# node test.js
1605ms