I simplified the code a bit for testing:

ROUTINE ztest23
Version()  quit 20250613
  ;
  ; do init^ztest22(100)  ; in one irissession
  ;
  ; in another irissession:
  ; do test^ztest23()
  ;

test(N=1E7) public {
  do runOne^ztest23("convertInRunFar",N,.dt1),
     runOne^ztest23("convertInBigMacFar",N,.dt2)
  write $fnumber(dt2-dt1*100/dt1,"",2)_"% difference",!
}

runOne(pLabel,N=1E7,&dtpublic ; kill dt do runOne^ztest23("convertInRunFar",1E7,.dt)
{
  if pLabel="convertInRunFar" {
    set comment="looping $$convertIn^ztestLib (far)"
  }else{
    set comment="%New^ztestBigMac, looping $$convertIn^ztestLib (far)"
    set convertName=$$%New^ztestBigMac()
  }
  
  set convertIny=$zconvert("Маленькая умная Коричневая Лиса прыгает через лежащую сонную Пятнистую Собаку","o","UTF8")
  
  set dt0=$zhorolog  for i=1:1:set convertInx=""
  set dt0=($zhorolog-dt0)
  set dt1=$zhorolog for i=1:1:set convertInx=$$convertIn^ztestLib(convertIny,"UTF8")
  set dt=($zhorolog-dt1-dt0)*1E6,dt=dt/N
  write pLabel,?30,$fnumber(dt,"",3),?45,comment,!
}

IRIS 2025.1 CE

I made 4 launches in a row - the result fluctuates greatly:

USER>set N=1E7 do runOne^ztest22("convertInRunFar",N,.fieldsset dt1=$get(fields("dt")) do runOne^ztest22("convertInBigMacFar",N,.fieldsset dt2=$get(fields("dt")) w $fn(dt2-dt1*100/dt1,"",2)_"% difference",!
convertInRunFar               0.473          looping $$convertIn^ztestLib (far)
convertInBigMacFar            0.478          %New^ztestBigMac, looping $$convertIn^ztestLib (far)
1.13% difference
 
USER>set N=1E7 do runOne^ztest22("convertInRunFar",N,.fieldsset dt1=$get(fields("dt")) do runOne^ztest22("convertInBigMacFar",N,.fieldsset dt2=$get(fields("dt")) w $fn(dt2-dt1*100/dt1,"",2)_"% difference",!
convertInRunFar               0.474          looping $$convertIn^ztestLib (far)
convertInBigMacFar            0.598          %New^ztestBigMac, looping $$convertIn^ztestLib (far)
25.99% difference
 
USER>set N=1E7 do runOne^ztest22("convertInRunFar",N,.fieldsset dt1=$get(fields("dt")) do runOne^ztest22("convertInBigMacFar",N,.fieldsset dt2=$get(fields("dt")) w $fn(dt2-dt1*100/dt1,"",2)_"% difference",!
convertInRunFar               0.461          looping $$convertIn^ztestLib (far)
convertInBigMacFar            0.597          %New^ztestBigMac, looping $$convertIn^ztestLib (far)
29.70% difference
 
USER>set N=1E7 do runOne^ztest22("convertInRunFar",N,.fieldsset dt1=$get(fields("dt")) do runOne^ztest22("convertInBigMacFar",N,.fieldsset dt2=$get(fields("dt")) w $fn(dt2-dt1*100/dt1,"",2)_"% difference",!
convertInRunFar               0.511          looping $$convertIn^ztestLib (far)
convertInBigMacFar            0.551          %New^ztestBigMac, looping $$convertIn^ztestLib (far)
7.88% difference
 
USER>

I'm afraid we can't do without the WRC.

See Zen Layout, Zen Style

Class dc.test Extends %ZEN.Component.page
{

XData Style
{
  <style type="text/css">
  #mss {
    width:200px;
    height:100px;
    overflow:auto;
    border:2px solid DeepPink;
    background-color: #E5E5E5;
  }

  a.multiSelectSetCaption {
    colorblue;
    font-familyVerdana;
    font-weightbold;
  }
</style>
}

XData Contents [ XMLNamespace "http://www.intersystems.com/zen" ]
{
<page xmlns="http://www.intersystems.com/zen">
  <multiSelectSet
    id="mss"
    sql="
    select 1 id,'Apple' name
    union select 2,'Banana'
    union select 3,'Cherry'
    union select 4,'Peach'
    union select 5,'Peach'
    union select 6,'Cherry'
    union select 7,'Banana'
    union select 8,'Apple'"
  />
</page>
}

}
Class dc.test Extends %ZEN.Component.page
{

ClientMethod selectMulti() [ Language = javascript ]
{
  var values zenPage.GetValues()
  
  zenSetProp('mss','value',values);
}

ClassMethod GetValues() As %String ZenMethod ]
{
  ; here select data according to a certain condition
  &sql(
  select LIST(idinto :r
  from
    (select id,'Apple' name
    union
    select 2,'Banana'
    union
    select 3,'Cherry'
    union
    select 4,'Peach')
  where name['a'
  )
  quit ; return 2,4
}

ClientMethod saveMulti() [ Language = javascript ]
{
  var values zenGetProp('mss','value');
  zenPage.SaveValues(values);
}

ClassMethod SaveValues(values) [ ZenMethod ]
{
  set ^fruits=values
}

XData Contents [ XMLNamespace "http://www.intersystems.com/zen" ]
{
<page xmlns="http://www.intersystems.com/zen">
  <button caption="Select All" onclick="zen('mss').selectAll()"/>
  <button caption="Select based on data from the database" onclick="zenPage.selectMulti();"/>
  <button caption="Save" onclick="zenPage.saveMulti();"/>
  <multiSelectSet
    id="mss"
    sql="select 1 id,'Apple' name union select 2,'Banana' union select 3,'Cherry' union select 4,'Peach'"
  />
</page>
}

}
Let's suppose two different routines use one and the same chunk of code. From the object-oriented POV, a good decision is to have this chunk of code in a separate class and have both routines call it. However, whenever you call code outside of the routine as opposed to calling code in the same routine, some execution speed is lost. For reports churning through millions of transactions this lost speed might be noticeable. Any advice how to optimize specifically speed?

What you are asking is very similar to Inline function in C.

In Caché, macros and/or preprocessor directives are great for this role. Especially if the code size is small: ObjectScript Macros and the Macro Preprocessor

In this case you will avoid the overhead of calling goto, do, job, xecute, etc.

 
Example (procedure "swap")

When implementing a sorting algorithm doing lots of swaps, this can increase the execution speed.

PS: And yes, avoid passing input/output parameters and class methods due to the high overhead of calling them.

CREATE FUNCTION inLike(str VARCHAR(50), lstLike VARCHAR(50))
RETURNS BIT
PROCEDURE
LANGUAGE OBJECTSCRIPT
{
  set res = 0, ptr = 0
  while $listnext(lstLike,ptr,v{
    &sql(select case when :str like :v then else end into :like)
    if like {
      set res = 1
      quit
    }
  }  
  quit res
}

Usage:

select * from CustomersTable where inLike(CustomerName,$LISTBUILD('%Mark%','%John%','%an%'))=1

In any unclear situation, when incorrect data is returned, two things need to be done first: rebuild the indexes and tune tables:

Since you have a large range of values, I would pay attention to INDEXNULLMARKER: Indexing a NULL

Has it worked before? If so, then most likely there were some changes in the OS at the file/registry level.

First, try to run on the command line (see Registering Files):

>cd D:\DHC\DEVSOFTWARE\ENSEMBLE\BIN
D:\DHC\DEVSOFTWARE\ENSEMBLE\BIN>RegFiles.bat ALL

If it doesn't help, try select Repair to repair problems with the instance such as missing or corrupt files or registry entries: Reinstalling or Uninstalling Caché

Class dc.a Extends %Persistent
{

Property As %String;

ClassMethod Test()
{
  &sql(truncate table dc.a)

  &sql(insert into dc.a(svalues('Hello'))
  ##class(%SQL.Statement).%ExecDirect(,"select * from dc.a").%Display()

  !
  &sql(update dc.set s=s||' world' where %ID=1)
  ##class(%SQL.Statement).%ExecDirect(,"select * from dc.a").%Display()
}

}

USER>##class(dc.a).Test()
ID      s
1       Hello
 
1 Rows(s) Affected
ID      s
1       Hello world
 
1 Rows(s) Affected

Can we see the error number and error text?

If that's correct, is there a way to configure the JDBC connection to interpret this data using EUC-KR encoding?

No: Caché JDBC Connection Properties
But even if JDBC had encoding settings, it wouldn't help you, because the 8-bit version of Caché doesn't support Korean and doesn't know anything about EUC-KR/KSC5601.

PS: I would consider switching to the Unicode version of Caché, which already has support for the Korean language.

However, when I access the data through the Cache Management Portal, Cache Terminal, VSC, or IntelliJ, the Korean text appears broken, as I mentioned earlier.

Give an example of what you see in globals in the InterSystems Management Portal:
System Explorer > Globals

Since you have an 8-bit version and not Unicode, you probably won't see the hieroglyphs (최봉남), but rather something similar to (ÃÖºÀ³²).

This is not corrupted data, just a string stored in KSC5601/EUC-KR encoding.

From Caché terminal (Unicode version, locale = korw (Korean, Korea, Unicode)):

USER>w $zcvt("최봉남","O","KSC5601")
ÃÖºÀ³²
USER>w $zcvt("ÃÖºÀ³²","I","KSC5601")
최봉남

The same on Java:

System.out.println(new String("최봉남".getBytes(Charset.forName("EUC-KR")), Charset.forName("ISO-8859-1"))); // ÃÖºÀ³²
System.out.println(new String("ÃÖºÀ³²".getBytes(StandardCharsets.ISO_8859_1), Charset.forName("EUC-KR")));   // 최봉남
When I run below code in the Cache terminal, it returns 0, so it seems to be the 8-bit version.

That's what I thought. I have the Unicode version installed, the rusw locale, and there are no problems at all.

 
Example
(When I check from the Management Portal, it shows as Latin1. If there's a more accurate way to verify this, please let me know.)

In SMP: System Administration > Configuration > National Language Settings > Locale Definitions
You should have something like kor8, enu8, eng8, etc.