Nim 概念 Concept 对性能的影响
Nim 概念 Concept 对性能的影响
继上一篇文章《C# 泛型编译特性对性能的影响》后,我又研究了 Nim 语言相关的设计,由于 Nim 语言与 C# 语言有些差异,比如Nim 没有接口,也没有直接的 class 关键字,所以某些实现是变通的办法。
概念 Concept
在Nim中没有 Interface 的概念,虽然有多次提案,但似乎语言设计者一直拒绝这一设计,他们提供了 Concept 这一方案。他与C#的interface的相似点包括:
concept
和interface
都用于定义抽象类型和行为规范,允许在没有提供具体实现的情况下定义方法签名。- 两者都支持多态,允许不同的类型实现相同的接口或概念,并以相同的方式被操作或使用。
但也有不同之处,比如:
- 在Nim的concept中,方法声明不需要关键字(如fn),而是直接指定方法的签名。在C#中,interface中的方法声明需要使用method或property等关键字。
- concept在Nim中比interface更加灵活。concept可以用于限制多个类型的行为,但不一定需要显式声明实现。它允许在函数中使用未显式声明为实现concept的类型。interface在C#中更加严格,要求类型明确地声明并实现接口中的所有成员。
- 在C#中,interface可以在字段、方法参数、方法返回值等多个地方使用,允许动态地访问实现。在Nim中,concept主要用于参数约束,只允许在函数或过程中使用,
无法在字段或返回值中声明
。
下面是这个案例中声明 Concept 的例子:
type
IValueGetter = concept s
s.getValue(int32) is int64
有了 concept,我们就可以在泛型中约束 泛型参数的行为,例如下面的泛型类型 MyTestClass[T] ,其类型声明中没有约束 T,但在相关的方法中,允许约束。
type
MyTestClass[T] = object
valueGetter: T
proc run[T: IValueGetter](this: MyTestClass[T]): int64 =
var r = 0i64
let n = high(int32) - rand(100).int32
for i in 0 ..< n:
r += this.valueGetter.getValue(i)
return r
Nim 中 Struct 和 Class
在Nim语言中, struct 是使用 object 关键字,同样的,如果在object 的前面加上 ref 关键字,就变成了 struct 引用,自然就相当于 class 了,下面是示例代码:
type
StructValueGetter = object
StructValueGetter2 = object
someField: int
ValueGetter = ref object of RootObj
ClassValueGetter1 = ref object of ValueGetter
ClassValueGetter2 = ref object of ValueGetter
在这个例子中,我们看见如何声明 Struct,以及声明字段, 同时也使用 ref object 声明了 class ,他使用 of 关键字表示继承关系。
你也许注意到,RootObj ,他是nim语言提供的默认基类,你可以理解为c#和java 的object 基类,但nim语言具有很强的灵活性,可以不继承任何基类,或使用其他的基类。
Nim中定义方法或动态方法
一般情况下,Nim建议使用 proc 和 func 作为方法前的关键字,因为这样的话方法就是静态编译的,具有最佳的性能,func 其实是 proc 的特例,即表示无副作用的 proc,比如你仅仅是读取对象的数据,不会破坏结构,这就是无副作用。
# 实现 IValueGetter 的 concept
func getValue(this: StructValueGetter, index: int32): int64 =
result = index.int64 + 3i64
func getValue(this: StructValueGetter2, index: int32): int64 =
result = index.int64 + 5i64
func getValue(this: ClassValueGetter1, index: int32): int64 =
result = index.int64 + 5i64
func getValue(this: ClassValueGetter2, index: int32): int64 =
result = index.int64 + 7i64
为实现诸如 c# 的虚方法功能(即动态调用),nim 设计了 method 关键字。
method getValueCore(this: ValueGetter, index: int32): int64 {.base.} =
quit "to overrdie"
method getValueCore(this: ClassValueGetter1, index: int32): int64 =
return getValue(this,index)
method getValueCore(this: ClassValueGetter2, index: int32): int64 =
return getValue(this,index)
# 为 ValueGetter 实现契约,相当于使用契约调用的是虚方法。
proc getValue(this: ValueGetter, index: int32): int64 =
return getValueCore(this, index)
测试
下面我们将使用 stuct 和 class 两种形式,确定 concept 和 泛型结合,对性能的影响。同时我们也观察动态方法调用,即虚方法的调用对性能的影响。
import std/[times],std/random
type
IValueGetter = concept s
s.getValue(int32) is int64
MyTestClass[T] = object
valueGetter: T
proc run[T: IValueGetter](this: MyTestClass[T]): int64 =
var r = 0i64
let n = high(int32) - rand(100).int32
for i in 0 ..< n:
r += this.valueGetter.getValue(i)
return r
type
StructValueGetter = object
StructValueGetter2 = object
someField: int
ValueGetter = ref object of RootObj
ClassValueGetter1 = ref object of ValueGetter
ClassValueGetter2 = ref object of ValueGetter
# 实现 IValueGetter 的 concept
func getValue(this: StructValueGetter, index: int32): int64 =
result = index.int64 + 3i64
func getValue(this: StructValueGetter2, index: int32): int64 =
result = index.int64 + 5i64
func getValue(this: ClassValueGetter1, index: int32): int64 =
result = index.int64 + 5i64
func getValue(this: ClassValueGetter2, index: int32): int64 =
result = index.int64 + 7i64
# 为接口 ValueGetter 实现契约,相当于使用契约调用的是委托。
method getValueCore(this: ValueGetter, index: int32): int64 {.base.} =
quit "to overrdie"
method getValueCore(this: ClassValueGetter1, index: int32): int64 =
return getValue(this,index)
method getValueCore(this: ClassValueGetter2, index: int32): int64 =
return getValue(this,index)
proc getValue(this: ValueGetter, index: int32): int64 =
return getValueCore(this, index)
proc measureTime(caption: string, procToMeasure: proc(): int64) =
var startTime = cpuTime()
let r = procToMeasure()
var endTime = cpuTime()
echo caption, " time = ", endTime - startTime, " result = ", r
# 运行测试
proc main() =
randomize()
let t1 = MyTestClass[StructValueGetter](valueGetter : StructValueGetter())
measureTime("StructValueGetter ", proc ():int64 = t1.run() )
let t2 = MyTestClass[ClassValueGetter1](valueGetter : new(ClassValueGetter1))
measureTime("ClassValueGetter1 ", proc ():int64 = t2.run() )
let t3 = MyTestClass[ClassValueGetter2](valueGetter : new(ClassValueGetter2))
measureTime("ClassValueGetter2 ", proc ():int64 = t3.run())
let t4 = MyTestClass[ValueGetter](valueGetter : new(ClassValueGetter1))
measureTime("IValueGetter-1 ", proc ():int64 = t4.run())
let t5 = MyTestClass[ClassValueGetter1](valueGetter : new(ClassValueGetter1))
measureTime("ClassValueGetter1 ", proc ():int64 = t5.run())
let t6 = MyTestClass[StructValueGetter2](valueGetter : StructValueGetter2())
measureTime("StructValueGetter2", proc ():int64 = t6.run())
when isMainModule:
main()
编译的命令行如下:
nim c -d:release -x --checks:off -r ".\demo1.nim"
请自己编译时将 demo1.nim 替换成自己的文件名,同时你也可能注意到 我关闭了检查,我发现如果不关闭的话,性能会慢很多。在我的笔记本电脑的参考结果如下:
StructValueGetter time = 0.429 result = 2305842997402533900
ClassValueGetter1 time = 0.421 result = 2305842825603845693
ClassValueGetter2 time = 0.421 result = 2305842971632730244
IValueGetter-1 time = 4.74 result = 2305842913650672596
ClassValueGetter1 time = 0.4210000000000003 result = 2305842870701000726
StructValueGetter2 time = 0.4190000000000005 result = 2305842920093123411
我们注意到:
- 在nim语言实现中 , struct 和 class 在泛型和 concept 的环境下,性能几乎没有影响;
- 与c#不同,nim仍然为每种 class 编译不同的程序,所以性能不会变化;
- 尽量避免使用虚方法,性能的损失很大;
Nim 概念 Concept 对性能的影响的更多相关文章
- [转帖]【译】RAID的概念和RAID对于SQL性能的影响
[译]RAID的概念和RAID对于SQL性能的影响 https://www.cnblogs.com/VicLiu/p/11479427.html 简介 我们都听说过RAID,也经常作为SQL DBA. ...
- SQL Server中多表连接时驱动顺序对性能的影响
本文出处:http://www.cnblogs.com/wy123/p/7106861.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...
- 极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间
极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间 笔记体会: 方案一,事务相 ...
- 高性能JavaScript-JS脚本加载与执行对性能的影响
在web产品优化准则中,很重要的一条是针对js脚本的加载和执行方式的优化.本篇文章简单描述一下其中的优化准则. 1. 脚本加载优化 1.1 脚本位置对性能的影响 优化页面加载性能的原则之一是将scri ...
- JAVA 异常对于性能的影响
陶炳哲 - MAY 12, 2015 在对OneAPM的客户做技术支持时,我们常常会看到很多客户根本没意识到的异常.在消除了这些异常之后,代码运行速度与以前相比大幅提升.这让我们产生一种猜测,就是在代 ...
- HTTP/2 对 Web 性能的影响(下)
一.前言 我们在 HTTP/2 对 Web 性能的影响(上)已经和大家分享了一些关于 Http2 的二项制帧.多用复路以及 APM 工具等,本文作为姊妹篇,主要从 http2 对 Web 性能的影响. ...
- smarty对网页性能的影响--开启opcache
在上一篇<smarty对网页性能的影响>中,默认没有开启opcache,于是我安装了一下zend opcache扩展,重新实验了一下,结果如下: 有smarty 用apache的ab命令进 ...
- C++ 性能剖析 (四):Inheritance 对性能的影响
(这个editor今天有毛病,把我的format全搞乱了,抱歉!) Inheritance 是OOP 的一个重要特征.虽然业界有许多同行不喜欢inheritance,但是正确地使用inheritanc ...
- css的!important规则对性能有影响吗
最近在做项目中发现很多CSS代码里面都使用!important去覆盖原有高优先级的样式.按照常理来说,越是灵活的东西,需要做的工作就会更多.所以想当然的认为像!important这样灵活.方便的规则如 ...
- List是线程安全的吗?如果不是该怎么办呢?安全的List对性能的影响有多大呢?
测试条件: 开启2个并行执行任务,往同一个list对象写入值 测试代码: ; static List<int> list = new List<int>(); static v ...
随机推荐
- Idea报错 【cannot access com.xxx】的【解决办法】
正常操作代码,一个类突然标红,提示 cannot access com.xxx . 执行下面操作,执行完后项目变为正常 但是如果是你代码存在异常,可不是清缓存就能解决了,就要靠自己了哈哈 第一步Fil ...
- SqlServer性能检测之Sql语句排查
很多时候,我们在用SQL语句查询数据时,难免会漏掉对SQL语句性能的考虑,所以有时就会造成SqlServer服务占用过高的问题,为了大致排查是哪些SQL语句造成的问题,我们可以通过如下SQL查询出最近 ...
- HTML标签-form表单
HTML标签-form表单 在Web开发中,HTML表单(form)是不可或缺的一部分,它承担着用户与Web服务器之间交互的重任.今天,我们就来详细探讨一下HTML中的form表单标签. 一.form ...
- PHP简介与开发环境搭建
PHP简介与开发环境搭建 一.PHP简介 PHP,全称PHP: Hypertext Preprocessor(超文本预处理器),是一种广泛使用的开源服务器端脚本语言,尤其适合Web开发.PHP由Ras ...
- AI如何改变数据驱动决策的方式
导语 在这个信息爆炸的时代,数据成为了企业和组织最为宝贵的资源.然而,单纯的数据堆积并没有太大价值,只有通过分析和挖掘,才能真正发挥数据的潜力.随着AI技术的飞速发展,我们正见证着数据驱动决策方式发生 ...
- 什么是A型或者B型剩余电流保护器?
我国的剩余电流保护装置(RCD)指导性标准GB/Z 6829-2008(IEC/TR 60755:2008,MOD)<剩余电流动作保护器的一般要求> 从产品的基本结构.剩余电流类型.脱扣方 ...
- Vue 前端页面利用MediaRecorder实现音频录制
Don't Talk, code is here: 重点是startRecord 方法 <template> <div> <el-tooltip class=" ...
- flutter - [02] 基本语法
题记部分 一.注释 ///这是一个注释 //这也是个注释 /* 这还是个注释 */ void main(List<String> args) { print ('你好 dart'); } ...
- 绝了!k3s (k8s) 安装 ollama 运行 deepseek 全流程揭秘,yaml全公开
k3s (k8s) 环境搭建与 ollama 相关 yaml 文件部署 在容器编排的世界中,k3s (k8s) 无疑是备受瞩目的存在.此次聚焦在 k3s (k8s) 环境下安装 ollama,并实现运 ...
- FastAPI Cookie 和 Header 参数完全指南:从基础到高级实战 🚀
title: FastAPI Cookie 和 Header 参数完全指南:从基础到高级实战 date: 2025/3/9 updated: 2025/3/9 author: cmdragon exc ...