amazon web services – AWS XFS performance issues. Stripped setup vs single disk setup

I wanted to share an issue (I guess I may be misunderstanding some concepts) that I’m facing with some benchmarks I’m doing to XFS setups, as we are going to recently migrate a service to a new instance and we would like to have the max. amount of IOPS possible.

We have a Gitolite instance that currently works with a 500GB io1 volume (25K IOPS), we would like to move this service to a new instance and I was considering the possibility of improving the underlying filesystem.
At this moment the filesystem the instance has it’s XFS on top of LVM on that single volume.

I have been doing some benchmarks on moving the service to an instance with:

  • 8 volumes of 50GB – 2500IOPS each of those

These 8 volumes are included in the same LVM group in an stripped configuration. The commands I used to create this stripped setup are:

## Create the LVM PV's

$ pvcreate /dev/nvme(12345678)n1



## Create the volume group:

$ vgcreate test_vol /dev/nvme(12345678)n1



## Create the stripe configuration:

$ lvcreate --extents 100%FREE --stripes 8 --stripesize 256 --name test test_vol


## XFS format the new volume:

$ mkfs.xfs /dev/mapper/test_vol-root -f

And that should be it. Now, benchmarks.

Running this fio test over this virtual volume:

io --name randwrite --ioengine=libaio --iodepth=2 --rw=randwrite --bs=4k --size=400G --numjobs=8 --runtime=300 --group_reporting --filename=/test/testfile --fallocate=none

Shows the following report:

Jobs: 8 (f=8): (w(8))(100.0%)(w=137MiB/s)(w=35.1k IOPS)(eta 00m:00s)
randwrite: (groupid=0, jobs=8): err= 0: pid=627615: Wed Nov 25 13:15:33 2020
  write: IOPS=23.0k, BW=93.7MiB/s (98.2MB/s)(27.4GiB/300035msec); 0 zone resets
    slat (usec): min=2, max=132220, avg=141.07, stdev=2149.78
    clat (usec): min=3, max=132226, avg=143.46, stdev=2150.25

Which is not bad at all, but executing the very same fio benchmark on another instance with a single volume of 500GB (25K IOPS) shows:

Jobs: 8 (f=8): (w(8))(100.0%)(w=217MiB/s)(w=55.6k IOPS)(eta 00m:00s)
randwrite: (groupid=0, jobs=8): err= 0: pid=11335: Wed Nov 25 12:54:57 2020
  write: IOPS=48.2k, BW=188MiB/s (198MB/s)(55.2GiB/300027msec); 0 zone resets
    slat (usec): min=2, max=235750, avg=130.69, stdev=1861.69

Which is by far much better output than the stripped setup.


We are going to use this instance to host an internal Git server, so I was assuming than an stripped setup would be much better than an instance with a single volume, but those benchmarks show the best setup (in terms of IOPS/bandwidth) is the one with the single disk.

Am I assuming anything wrong? Will the stripped setup work better for random writers(ie. not running out of IOPS)

performance – How can I speed up my VBA code?

I want to ask for help on how to further accelerate this code.

Operation of the code

It copies 1-1 worksheets from 3 different workbooks to 3 worksheets of the new workbook. Inserts, copies, and formats different columns. Then, by examining different criteria on a worksheet called “lista”, type red 1s in specific cells or copy text.

What I’ve done so far for speed up

-Switching application functions on and off (like Application.ScreenUpdating)

-where it is possible using With – end with

-Delimitation of operation area with “lastrow”.

-Usage vbNullString instead of “”

Get running the macro with a list of 180,000 lines takes 3-3.5 hours for done.

Environmental parameters

  • Windows 10 Home
  • Intel Core i7-930 2.8Ghz
  • 16GB RAM
  • 516GB SSD
  • Excel 2013

Do you see any opportunity to accelerate?

The entire code:

Option Explicit
Sub Gyogyit()

Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.EnableEvents = False
ActiveSheet.DisplayPageBreaks = False

Dim egyedilap, gyogylap, segedlap, listlap As Worksheet
Dim closedBook As Workbook
Dim listlastrow, gyogylastrow, listlastrow2, egyedilastrow As Long
Dim aoszl, Prob, kitolt, a, x, y, Z, v, w, af, dd, coutaj, egmunk, egmunk2, kozfog, kozfog2, j, nm, eufogl, eufogl2, vangyogy, vanegyedi, alap As Integer
Dim n As Date
Dim p, q, ag, ah, ak, an, ao, ap, aq, megbkim, apolh, korhdat, korhnev, imporsz, jarvaz, nevkod, jarvnev, betmk, betfog, kozfogl, kozfogl2, muhnev, munkhelygyogy, betmunkgyogy, betfoglszovgyogy, korhegyedi, megbkimegyed, korfelvegyed, kormegngyogy, korfeldatgyogy, apolhelygyogy, megbkimgyogy, apolhelyegyed As String
Dim StartTime As Double
Dim MinutesElapsed As String
Dim gyogyult, otthon As Boolean

StartTime = Timer

Set listlap = ThisWorkbook.Worksheets("lista")
Set gyogylap = ThisWorkbook.Worksheets("BE_gyogy")
Set segedlap = ThisWorkbook.Worksheets("segedlap")
Set egyedilap = ThisWorkbook.Worksheets("egyedi")

Application.DisplayAlerts = False
    listlap.Range("I:K").Delete

Set closedBook = Workbooks.Open("C:UserstulajDocumentsmakróhozalap másolatalista_okt-26.xlsx")
    closedBook.Sheets(1).Range("A:AM").Copy listlap.Range("I:AU")
    closedBook.Close SaveChanges:=False
Set closedBook = Workbooks.Open("C:UserstulajDocumentsmakróhozalap másolataBE_gyogy.xlsx")
    closedBook.Sheets(1).Range("A:DD").Copy gyogylap.Range("B:DF")
    closedBook.Close SaveChanges:=False
Set closedBook = Workbooks.Open("C:UserstulajDocumentsmakróhozalap másolataegyedi.xlsx")
    closedBook.Sheets(1).Range("A:DY").Copy egyedilap.Range("B:DZ")
    closedBook.Close SaveChanges:=False
Application.DisplayAlerts = True

With egyedilap
    .Activate
    .Range("E:E").Copy Range("A:A")
    .Columns("A:A").NumberFormat = "0"
End With
With gyogylap
    .Activate
    .Range("I:I").Copy Range("A:A")
    .Columns("A:A").NumberFormat = "0"
End With

gyogylastrow = gyogylap.Cells(Rows.Count, 1).End(xlUp).Row
egyedilastrow = egyedilap.Cells(Rows.Count, 1).End(xlUp).Row

With listlap
    .Activate
    .Columns("AG").Insert Shift:=xlToRight
    .Range("AG1").Value = "Eü. fogl."
    .Columns("AK").Insert Shift:=xlToRight
    .Range("AK1").Value = "Import orsz."
    .Columns("AO").Insert Shift:=xlToRight
    .Range("AO1").Value = "Járvány neve"
    .Range("AT:AT").Copy Range("A:A")
    .Columns("A:A").NumberFormat = "0"
    .Range("A1").Value = "TAJ"
    .Columns("AS:AS").NumberFormat = "yyyy/mm/dd"
    
    listlastrow = listlap.Cells(Rows.Count, 1).End(xlUp).Row
    
        For x = 2 To listlastrow
            If .Range("A" & x).Value = vbNullString Then
                .Range("A" & x).Value = "nincs"
            End If
        Next x

    For kitolt = 2 To listlastrow
    On Error Resume Next
        a = .Range("A" & kitolt)
        n = .Range("N" & kitolt)
        p = .Range("P" & kitolt)
        q = .Range("Q" & kitolt)
        x = .Range("X" & kitolt)
        y = .Range("Y" & kitolt)
        Z = .Range("Z" & kitolt)
        v = .Range("V" & kitolt)
        w = .Range("W" & kitolt)
        j = .Range("J" & kitolt)
        ag = .Range("AG" & kitolt)
        ak = .Range("AK" & kitolt)
        an = .Range("AN" & kitolt)
        ao = .Range("AO" & kitolt)
            With Application.WorksheetFunction
                vangyogy = .CountIf(gyogylap.Range("A:A"), a)
                vanegyedi = .CountIf(egyedilap.Range("A:A"), a)
                korfeldatgyogy = .VLookup(a, gyogylap.Range("A2:CM" & gyogylastrow), 46, False)
                kormegngyogy = .VLookup(a, gyogylap.Range("A2:CM" & gyogylastrow), 47, False)
                korhegyedi = .VLookup(a, egyedilap.Range("A2:DZ" & egyedilastrow), 32, False)
                korfelvegyed = .VLookup(a, egyedilap.Range("A2:DZ" & egyedilastrow), 33, False)
                    If vangyogy = 1 Then
                        megbkimgyogy = .VLookup(a, gyogylap.Range("A2:CM" & gyogylastrow), 49, False)
                        apolhelygyogy = .VLookup(a, gyogylap.Range("A2:CM" & gyogylastrow), 33, False)
                    Else
                        megbkimgyogy = vbNullString
                        apolhelygyogy = vbNullString
                    End If
                    If vanegyedi <> vbNullString Then
                        megbkimegyed = .VLookup(a, egyedilap.Range("A2:DZ" & egyedilastrow), 35, False)
                        apolhelyegyed = .VLookup(a, egyedilap.Range("A2:DZ" & egyedilastrow), 12, False)
                    Else
                        megbkimegyed = vbNullString
                        apolhelyegyed = vbNullString
                    End If
                betfoglszovgyogy = .VLookup(a, gyogylap.Range("A2:CM" & gyogylastrow), 19, False)
                eufogl = .CountIf(segedlap.Range("M:M"), betfoglszovgyogy)
                betmunkgyogy = .VLookup(a, gyogylap.Range("A2:CM" & gyogylastrow), 20, False)
                eufogl2 = .CountIf(segedlap.Range("M:M"), betmunkgyogy)
                munkhelygyogy = .VLookup(a, gyogylap.Range("A2:CM" & gyogylastrow), 21, False)
                kozfogl = .CountIf(segedlap.Range("K:K"), betmunkgyogy)
                kozfogl2 = .CountIf(segedlap.Range("K:K"), betfoglszovgyogy)
                nevkod = .VLookup(a, gyogylap.Range("A2:CM" & gyogylastrow), 11, False)
                otthon = ((apolhelygyogy = "Otthon" And vanegyedi <> 1) Or _
                (apolhelygyogy = vbNullString And vanegyedi = 1 And apolhelyegyed = "Otthon") Or _
                (apolhelygyogy = "Otthon" And vanegyedi = 1 And apolhelyegyed = "Otthon"))
                gyogyult = ((megbkimgyogy = "Gyógyult" And vanegyedi <> 1) Or _
                (megbkimegyed = "gyógyult" And vanegyedi = 1 And megbkimgyogy = vbNullString) Or _
                (megbkimegyed = "gyógyult" And vanegyedi = 1 And megbkimgyogy = "Gyógyult"))
            End With

            If a <> vbNullString And a <> 0 And a <> "nincs" Then
                If q = vbNullString And _
                    v = vbNullString And _
                    w = vbNullString And _
                    x = vbNullString And _
                    Z = vbNullString And _
                    korfeldatgyogy = vbNullString And _
                    kormegngyogy = vbNullString And _
                    korhegyedi = vbNullString And _
                    korfelvegyed = vbNullString And _
                    nevkod <> "comtu001" And _
                    nevkod <> "voviv001" And _
                    nevkod <> "rocal006" Then
                    alap = 1
                'Debug.Print alap
                        If p = vbNullString And _
                            (vangyogy = 1 Or vanegyedi = 1) = True And _
                            alap = 1 And _
                            otthon = True Then
                            .Range("P" & kitolt).Value = 1
                            .Range("P" & kitolt).Font.Color = RGB(210, 65, 65)
                        End If
                        If y = vbNullString And _
                            (vangyogy = 1 Or vanegyedi = 1) = True And _
                            j < 64 And _
                            Date - n > 13 And _
                            p = 1 And _
                            gyogyult = True Then
                            .Range("Y" & kitolt).Value = 1
                            .Range("Y" & kitolt).Font.Color = RGB(210, 65, 65)
                        End If
                        alap = 0
                End If
                'Debug.Print kitolt '& " " & alap & " " & vangyogy & " " & vanegyedi & " " & otthon & " " & gyogyult & " " & megbkimgyogy & " " & megbkimegyed
            End If
            If ak = vbNullString Then
                .Range("AK" & kitolt).Value = Application.WorksheetFunction.VLookup(a, gyogylap.Range("A2:CM" & gyogylastrow), 54, False)
                .Range("AK" & kitolt).Font.Color = RGB(210, 65, 65)
            End If
            If an = vbNullString Then
                .Range("AN" & kitolt).Value = Application.WorksheetFunction.VLookup(a, gyogylap.Range("A2:CM" & gyogylastrow), 87, False)
                .Range("AN" & kitolt).Font.Color = RGB(210, 65, 65)
            End If
            If ao = vbNullString Then
                .Range("AO" & kitolt).Value = Application.WorksheetFunction.VLookup(a, gyogylap.Range("A2:CM" & gyogylastrow), 88, False)
                .Range("AO" & kitolt).Font.Color = RGB(210, 65, 65)
            End If
            If ag = vbNullString Then
                If eufogl = 1 Then
                    .Range("AG" & kitolt).Value = betmunkgyogy
                    .Range("AH" & kitolt).Value = munkhelygyogy
                    .Range("AF" & kitolt).Value = 1
                    .Range("AG" & kitolt).Font.Color = RGB(210, 65, 65)
                    .Range("AH" & kitolt).Font.Color = RGB(210, 65, 65)
                    .Range("AF" & kitolt).Font.Color = RGB(210, 65, 65)
                ElseIf eufogl2 = 1 And a <> vbNullString And a <> "0" And a <> "nincs" Then
                    .Range("AG" & kitolt).Value = betfoglszovgyogy
                    .Range("AH" & kitolt).Value = munkhelygyogy
                    .Range("AF" & kitolt).Value = 1
                    .Range("AG" & kitolt).Font.Color = RGB(210, 65, 65)
                    .Range("AH" & kitolt).Font.Color = RGB(210, 65, 65)
                    .Range("AF" & kitolt).Font.Color = RGB(210, 65, 65)
                End If
            End If
            If aq = vbNullString Then
                If kozfogl = 1 Then
                    .Range("AQ" & kitolt).Value = betmunkgyogy
                    .Range("AP" & kitolt).Value = munkhelygyogy
                    .Range("AQ" & kitolt).Font.Color = RGB(210, 65, 65)
                    .Range("AP" & kitolt).Font.Color = RGB(210, 65, 65)
                ElseIf kozfogl2 = 1 And a <> vbNullString And a <> "0" And a <> "nincs" Then
                    .Range("AQ" & kitolt).Value = betfoglszovgyogy
                    .Range("AP" & kitolt).Value = munkhelygyogy
                    .Range("AQ" & kitolt).Font.Color = RGB(210, 65, 65)
                    .Range("AP" & kitolt).Font.Color = RGB(210, 65, 65)
                End If
            End If
    Next kitolt
    
    Range("H2").Select
    ActiveCell.FormulaR1C1 = "=COUNTIF(C(+7),RC(+7))"
    Range("E2").Select
    ActiveCell.FormulaR1C1 = "=CONCATENATE(RC(39),RC(40))"
    
End With

Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.DisplayStatusBar = True
Application.EnableEvents = True
ActiveSheet.DisplayPageBreaks = True

MinutesElapsed = format((Timer - StartTime) / 86400, "hh:mm:ss")
MsgBox "This code ran successfully in " & MinutesElapsed & " minutes", vbInformation
End Sub
```

Battery performance on iPad in sidecar mode

I’m thinking of getting an iPad as a second display using the sidecar feature.

Assuming the display be always on in sidecar mode and it’s always plugged in to charge, would the iPad using its battery while it’s charging? Or will it be drawing power from the outlet?

I’m wondering about battery performance (cycles) since the device would be on most of the day and it would need to charged often.

performance – Forecasts for construction equipment dealers

I was wondering if it is possible to speed up this script? The source file has 90,000 rows, and it has to create a separate forecast for 1200 unique dealers using fbprophet. I’m new to python so I’m not sure if there is something obvious I’m missing, or if it’s just going to have to take a really long time. If any sees a simple solution that would speed it up, I would appreciate any insight. Thank you

Additional details about code:
The code takes a CSV file that has 3 columns(Month, Dealer, and Sales) and creates a filter essentially for each unique dealer name, and then uses Fbprophet to forecast the future results of each dealer. Then it combines all the information in a CSV file. It’s 90,000+ rows of data typically, and normally 1200 unique dealers that need to be forecasted. The historical data is 7 years of history.

from pandas import read_csv
from pandas import to_datetime
from pandas import DataFrame


from fbprophet import Prophet
from matplotlib import pyplot
import pandas as pd
# load data
data = read_csv('X.csv', header=0)
# prepare expected column names
data.columns = ('ds','Dealer', 'y')
data('ds')= to_datetime(data('ds'))

results = pd.DataFrame()

for dealer in data('Dealer').unique():
    df_filtered = data(data('Dealer')==dealer)
    prophet_df = data(('ds', 'y'))
    # define the model
    model = Prophet()
    # fit the model
    model.fit(prophet_df)
    # define the period for which we want a prediction
    future = list()
    for h in range(11, 13):
        date = '2020-%02d' % h
        future.append((date))
    for i in range(1, 13):
        date = '2021-%02d' % i
        future.append((date))
    for j in range(1, 13):
        date = '2022-%02d' % j
        future.append((date))
    for k in range(1, 13):
        date = '2023-%02d' % k
        future.append((date))
    future = DataFrame(future)
    future.columns = ('ds')
    future('ds')= to_datetime(future('ds'))
    # use the model to make a forecast
    forecast = model.predict(future)
    forecast('Dealer') = dealer
#     forecast.head(5)
    results = results.append(forecast)

results.to_csv('X1.csv')

Link to Sample Data: https://drive.google.com/file/d/1e_FlpsdS0hex2RocHg7GSfP__H4sxNF1/view?usp=sharing

magento2 – Magento Checkout Page Performance

I was going through perfomance improvement in magento 2 checkout page and I found in view source
country Id with huge country list irrespective of your admin configuration Allowed country list

the problem is I literally measured the size of that json object and its nearly 800 kb close to 1 MB

enter image description here

so anybody have idea to optimize this part would be appreciated

Thanks in advance

performance – JMeter: how to asign a single distinct value from CSV Data Set Config to each thread in thread group?

I have to make a load test for a relatively large number of users so I cant really use User Parameters pre-processor to parametrize each thread with custom user data. I’ve read that I should use CSV Data Set Config instead. However I run into a problem with how JMeter interprets the input of this Config.

Example:

I have a thread group of 3 threads and Loop Count:10 with one HTTP request sampler with server www.example.com and path: ${user}.
The csv file (bullet is a single line in file) for CSV Data Set Config to extract the user parameter:

Expected output is that for thread 1-x the path of the request should be: x. So the output file should consist of 10 samples per thread namely:

  • for thread 1-1 : 10 requests to www.example.com1
  • for thread 1-2 : 10 requests to www.example.com2
  • for thread 1-3 : 10 requests to www.example.com3

but instead i get requests to each 1 – 5 and then to EOF. Does anyone know how to achieve the expected effect with CSV Data Set Config in jmeter 2.9?

performance – “Backwards Read Primes” of Codewars powershell version

Link to problem: https://www.codewars.com/kata/5539fecef69c483c5a000015/train/powershell

I have a working solution in Codewars but my solution is slow for some reason and
I need to improve the efficiency.

Please look over my solution and offer any suggestions on things I could do to
improve what I have.

Instructions for problem:

Backwards Read Primes are primes that when read backwards in base 10 (from right
to left) are a different prime. (This rules out primes which are palindromes.)

Examples:
13 17 31 37 71 73 are Backwards Read Primes
13 is such because it’s prime and read from right to left writes 31 which is prime too. Same for the others.

Task
Find all Backwards Read Primes between two positive given numbers (both inclusive), the second one always being greater than or equal to the first one. The resulting array or the resulting string will be ordered following the natural order of the prime numbers.

Example
backwardsPrime(2, 100) => (13, 17, 31, 37, 71, 73, 79, 97) backwardsPrime(9900, 10000) => (9923, 9931, 9941, 9967) backwardsPrime(501, 599) => ()

Note for Forth
Return only the first backwards-read prime between start and end or 0 if you don’t find any

Don’t use Ruby Prime class, it’s disabled.
backwardsPrime(2, 100) => (13, 17, 31, 37, 71, 73, 79, 97)
backwardsPrime(9900, 10000) => (9923, 9931, 9941, 9967)

Thanks.


$primes = @{ 2 = 2; 3 = 3; 5 = 5; 7 = 7; 11 = 11; 13 = 13; 17 = 17; 31 = 31; 37 = 37; 71 = 71; 73 = 73; 79 = 79; 97 = 97; 107 = 107; 113 = 113; 149 = 149; 157 = 157; 167 = 167; 179 = 179; 199 = 199 };

function backwards-prime($start, $stop) 
{

    function revNum ((int) $n) {
        $numStr = $n.ToString();
        return ($numStr(-1..-($numStr.Length)) -join "") -as (int);
    }

    function isPrime ($num) {

        if ($primes.containsKey($num)) {
            return $true;
        }

        if ($num -lt 3) {
            return $num -gt 1;
        }

        if ($num % 2 -eq 0 -or $num % 3 -eq 0) {
            return $false;
        }

        $i = 5;

        while ($i * $i -le $num) {
            if ($num % $i -eq 0 -or $num % ($i + 2) -eq 0) {
                return $false; 
            }

            $i += 6;
        }

        $primes($num.ToString()) = $num;

        return $true;
    }

    $res = @();
    
    if($start % 2 -eq 0) { $start = $start + 1; }
    if($stop % 2 -eq 0) { $stop = $stop - 1; }

    for ($i = $start; $i -le $stop; $i += 2) {
        $nPrime = isPrime $i;
        $nReversed = revNum $i;
        $nPrimeReverse = isPrime $nReversed;

        if ($nPrime -and $nPrimeReverse -and $i -ne $nReversed -and $i -ge 13) {
            $res += $i;
        }
    }

    return ($res -join ", ").Trim();
}

``` 

performance – Speed up a loop with values replacement

I have a 2D matrix. I want to compare each value with the mean of the values in a box around it(excluding the value itself). If the value is bigger than the mean plus 3sigma it will be replaced by the mean of the values in the box. Then I repeat the process over the matrix five times.
So, I have these pice of code that works just fine in my little example matrix, but when I go to the real one (750X2000) it takes forever to run. Is there any way to speed up this loop? Im relatively new to python, so maybe there are some basic, obvious things that Im not seeing.

    import numpy as np
    mat= (( 0 , 2 , 4 , 60000 , 8),(10 ,12, 14000, 16, 18),(20 ,22, 625, 26, 28),(30, 32,34, 36, 38),(10000, 42, 44, 46, 48)) 
    mat=np.array(mat)
    print(mat)
    print(mat.shape(0))
    print('###############')
    b=0
    while b<5:
          for i in range(mat.shape(0)):
               for j in range(mat.shape(1)):
                   chunk = mat(max(0,i-1):i+2, max(0,j-1):j+2)
                   c = np.setdiff1d(chunk,mat(i,j))
                   media_c=np.mean(c)
                   #print(media_c)
                   sdv=np.std(c)
                   if mat(i,j)>media_c+3*sdv:
                       mat(i,j)=media_c
        
               b+=1
    
     print(mat)

sharepoint server – Performance on using hierarchical tasks in a huge task list

We combined multiple task lists into one to overcome different difficulties. This resulted in a task list with about 90.000 items.
Upon opening a hierarchical task view with an additional filter on an indexed column, SharePoint takes about 60s to render the page. The time consuming operations seem to reside on the server side, as we get our first response inside the network tab of FireBug at about 58s. We think, SharePoint will be getting all list items to sort them properly into the hierarchy.

Does anybody have a clue if SharePoint could be convinced to just load those elements, that would be contained inside the filter?
Upon filtering directly or by using a view grouped by the filter element, the page renders in about 2 seconds.

performance – Is this function “in place” and O(1) space and O(n) time?

function reverseWords(message) {
  const max = message.length;
  let n = max;
  let wordLen = 0;
  for (let i = 0; i < max; i += 1) {
    if (message(i) === " ") {
      n -= wordLen;
      wordLen = 0;
      message.splice(max - wordLen, 0, " ");
    } else {
      message.splice(n, 0, message(i));
      wordLen += 1;
      n += 1;
    }
  }
  message.splice(0, max);
}

//==========================================================================
/*Test cases using Jasmine (see https://github.com/jasmine/jasmine and https://jasmine.github.io/pages/docs_home.html):
describe("main tests, but showing just one for brevity", function () {

  it("rearranges correctly", function () {
    const message = (
      "m",
      "e",
      "s",
      "s",
      "a",
      "g",
      "e",
      " ",
      "t",
      "h",
      "e",
      " ",
      "i",
      "s",
      " ",
      "h",
      "e",
      "r",
      "e"
    );

    reverseWords(message);
    expect(message.join("")).toEqual("here is the message");
  });
});*/

const message = (
      "m",
      "e",
      "s",
      "s",
      "a",
      "g",
      "e",
      " ",
      "t",
      "h",
      "e",
      " ",
      "i",
      "s",
      " ",
      "h",
      "e",
      "r",
      "e"
    );

    reverseWords(message);
    console.log(message.join(""));