Static variable for VUs in K6 - k6

Is there a way to use a static variable shared across VUs in K6.
Say
// init code
let x = 0 // i want this to be static
// options
export let options = {
vus : 10,
iterations : 10
};
// VU code
export default function() {
x++;
console.log(x);
}
When I run this piece of code, the output should be incremental (1 to 10) and not 1 printed 10 times (1 for each VU).

In k6, each VU is a separate independent JS runtime, so you essentially have 10 copies of x. There is no way around that with stock k6 for now, you have to use some external service as an incrementing counter via HTTP or something like that. Alternatively, if you'll run k6 locally and only on a single instance, you can use this xk6 extension (more info): https://github.com/MStoykov/xk6-counter. It was a PoC originally developed for https://community.k6.io/t/unique-test-data-per-vu-without-reserving-data-upfront/1136/3 , but can be easily extended.

Related

Interrupt ZStream mapMPar processing

I have the following code which, because of Excel max row limitations, is restricted to ~1million rows:
ZStream.unwrap(generateStreamData).mapMPar(32) {m =>
streamDataToCsvExcel
}
All fairly straightforward and it works perfectly. I keep track of the number of rows streamed, and then stop writing data. However I want to interrupt all the child fibers spawned in mapMPar, something like this:
ZStream.unwrap(generateStreamData).interruptWhen(effect.true).mapMPar(32) {m =>
streamDataToCsvExcel
}
Unfortunately the process is interrupted immediately here. I'm probably missing something obvious...
Editing the post as it needs some clarity.
My stream of data is generated by an expensive process in which data is pulled from a remote server, (this data is itself calculated by an expensive process) with n Fibers.
I then process the streams and then stream them out to the client.
Once the processed row count has reached ~1 million, I then need to stop pulling data from the remote server (i.e. interrupt all the Fibers) and end the process.
Here's what I can come up with after your clarification. The ZIO 1.x version is a bit uglier because of the lack of .dropRight
Basically we can use takeUntilM to count the size of elements we've gotten to stop once we get to the maximum size (and then use .dropRight or the additional filter to discard the last element that would take it over the limit)
This ensures that both
You only run streamDataToCsvExcel until the last possible message before hitting the size limit
Because streams are lazy expensiveQuery only gets run for as many messages as you can fit within the limit (or N+1 if the last value is discarded because it would go over the limit)
import zio._
import zio.stream._
object Main extends zio.App {
override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = {
val expensiveQuery = ZIO.succeed(Chunk(1, 2))
val generateStreamData = ZIO.succeed(ZStream.repeatEffect(expensiveQuery))
def streamDataToCsvExcel = ZIO.unit
def count(ref: Ref[Int], size: Int): UIO[Boolean] =
ref.updateAndGet(_ + size).map(_ > 10)
for {
counter <- Ref.make(0)
_ <- ZStream
.unwrap(generateStreamData)
.takeUntilM(next => count(counter, next.size)) // Count size of messages and stop when it's reached
.filterM(_ => counter.get.map(_ <= 10)) // Filter last message from `takeUntilM`. Ideally should be .dropRight(1) with ZIO 2
.mapMPar(32)(_ => streamDataToCsvExcel)
.runDrain
} yield ExitCode.success
}
}
If relying on the laziness of streams doesn't work for your use case you can trigger an interrupt of some sort from the takeUntilM condition.
For example you could update the count function to
def count(ref: Ref[Int], size: Int): UIO[Boolean] =
ref.updateAndGet(_ + size).map(_ > 10)
.tapSome { case true => someFiber.interrupt }

DoGet with multiple parameters not being recognized

I'm currently trying to connect a Lua Script with a GS WebApp. The connection is working but due to my lack of knowledge in GScripting I'm not sure why it isn't saving my data correctly.
In the Lua side I'm just passing in a hard-code a random name and simple numerical userid.
local HttpService = game:GetService("HttpService")
local scriptID = scriptlink
local WebApp
local function updateSpreadSheet ()
local playerData = (scriptID .. "?userid=123&name:Jhon Smith")
WebApp = HttpService:GetAsync(playerData)
end
do
updateSpreadSheet()
end
On the Google Script side i'm only saving the data on the last row and then add the value of the userid and the name.
function doGet(e) {
console.log(e)
// console.log(f)
callName(e.parameter.userid,e.parameter.name);
}
function callName(userid,name) {
// Get the last Row and add the name provided
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(sheet.getLastRow() + 1,1).setValues([userid],[name]);
}
However, the only data the script is saving is the name, bypassing the the userid for reasons I have yet to discover.
setValues() requires a 2D array and range dimensions should correspond to that array. The script is only getting 1 x 1 range and setValues argument is not a 2D array. Fix the syntax or use appendRow
sheet.getRange(sheet.getLastRow() + 1,1,1,2).setValues([[userid,name]]);
//or
sheet.appendRow([userid,name])
References:
appendRow

Overriding a conditional variable in UnrealScript with a child class in Deus Ex?

I'm actually using the original Deus Ex game from the year 2000. I created a child class of "DeusEx.Flare" and called it "rflare" and saved it to my own package. I have successfully compiled it, and it works, but not the way I intended. I want to override the function "LifeSpan = 30" and give it "LifeSpan = 120". The problem is the documentation. There practically is none. And the documentation I can find generally is too confusing and does not give good enough examples for what I'm tryng to do. here is the code. I know I'm supposed to be using the "super" expression but I have exhausted all the ways I know how to use it. I simply cannot get it to work. However, I can get it to work if I dont' mind throwing both the normal flare (which goes out in 30 seconds) and my own flare, which only drops to the ground without a sound but will in fact last 120 seconds. So my code would end up throwing 2 flares. 1 normal flare that goes out in 30 sec. and the other that does last 120 but does not get thrown like the normal flare does.
here is the code from DeusEx.Flare script that I'm trying to change.
function LightFlare()
{
local Vector X, Y, Z, dropVect;
local Pawn P;
if (gen == None)
{
LifeSpan = 30;
}
}
My first attempt was to copy this and change it in my own package. It worked but again, it shot 2 flares, 1 normal and 1 that sorta worked. I want to do only one. So here is my attempt at correcting the code.
function LightFlare()
{
Super(Flare).LightFlare();
if (gen == None)
{
LifeSpan = 120;
}
}
All this does is spawn the normal flare, with no difference in the time it lasts. Can someone please help me?
I would suggest copying the LightFlare function in it's entirety from the parent class and not calling super. You don't want the original function to run, as that will mess with the lifetime variable.
For instance:
class RFlare extends Flare;
function LightFlare()
{
local Vector X, Y, Z, dropVect;
local Pawn P;
// Original function here, change lifetime when specified.
if (gen == None)
{
LifeSpan = 120;
}
}
defaultproperties
{
}

How do I limit the number of concurrent processes spawned by Proc::Async in Perl 6?

I want to process a list of files in a subtask in my script and I'm using Proc::Async to spawn the subprocesses doing the work. The downside is that if I have a large list of files to process, it will spawn many subprocesses. I want to know how to limit the number of concurrent subprocesses that Proc::Async spawns?
You can explicitly limit the number of Proc::Async processes using this react block technique which Jonathan Worthington demonstrated in his concurrency/parallelism/asynchrony talk at the 2019 German Perl Workshop (see slide 39, for example). I'm using the Linux command echo N as my "external process" in the code below.
#!/bin/env perl6
my #items = <foo bar baz>;
for #items -> $item {
start { say "Planning on processing $item" }
}
# Run 2 processes at a time
my $degree = 2;
react {
# Start $degree processes at first
run-one-process for 1..$degree;
# Run one, run-one again when it ends, thus maintaining $degree active processes at a time
sub run-one-process {
my $item = #items.shift // return;
my $proc = Proc::Async.new('echo', "processing $item");
my #output;
# Capture output
whenever $proc.stdout.lines { push #output, $_; }
# Print all the output, then start the next process
whenever $proc.start {
#output.join("\n").say;
run-one-process
}
}
}
Old Answer:
Based on Jonathan Worthington's talk Parallelism, Concurrency, and Asynchrony in Perl 6 (video, slides), this sounds most like parallelism (i.e. choosing to do multiple things at once; see slide 18). Asynchrony is reacting to things in the future, the timing of which we cannot control; see slides 39 and 40. As #raiph pointed out in his comment you can have one, the other, or both.
If you care about the order of results, then use hyper, but if the order isn't important, then use race.
In this example, adapted from Jonathan Worthington's slides, you build a pipeline of steps in which data is processed in batches of 32 filenames using 4 workers:
sub MAIN($data-dir) {
my $filenames = dir($data-dir).race(batch => 32, degree => 4);
my $data = $filenames.map(&slurp);
my $parsed = $data.map(&parse-climate-data);
my $european = $parsed.grep(*.continent eq 'Europe');
my $max = $european.max(by => *.average-temp);
say "$max.place() is the hottest!";
}

How to access #1 inside conditional inside array->forEach

I trying to learn captures in Lasso 9, but I am struggling to figure out how to access the #1 local variable from within a conditional that's inside an array->forEach capture. Maybe my approach is all wrong. Is there a reference to the parent capture that I need to use? Following is the working code:
define paramstovars() => {
local(p = web_request->params)
#p->foreach => {
local(i = #1)
if(#i->type == 'pair') => {
var(#i->first->asstring = #i->second->asstring)
}
}
}
Following is the code I am trying to get working without relying on a redundant local variable definition:
define paramstovars() => {
local(p = web_request->params)
#p->foreach => {
if(#1->type == 'pair') => {
var(#1->first->asstring = #1->second->asstring)
}
}
}
In this second example, I receive an error that Position was out of range: 1 max is 0 (Error Code -1) on the line calling var().
Obvious security concerns with this custom method aside, what's the most efficient way to make #1 available inside nested conditionals?
#1 is replaced within each capture — so yes, you will need to assign it to another local in order to use it in deeper captures. If you need to work with the local again try using query expressions instead:
with i in web_request->params do {
if(#i->type == 'pair') => {
var(#i->first->asstring = #i->second->asstring)
}
}
Also, I wouldn't recommend settings variables in this fashion — it posses a security risk. It would be better to store the parameters in a single variable and then potentially set specific variables from that. There's a set of tags that does something similar here: getparam / postparam
It is my experience that #1 is consumed when called first time. At least I have never ben able to call it twice in the same capture.
If I need the value more than once I make it a local first. As you do in your example 1.
Some experiments later.
You can call #1 several times, contrary to what I wrote, but what trips your effort is that you have a capture inside the capture (the conditional).
The second capture will have it's own input params.
Here's a working, tested example to do what you want to do:
local(
myarray = array(1, 2 = 'two', 3 = 'four', 4),
mypairs = map
)
#myarray -> foreach => {
if(#1-> isa(::pair)) => {
#mypairs -> insert(#1 -> first -> asstring = #1 -> second -> asstring)
}(#1)
}
#my pairs
The result will be map(2 = two, 3 = four)
The trick is the sending of the foreach param to the conditional capture : `{some code}(#1)
Now, with all that worked out. I recommend that you take a look at Ke Carltons latest addition to tagswap. It will solve the same problem way better than creating a bunch of dynamic vars as you are attempting to do:
www.lassosoft.com/tagswap/detail/web_request_params

Resources