go to post Robert Cemper · Jun 24 About 5 years back, I composed an example for a WebSockel Clientmight be a starting point
go to post Robert Cemper · Jun 20 Point 2. of the previous reply is definitely WRONG! Point 4. takes that back in some way but leaves it ambiguous. Using extended Global References (also in Class Storage Definitions)allows access to any mounted DB if you have access rights. A personal example: USER>for i=1:1:5 set ^|"^^C:\InterSystems\IRIS242\mgr\nonspace"|rcc(i)=i USER>zwrite ^|"^^C:\InterSystems\IRIS242\mgr\nonspace"|rcc ^|"^^C:\InterSystems\IRIS242\mgr\nonspace"|rcc(1)=1 ^|"^^C:\InterSystems\IRIS242\mgr\nonspace"|rcc(2)=2 ^|"^^C:\InterSystems\IRIS242\mgr\nonspace"|rcc(3)=3 ^|"^^C:\InterSystems\IRIS242\mgr\nonspace"|rcc(4)=4 ^|"^^C:\InterSystems\IRIS242\mgr\nonspace"|rcc(5)=5 USER> I learned this traditional technique 47 years ago. And it still works fine.
go to post Robert Cemper · Jun 20 straight ObjectScript USER>if $d(^|"%SYS"|CONFIG("Namespaces"," ")) ;; position $ZR in CONFIG USER>for set ns=$o(@$ZR) quit:ns="" zwrite ns ; list it ns="%SYS" ns="SAMPLES" ns="USER" USER> BINGO !
go to post Robert Cemper · Jun 8 Fully agree with your suggestion of an Abstract Class.It's in fact the modern equivalent of the old .INC approach
go to post Robert Cemper · Jun 8 much more simple with 2 identic .INT routines a1 and a2 ROUTINE a1 [Type=INC] load ; read !,"loops=",loop,! do t1 hang 0.5 do t2 quit next set t1=$zh quit t1 set t0=$zh for i=1:1:loop do next write t1-t0,! quit t2 set t0=$zh for i=1:1:loop do next^a2 write t1-t0,! quit SAMPLES>d ^a1 loops=1000000 .081626 .136785 SAMPLES> I just mean you can't do less:the difference is even worse 40.3%
go to post Robert Cemper · Jun 8 My approach was rather simple. in runtime any class has its .INT wich has its .OBJ the OBJ is in the partition. if I stay inside the .OBJ it's fine if I have to load another .OBJ and then reload the original .OBJ it consumes processor cycles both .OBJ can be assumed to be cached, so it's a pure memory exercise the difference of both variants is sub microscopic so looping for 100 M is kind of zoom-in to get something visible The 100 M are common to both scenarios and the Global has only (800 Mb) >>> 8 bytes / record counted by I decided for SQL Shell for its nice runtime display. SUMMARY: There is a difference.But I wouldn't bend a little finger to attack it. (not even on PDP-11)This is nothing where performance comes from.
go to post Robert Cemper · Jun 8 OK - in UDL IRIS for Windows (x86-64) 2024.3 (Build 217U) Thu Nov 14 2024 17:59:58 EST ROUTINE anna [Type=INC] anna(name) quit "" A.HUGE.cls Include anna Class A.HUGE Extends (%Persistent, %Populate) { Property calc As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ]; ClassMethod fill(size) As %String [ SqlProc ] { for i=1:1:size set ^A.HUGED(i)="" set ^A.HUGED=i quit $ZR_"="_@$ZR } ClassMethod test1(val) As %String [ SqlProc ] { quit ##class(A.PERSON).Anna(val) } ClassMethod test2(val) As %String [ SqlProc ] { quit $$anna(val) } Storage Default { <Data name="HUGEDefaultData"> <Value name="1"> <Value>%%CLASSNAME</Value> </Value> </Data> <DataLocation>^A.HUGED</DataLocation> <DefaultData>HUGEDefaultData</DefaultData> <IdLocation>^A.HUGED</IdLocation> <IndexLocation>^A.HUGEI</IndexLocation> <StreamLocation>^A.HUGES</StreamLocation> <Type>%Storage.Persistent</Type> } } A.PERSON.cls Include anna Class A.PERSON Extends %Persistent { Property calc As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ]; ClassMethod fill(size) As %String [ SqlProc ] { for i=1:1:size set ^A.PERSOND(i)="" set ^A.PERSOND=i quit $ZR_"="_@$ZR } ClassMethod test1(val) As %String [ SqlProc ] { quit ##class(A.PERSON).Anna(val) } ClassMethod Anna(name As %String) As %String { quit $$anna(name) } Storage Default { <Data name="PERSONDefaultData"> <Value name="1"> <Value>%%CLASSNAME</Value> </Value> </Data> <DataLocation>^A.PERSOND</DataLocation> <DefaultData>PERSONDefaultData</DefaultData> <IdLocation>^A.PERSOND</IdLocation> <IndexLocation>^A.PERSONI</IndexLocation> <StreamLocation>^A.PERSONS</StreamLocation> <Type>%Storage.Persistent</Type> } }
go to post Robert Cemper · Jun 7 I did this to verify my approach looping over a simulated table of 100 mio rows SQL procedure TEST1 uses an external Class Method based on anna.INC SQL procedure TEST2 uses an internal Class Method based on anna.INC The difference is evident: [SQL]SAMPLES>>select A.HUGE_fill(100000000) 18. select A.HUGE_fill(100000000) | Expression_1 | | -- | | ^A.HUGED=100000000 | 1 Rows(s) Affected statement prepare time(s)/globals/cmds/disk: 0.0008s/5/828/0ms execute time(s)/globals/cmds/disk: 18.8332s/100,000,002/200,000,445/0ms query class: %sqlcq.SAMPLES.cls3 --------------------------------------------------------------------------- [SQL]SAMPLES>>select list(A.HUGE_TEST1(ID)) from A.HUGE 19. select list(A.HUGE_TEST1(ID)) from A.HUGE | Aggregate_1 | | -- | | | 1 Rows(s) Affected statement prepare time(s)/globals/cmds/disk: 0.0005s/4/141/0ms execute time(s)/globals/cmds/disk: 101.5573s/100,000,001/700,000,424/0ms query class: %sqlcq.SAMPLES.cls2 --------------------------------------------------------------------------- [SQL]SAMPLES>>select list(A.HUGE_TEST2(ID)) from A.HUGE 20. select list(A.HUGE_TEST2(ID)) from A.HUGE | Aggregate_1 | | -- | | | 1 Rows(s) Affected statement prepare time(s)/globals/cmds/disk: 0.0005s/4/141/0ms execute time(s)/globals/cmds/disk: 72.1640s/100,000,001/700,000,424/0ms query class: %sqlcq.SAMPLES.cls1 --------------------------------------------------------------------------- [SQL]SAMPLES>> Rough calculation: including the code in the class saves ~30% of execution time my class code Include anna Class A.HUGE Extends (%Persistent, %Populate) { Property calc As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ]; ClassMethod fill(size) As %String [ SqlProc ] { for i=1:1:size set ^A.HUGED(i)="" set ^A.HUGED=i quit $ZR_"="_@$ZR } ClassMethod test1(val) As %String [ SqlProc ] { quit ##class(A.PERSON).Anna(val) } ClassMethod test2(val) As %String [ SqlProc ] { quit $$anna(val) } The simplified anna,INC just returns NullString to concentrate on code switching anna(name) quit ""
go to post Robert Cemper · Jun 6 Loading compiled obj code from cache to partition should not have any remarkable impact.But you are right by principle ! It's some kind of overhead and not for free. If you place the affected code into a .INC routine you may share that piecerather easy over multiple instances.Though mostly not used in that way any Include may also contain executable code.For a :MAC routine it's nothing impressive.For Class code it's a bit tricky but works as well example ANNA.INC anna(name) ; write !,"Hello ",name,! quit ">>>"_name_"<<<" example Anna.CLS /// demo for Anna Include ANNA Class A.Anna { ClassMethod demo(name As %String) As %String { quit $$anna(name) } } It works: SAMPLES>write "===",##class(A.Anna).demo("robert") === Hello robert >>>robert<<< SAMPLES> So multiple loading is reduced.You have of course also the option to compose a Custom Command in %ZLANG***.MACI just have no experience of how this impacts partition loading.
go to post Robert Cemper · Jun 5 Studio shows the Error already during typing. But this works fine as you expected: BINGO ! composed by nI
go to post Robert Cemper · Jun 5 Exactly.!..#PARAMETER inserts a STRINGBut >>> $NAME() looks for a variable also by indirection USER>w $name("^rcc(1)") W $NAME("^rcc(1)") ^ <SYNTAX> USER>w $name(^rcc(1)) ^rcc(1) USER>s x="^rcc(1)" USER>w $name(x) x USER>w $name(@x) ^rcc(1) USER>
go to post Robert Cemper · Jun 3 Hi Jean, at first glance I'd expect the query plan for #18. and #19. should be quite similar:SQL offers 3 levels to see the query plan show Show the execution plan for the current statement. show pl[an] [v[erbose]] Shows the current statement execution plan. If the verbose qualifier is used, show all the module details for the current statement's execution plan; Otherwise, display only the top-level module details by default. show planalt [v[erbose]] Shows the current statement alternate execution plans. If the verbose qualifier is used, show all the module details for the current statement's execution plan and all alternate plans; Otherwise, display only the top-level module details by default.. This might offer a chance to identify the difference.There's still an - unlikely - chance that #19 runs on some broken cached query,that never was updated. so clear cached queries might be a possible solution. Not an explanation Best regards, Robert
go to post Robert Cemper · Jun 1 Interoperability is not available in all namespaces. Typically not in %SYS, but in USERCheck in Management Portal. where it is included.
go to post Robert Cemper · May 29 I'm once more impressed by your contribution.As often in past you leave the (mostly boring) mainstream,look over the mental fence and bring tools and solutions beyond the usual compositions that I see repeatedly in my reviews.this is just great! . 👏 👍
go to post Robert Cemper · May 28 Hello community; My name is Robert C. Cemper, graduate engineer from Vienna Technical University I'm Austrian, born and still living in Vienna for 77 years. I'm married once and have 3 aged children. Over the years I worked with several big companies in the emerging IT market, like SIEMENS, Olivetti, Digital Equipment, Compaq, ... finally InterSystems. My special story with InterSystems is available in this article 45 Years with Intersystems Actually I'm "retired but not tired" and follow Developer Community with unbroken interest. Especially because I had a similar proposal 10 years before it finally materialized. My feelings for it are quite similar to a grandfather My special interests are the core functionalities of the Global Storage, ObjectScript and SQL Working close to the internals is my core competence, but also all network stuff. Actually im focusing on Docker in the OpenExchange environment. My top hobby are computers for about 60 years and my whole career was based on it. I started with a console panel with toggle switches for the address and some others for the content. One of my teachers built the first transistor based computer in Europe. Other hobbies like music, theater, skiing, hiking, biking, travel to other countries changed importance over time. At my retirement I returned to University to catch up with progress in Physics, especially Quantum Physics, Cosmology, Paleology, ... I also added Latin to my set of 4 spoken + 2 written languages. I stopped LinkedIn as I was spammed by unacceptable job offers. Due to health and social limitations I will not attend READY 2025