一个小栗子比较 golang、php、Node.js、Python、Rust 性能
看到网友toozyxia(https://my.oschina.net/xiayongsheng/blog/4775399)的对比,突发奇想,增加Node.js的对比
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:
<?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

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
前端开发还可以这么玩?元数据实践分享
摘要:元数据是业务流中前端和业务侧实现共同使用的一种规范,是沟通前后端的桥梁,其通过统一的数据格式进行约束,从而约定前后端传参。使用元数据,大幅提升了开发效率,又降低了维护及二次开发成本。 1 ROMA 业务流简介 ROMA 业务流(以下简称“业务流”)是一个基于ROMA Connect平台的应用集成与数据开放服务,适用于跨实例、跨应用的企业系统集成场景。业务流支持通过可视化UI界面来创建任务,从而降低了不同经验背景的用户的开发门槛。 图1-1 业务流demo 2 元数据概述 Metadata(以下称作“元数据”)是业务流的一个重要概念,用于约束前端生成的数据模型,同时驱动业务的逻辑实现,是前端页面和后端业务共同使用的一种规范。 在前端的实现中,元数据负责驱动前端框架,用于构建一个完全由元数据建模动态生成的界面。在业务流开发过程中,只需添加新的Json格式的元数据即可添加新的组件,而无需再进行前端开发,这实现了快速开发、减少维护的目标。 在业务侧,处理程序是按照元数据模型实现的,这也就意味着用户将会在前端输入足够执行业务侧的数据从而正确运行业务逻辑。 并非为前端服务 需要注意的是,元数...
- 下一篇
回顾 Kotlin 1.4 的全新语言特性和更多改进
发布人:开发技术推广工程师 Wojtek Kaliciński 来自开发者社区的热情与积极采用推动了 Kotlin 成为 Android 开发的 首选语言 (Kotlin-first)。随着 Kotlin 不断发展,JetBrains(Kotlin 的创建者)、开源社区以及 Google 团队也将持续投入更多的资源和精力。 我们很高兴与大家分享 Kotlin 1.4 版本,这将是 Kotlin 发展的下一个里程碑,包含新的语言特性、改进的编译器和工具。以下是此版本中部分振奋人心的新特性的简要概述。您可以在 JetBrains 官方博客 中阅读有关 Kotlin 1.4 的更多信息。 新语言特性 Kotlin 1.4 中引入的新语言特性改善了编写 Kotlin 代码的 "人机工程学",例如: Kotlin 接口的 SAM 转换 过去,只有 Java 编程语言中定义的功能接口(即只有一个单一抽象方法 - SAM)受益于 Kotlin 中的速记语法: executor.execute { println("This is shorthand for passing in a Runnable...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7设置SWAP分区,小内存服务器的救世主
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS8编译安装MySQL8.0.19
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2整合Thymeleaf,官方推荐html解决方案