SharedArray
SharedArray
是一个类数组对象,它在 VU(虚拟用户)之间共享底层内存。该函数只执行一次,其结果也只在内存中保存一次。当脚本请求元素时,k6 会返回该元素的*副本*。
您必须在init
上下文中构造一个 SharedArray
。它的构造函数需要一个用于 SharedArray
的名称以及一个必须返回一个数组对象的函数。
import { SharedArray } from 'k6/data';
const data = new SharedArray('some name', function () {
const dataArray = [];
// more operations
return dataArray; // must be an array
});
名称参数是必需的。VU 是完全独立的 JS VM,k6 需要某种方式来识别它需要返回的 SharedArray
。您可以拥有多个 SharedArray
,甚至可以只为给定的 VU 加载其中一部分,尽管这不太可能带来任何性能优势。
SharedArray
支持的操作包括
- 使用
length
获取元素的数量 - 使用正常语法
array[index]
按索引获取元素 - 使用
for-of
循环
在大多数情况下,您可以通过将数组数据结构包装在 SharedArray
中来减少其内存使用。一旦构造完成,SharedArray
是只读的,因此您不能使用 SharedArray 在 VU 之间通信数据。
注意
尝试在init 上下文之外实例化
SharedArray
会导致异常new SharedArray must be called in the init context
。此限制最终将被移除,但目前意味着您只能在测试的非常开始时使用
SharedArray
填充测试数据,而不能将其用作从响应接收数据的结果(例如)。
示例
import { SharedArray } from 'k6/data';
const data = new SharedArray('some name', function () {
// All heavy work (opening and processing big files for example) should be done inside here.
// This way it will happen only once and the result will be shared between all VUs, saving time and memory.
const f = JSON.parse(open('./somefile.json'));
return f; // f must be an array
});
export default function () {
const element = data[Math.floor(Math.random() * data.length)];
// do something with element
}
性能特性
在内部,当前 SharedArray
的实现将数据编组为 JSON,并且仅在请求时才对元素进行解组。
通常,此操作应该是不可察觉的(相对于您对数据所做的其他操作)。但是,对于小数据集,SharedArray
的性能可能会更差。然而,这高度依赖于用例。
为了测试这一点,我们在 v0.31.0 版本上使用 100 个 VU 运行了以下脚本。
import { check } from 'k6';
import http from 'k6/http';
import { SharedArray } from 'k6/data';
const n = parseInt(__ENV.N);
function generateArray() {
const arr = new Array(n);
for (let i = 0; i < n; i++) {
arr[i] = { something: 'something else' + i, password: '12314561' };
}
return arr;
}
let data;
if (__ENV.SHARED === 'true') {
data = new SharedArray('my data', generateArray);
} else {
data = generateArray();
}
export default function () {
const iterationData = data[Math.floor(Math.random() * data.length)];
const res = http.post('https://quickpizza.grafana.com/api/post', JSON.stringify(iterationData), {
headers: { 'Content-type': 'application/json' },
});
check(res, { 'status 200': (r) => r.status === 200 });
}
如表所示,在较低数据行数时性能差异不大:直到约 1000 数据行时,SharedArray
在内存使用方面几乎没有优势,并且 CPU 使用率的上限更高(尽管没有显著高)。
在 1 万行及以上时,内存节省也开始显著转化为 CPU 节省。
数据行数 | 共享 | 挂钟时间 | CPU % | 内存使用量 | http 请求数 |
---|---|---|---|---|---|
100 | 真 | 2:01:70 | 70-79% | 213-217MB | 92191-98837 |
100 | 假 | 2:01:80 | 74-75% | 224-232MB | 96851-98643 |
1000 | 真 | 2:01:60 | 74-79% | 209-216MB | 98251-98806 |
1000 | 假 | 2:01:90 | 75-77% | 333-339MB | 98069-98951 |
10000 | 真 | 2:01:70 | 78-79% | 213-217MB | 97953-98735 |
10000 | 假 | 2:03:00 | 80-83% | 1364-1400MB | 96816-98852 |
100000 | 真 | 2:02:20 | 78-79% | 238-275MB | 98103-98540 |
100000 | 假 | 2:14:00 | 120-124% | 8.3-9.1GB | 96003-97802 |
在 v0.30.0 中,在较低数量时 CPU 使用率的差异约为 10-15%,但在约 1 万数据行时也开始趋于平稳,并在 10 万数据行时明显更胜一筹。
CPU/内存数据来自使用 /usr/bin/time
。请参阅包含原始数据的 gist。
这些数字仅供说明:性能可能会受到从 SharedArray
检索到的元素的任何额外处理的影响,或者如果使用了输出,或者获取了多个元素等。虽然 SharedArray
会有一些 CPU 使用率,但在仅有 10 个元素的给定情况下,它可能微不足道,或者对于 10 万个元素而言,其问题比内存使用量更大。因此,如有疑问,您应该进行一些基准测试,并根据您的用例决定哪些权衡更重要。