Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >提高F#映射插入性能

提高F#映射插入性能
EN

Stack Overflow用户
提问于 2020-05-08 19:04:28
回答 1查看 217关注 0票数 5

我目前正在做一些关于F#地图和C#字典的测试。我意识到它们在实现方面有很大的不同,但它们确实为各自的语言提供了相同的用途。

我设计了一个简单的测试来检查插入时间,因为F#映射是不可变的,因此它必须为每次插入创建一个全新的映射。我想知道这到底有多成功。

测试如下:

代码语言:javascript
运行
AI代码解释
复制
 //F# 
 module Test = 
    let testMapInsert () = 
        let sw = Stopwatch()
        let rec fillMap endIdx curr map =
            if curr = endIdx then 
                map 
            else 
                fillMap endIdx (curr + 1) (map |> Map.add curr curr)
        sw.Start ()
        let q = fillMap 100000000 Map.empty
        sw.Stop ()
        printfn "%A" sw.ElapsedMilliseconds

 //C#
 class Program
    {
        static void Test(int x) {
            var d = new Dictionary<int,int>();
            for (int i = 0; i < x; i++) {
                d.Add(i,i);
            }
        }
        static void Main(string[] args) {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            Test(10000000);
            sw.Stop();
            System.Console.WriteLine(sw.ElapsedMilliseconds);
            //FSHARP.Test.testMapInsert(); f# function called in c#.

        }
    }

执行1000万次元素插入会产生以下时间(以毫秒为单位):

代码语言:javascript
运行
AI代码解释
复制
C#: 332

F#: 13605

我认为C#字典会更快一些,但这是非常不同的。

对于这种用例,有没有一种方法可以加速F#字典?或者,这只是一种方式,F#映射在这些情况下与线程安全的性能进行了权衡?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-08 21:01:35

正如评论中提到的,区别不是基于C#和F#之间的区别,而是基于不可变的基于树的映射和基于哈希表的可变字典之间的区别。

使用#time,我在F# interactive中获得了以下性能:

代码语言:javascript
运行
AI代码解释
复制
#time 
// Immutable tree-based F# map (~14 sec)
let mutable map = Map.empty
for i in 0 .. 10000000 do
  map <- Map.add i i map

// Mutable hashtable-based .NET dictionary (~0.3 sec)
let dict = System.Collections.Generic.Dictionary<_, _>()
for i in 0 .. 10000000 do
  dict.Add(i, i)

有趣的问题是-你能让不可变的F#映射变得更快吗?原则上,如果您知道正在使用已排序的数组,则可以更快地构建映射。F#映射没有任何允许您执行此操作的操作,但可以添加它。

当我定义自己的映射类型,它与F#映射共享内部结构时:

代码语言:javascript
运行
AI代码解释
复制
type MapTree<'Key, 'Value when 'Key : comparison > = 
  | MapEmpty 
  | MapOne of 'Key * 'Value
  | MapNode of 'Key * 'Value * MapTree<'Key, 'Value> *  MapTree<'Key, 'Value> * int

然后我可以定义ofSortedArray操作:

代码语言:javascript
运行
AI代码解释
复制
let height = function
  | MapEmpty -> 0
  | MapOne _ -> 1
  | MapNode(_, _, _, _, h) -> h

let rec ofSortedArray (data:_[]) i j = 
  if i = j then MapOne(data.[i])
  elif i > j then MapEmpty 
  else 
    let m = i + (j - i) / 2
    let l, r = ofSortedArray data i (m - 1), ofSortedArray data (m + 1) j
    let k, v = data.[m]
    MapNode(k, v, l, r, 1 + (max (height l) (height r)))

这仍然比不上可变哈希表的效率,但我得到了以下结论:

代码语言:javascript
运行
AI代码解释
复制
// Immutable tree-based F# map, using sorted array 
let arr = [| for i in 0 .. 10000000 -> i, i |] // ~1 sec
let map = ofSortedArray arr 0 10000000         // ~3 sec

如果你真的想使用它,你需要你自己的F#地图版本--或者你可以向F#核心库发送一个拉取请求,添加对这类东西的支持!

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61686286

复制
相关文章
11.22 访问日志不记录静态文件
访问日志不记录指定类型的文件目录概要 网站大多元素为静态文件,如图片、css、js等,这些元素可以不用记录 把虚拟主机配置文件改成如下: <VirtualHost *:80> DocumentRoot "/data/wwwroot/www.123.com" ServerName www.123.com ServerAlias 123.com SetEnvIf Request_URI ".*\.gif$" img SetEnvIf Request_URI ".*\.j
运维小白
2018/02/06
1.1K0
11.22 访问日志不记录静态文件
Apache访问日志+不记录静态文件
Apache访问日志 : 访问日志:顾名思义就是当有人访问咱们的站点,就会被记录些信息!其实这个还是蛮重要,尤其是站点受到攻击,直接命令的日志可以让我们迅速找到攻击者IP的规律! 根据咱们之前的配置,访问日志如下: <VirtualHost *:80> DocumentRoot "/data/wwwroot/test3.com" ServerName www.test3.com ServerAlias www.haha.com #<Directory /data/wwwroot
老七Linux
2018/05/09
1.8K0
docker exec和docker attach
Docker是一种流行的容器化技术,它可以轻松地在一个容器中封装应用程序和它们的依赖项,以便在不同的环境中运行。Docker提供了许多命令行工具来管理Docker容器,其中包括docker exec和docker attach命令,这些命令用于与正在运行的Docker容器交互。
玖叁叁
2023/04/26
7370
docker exec 与 docker attach 区别
不论是开发者是运维人员,都经常有需要进入容器的诉求。  目前看,主要的方法不外乎以下几种:  1. 使用ssh登陆进容器  2. 使用nsenter、nsinit等第三方工具  3. 使用Docker本身提供的工具
拓荒者
2019/03/11
3.5K0
Nginx访问日志,Nginx日志切割,静态文件不记录日志和过期时间
其中的combined_realip是日志的名称,这个名称可以自定义,但是你定义了什么名称,后面你操作日志的时候也要使用这个名称。就像你给一个人起名叫李四,你就得用李四这个名字去叫他干活。剩下的字符串含义在上面的图片已经介绍了,就不赘述了。
端碗吹水
2020/09/23
5.4K0
Nginx访问日志,Nginx日志切割,静态文件不记录日志和过期时间
docker attach 和 exec 的区别
一个好习惯是使用 run 启动容器,用 exec 运行容器,用 Ctrl+P+Q 退出容器。
看、未来
2022/05/17
1.5K0
Nginx访问日志,Nginx日志切割,静态文件不记录日志和过期时间
 Nginx访问日志: vim /usr/local/nginx/conf/nginx.conf //搜索log_format    = 配置文件里面可以查找到日志格式 定义访问日志 定义日志是需要在
叶瑾
2018/06/14
1.2K0
12.12 静态文件不记录日志和过期时间
静态文件不记录日志和过期时间目录概要 配置如下 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 7d; access_log off; } location ~ .*\.(js|css)$ { expires 12h; access_log off; } 静态文件不记录日志和过期时间 在配置文件中添加 location
运维小白
2018/02/06
1.1K0
Nginx日志过滤 使用ngx_log_if不记录特定日志
ngx_log_if是Nginx的一个第三方模块。它在Github上的描述是这样介绍的:ngx_log_if是一个独立的模块,允许您控制不要写的访问日志,类似于Apache的"CustomLog env = XXX"
星哥玩云
2022/07/01
1.3K0
访问日志不记录静态文件,访问日志切割,静态元素过期时间
使用浏览器打开一个网站时,我们可以按F12打开控制台,在Network中可以看到许多在访问时下载的静态文件,这些对静态文件的请求都会记录到访问日志里面的:
端碗吹水
2020/09/23
1.3K0
访问日志不记录静态文件,访问日志切割,静态元素过期时间
Nginx访问日志+日志切割+静态文件不记录和过期时间设置
一、 Nginx访问日志 1.1 打开配置文件: vim /usr/local/nginx/conf/vhost/../nginx.conf 找到如下,是定义日志格式: log_format combined_realip '$remote_addr $http_x_forwarded_for [$time_local]' ' $host "$request_uri" $status' ' "$http_referer" "$http_user_agent"'; combined_real
老七Linux
2018/05/09
1.1K0
访问日志不记录静态文件,访问日志切割,静态元素过期时间
访问日志不记录静态文件: 配置文件:(红色img后缀的拷贝到服务器里面) <VirtualHost *:80>     DocumentRoot "/data/wwwroot/www.123.com
叶瑾
2018/06/14
9810
docker exec 进入容器报错 is not running
Error response from daemon: Container 1d7dd0a4a999bb6346c58b0eed286573e8139cca1d2854c543f713c2fea220c7 is not running 分析: Docker容器后台运行,就必须有一个前台进程。主线程结束,容器会退出。 所以就加上了 dit 参数,再次运行即可。 docker ps -a # 查看正在运行的镜像 docker rm -
eisc
2021/05/10
10.2K0
记录日志
日志级别:debug<info<warn<error application.yml配置日志 logging: file: target/app.log level: ROOT: WARN cn.devmar: TRACE import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class SampleClass{ private static
华创信息技术
2019/11/08
7970
日志记录
访问应用服务器的请求都需要拥有一定权限,如果说每访问一个服务都需要验证一次权限,这个对效率是很大的影响。可以把权限认证放到 API 网关来进行。目前比较常见的做法是,用户通过登录服务获取 Token,把它存放到客户端,在每次请求的时候把这个 Token 放入请求头,一起发送给服务器。API 网关要做的事情就是解析这个 Token,知道访问者是谁(鉴定),他能做什么/访问什么(权限)。说白了就是看访问者能够访问哪些 URL,这里根据权限/角色定义一个访问列表。如果要实现多个系统的 OSS(Single Sign On 单点登录),API 网关需要和 CAS(Central Authentication Service 中心鉴权服务)做连接,来确定请求者的身份和权限。
用户1880875
2021/09/07
1.2K0
docker exec执行多个命令详解 原
docker exec命令能够在运行着的容器中执行命令。docker exec命令的使用格式:
拓荒者
2019/03/11
6.5K0
docker 创建容器,端口映射(docker exec 进入容器)
今天用docker的swarm搭建了一个集群,在启动主节点的swarm的时候出错了,报的错误是:
全栈程序员站长
2022/07/31
1.1K0
MongoDB日志记录
为了在发生故障时提供持久性,MongoDB使用预写日志记录到磁盘journal文件中。
MongoDB中文社区
2020/11/11
2.8K0
MongoDB日志记录
Python记录日志的方法
日志不管对于开发或者运维都是一项非常重要的东西,它可以用来排错,解决故障,统计分析等。
py3study
2020/01/07
2K0
mysql日志记录
log-bin = /path/mysql-bin #其记录日志文件名为mysql-bin.index,mysql-bin.000001(注:重启或者单个文件超出限制会+1)
93年的老男孩
2019/12/18
4.8K0

相似问题

调整R中levelplot函数中轴标签的字体大小

30

海运中轴标签的字体大小

11

热图调整

11

在热图中调整热图大小和调整热图。2

23

如何调整热图的轴?

124
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档