JGI*_*nal 5 arrays size tcl limit
我正在研究工程应用程序,接口是用TCL TK编写的.
一切都很顺利,直到我需要使用(非常)大阵列.370.000.000个元素,每个元素长度为2到10个字符(线性增长).
我的问题是,¿TCL阵列的大小限制在哪里? 我一直在阅读和调查,我发现只有"2GB"的字符串数据,但我不知道它是否可靠,因为它没有解释原因.
我做了一个实验:
set lista [list ]
catch {
for {set i 0} {$i < 370000000} {incr i} {
lappend lista $i
}
}
puts $i
Run Code Online (Sandbox Code Playgroud)
在32位Windows 7上或多或少地返回$ i = 50.000.000
Don*_*ows 10
解释起来有点复杂.2GB限制来自低级别内存分配器,它具有大小限制,因为它使用带符号的 32位整数来描述要分配的内存量.在32位系统上这很好,但它是一个开放的错误(可能会分配给我),它仍然适用于64位系统; C API中的正确类型实际上ssize_t
(是的,仍然是签名的;负值用于信令)但是修复它完全破坏了很多API,所以它需要进行重大版本更改才能进行整理.
但是列表的最大大小是另外的.这基本上与一些事物的组合有关.首先,可以分配的内存结构的最大大小(2GB限制),这意味着您可能无法在64位系统的列表中可靠地获得超过256M的元素.然后是分配的项目总数,尽管这在实践中不是问题,特别是如果您实际上多次将项目放入列表中(因为它们共享引用).最后,列表的字符串表示的大小:如果你生成了很多,那么你无论如何都会做错,但如果你正在创建它,那将是你的例子中的真正限制因素(因为那样做)早点达到2GB的限制).
达到内存限制的实际点可能会更低,具体取决于系统何时开始拒绝分配内存的请求.这完全取决于操作系统,它倾向于根据系统上的其他内容做出决定,所以在那里给出任何一般规则是非常困难的.我的(64位,OSX)系统需要很长时间,但成功运行了示例代码:
$ tclsh8.6
% eval {
set lista [list ]
catch {
for {set i 0} {$i < 370000000} {incr i} {
lappend lista $i
}
}
puts $i
}
370000000
% llength $lista
370000000
% unset lista
% exit
Run Code Online (Sandbox Code Playgroud)
这llength
是唯一真正快速的操作(因为它可以从列表元数据中拉出长度).在unset
花了很长时间.这exit
很快,但花了几秒钟.