【问题标题】:How much memory does a variable take?一个变量需要多少内存?
【发布时间】:2017-03-27 08:44:45
【问题描述】:

变量"a=b" 包含1 个字符'a' 作为名称,1 个字符'b' 作为值。

共 2 个字节。

How many characters can you store with one byte ?

变量需要一个指针。 8 个字节。

How many bytes do pointers take up ?

共 10 个字节。

存储在内存中的变量"a=b" 是否需要大约 10 个字节? 10 个相同大小的变量会占用大约 100 个字节吗?

所以 1000 个 1000 字节的变量几乎是 1MB 的内存?

我有一个只包含变量的文件 data.sh。 我需要检索该文件中一个变量的值。 我通过使用一个函数来做到这一点。 (由“'function-name' 'datafile-name' 'variable-name'”调用)

#!/usr/pkg/bin/ksh93

readvar () {
    while read -r line
    do
            typeset "${line}"
    done < "${1}"

    nameref indirect="${2}"
    echo "${indirect}"
 }

readvar datafile variable

函数逐行读取文件data.sh。 虽然这样做是排版每一行。 做完之后, 它从函数调用中的变量名进行名称引用, 到文件 data.sh 的变量之一。 最后打印该变量的值。

函数完成后不再占用内存。 但只要函数在运行它就可以。

这意味着文件 data.sh 中的所有变量都存储在内存中。

对吗?

实际上,我有一个文件,其中 ip-addresses 作为变量名,昵称作为值。所以我想这不会是内存上的问题。但是,如果我也将它用于访问者的帖子,变量值将会更大。但是有可能让这个函数每次只在内存中存储 10 个变量。 但是我想知道我计算变量的内存使用量的方法是否有意义。

编辑:

这可能是避免将整个文件加载到内存中的解决方案。

#!/bin/ksh

readvar () {
input=$(print "${2}" | sed 's/\[/\\[/g' | sed 's/\]/\\]/g')
line=$(grep "${input}" "${1}")
typeset ${line}
nameref indirect="${2}"
print "${indirect}"
}

readvar ./test.txt input[0]

用输入test.txt

input[0]=192.0.0.1
input[1]=192.0.0.2
input[2]=192.0.0.2

还有输出

192.0.0.1

编辑:

当然!!! 在原帖中 Bash read array from an external file 它说:

# you could do some validation here

所以:

    while read -r line
do
    # you could do some validation here
    declare "$line"
done < "$1"

行将在条件下被声明(或在 ksh 中排版)。

【问题讨论】:

    标签: bash variables memory ksh


    【解决方案1】:

    您真正关心的似乎不是“这需要多少内存?”但是“我怎样才能避免为此占用大量内存?”。我先回答这个问题。有关原始问题的一堆想法,请参阅我的答案的结尾。

    为了避免耗尽内存,我建议使用 grep 来获取您感兴趣的一行并忽略所有其他行:

    line=$(grep "^$2=" "$1")
    

    然后你可以从这一行中提取你需要的信息:

    result=$(echo "$line" | cut -d= -f 2)
    

    现在变量result 包含在文件$1 中分配给$2 的值。由于您不需要存储多个这样的结果值,因此您肯定没有内存问题。

    现在,回到原来的问题:

    要找出 shell 为每个变量使用了多少内存是很棘手的。您需要查看 shell 的源代码以确保实现。它可能因外壳而异(您似乎使用的是ksh,在这方面可能与bash不同)。它也可能因版本而异。

    获得想法的一种方法是观察 shell 进程的内存使用情况,同时让 shell 设置大量变量:

    bash -c 'a="$(head -c 1000 /dev/zero | tr "\0" x)"; for ((i=0; i<1000; i++)); do eval a${i}="$a"; done; grep ^VmPeak /proc/$$/status'
    bash -c 'a="$(head -c 1000 /dev/zero | tr "\0" x)"; for ((i=0; i<10000; i++)); do eval a${i}="$a"; done; grep ^VmPeak /proc/$$/status'
    bash -c 'a="$(head -c 1000 /dev/zero | tr "\0" x)"; for ((i=0; i<100000; i++)); do eval a${i}="$a"; done; grep ^VmPeak /proc/$$/status'
    bash -c 'a="$(head -c 1000 /dev/zero | tr "\0" x)"; for ((i=0; i<200000; i++)); do eval a${i}="$a"; done; grep ^VmPeak /proc/$$/status'
    

    这会打印 bash 使用的内存峰值量,它设置了 1000、10000、100000 和 200000 个变量,其值为 1000 x 个字符。在我的机器上(使用bash 4.2.25(1)-release),输出如下:

    VmPeak:    19308 kB
    VmPeak:    30220 kB
    VmPeak:   138888 kB
    VmPeak:   259688 kB
    

    这表明所使用的内存或多或少地以线性方式增长(加上 ~17000k 的固定偏移量),并且每个新变量占用 ~1.2kB 的额外内存。

    但正如我所说,其他 shell 的结果可能会有所不同。

    【讨论】:

    • 好的,谢谢,我认为以下可能是您的解决方案:#!/bin/ksh readvar () { input=$(print "${2}" | sed 's/\[/\\[/g' | sed 's/\]/\\]/g') line=$(grep "${input}" "${1}") typeset ${line} nameref indirect="${2}" print "${indirect}" } readvar ./test.txt input[0] with input datafile test.txt input[0]=192.0.0.1 output: 192.0.0.1 :)
    猜你喜欢
    • 2014-05-11
    • 2015-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-13
    • 2014-03-02
    相关资源
    最近更新 更多