AW: Thread-safe record mapper speed-ups

"Kallidis, Georg" <[email protected]> Fri, 17 Oct 2025 12:35:17 +0200
Newsgroups gmane.comp.jakarta.turbine.torque.devel
Message-ID <[email protected]>
------=_NextPart_000_0024_01DC3F62.582EA8B0
Content-Type: text/plain;
	charset="utf-8"
Content-Transfer-Encoding: quoted-printable

Hi Max and Rene,

thanks for this work!

I merged it locally, which worked as expected  with svn patch.

I did run the maven build locally, and no errors were reported.=20

When I inspect the implementation of a strategy,=20
e.g. in the generated torque-templates/target/generated-sources
org.apache.torque.test.BaseCRecordMapper class
in the method processRow

Previously (release 7), if criteria was not null the strategy (if set) =
gets applied.

Reading the code two things are now explicitely:
(1) if criteria is a composite or=20
(2) columns without offset is empty (that is all columns do have an =
offset)=20
processRow returns a null object.

(1) may or may be correct, I am not sure.
(2) I stumbled over the name columnsWithoutOffset. If I check the =
filtering skip(rowOffset) will only return an empty list if rowOffset is =
greater than the number of the selected columns. This might be almost an =
error, if not a warning IMO. Could we find a better name for the =
variable columnsWithoutOffset (might be columnsAfterOffset or =
shiftedColumns)?

Concerning backward compatibility: This seems only an issue, if you want =
to use the Torque classes without regenerating the sources.=20

But that's true, with the current patch this will fail. We could do a =
null check of the mappingStrategy field in ResultsetSpliterator =
tryAvance method and then calling the default processRow (which would in =
an old recordMapper code call a new MappingStrategy in the removed =
method initStrategy method - this may then be again backward =
comnpatible. Another backward issue would be that the Mappingstrategy =
method finish before had two parameters. We might resolve this latter =
issue also with a dummy method (we failed to declare an interface =
before, which had showed us this immediately =F0=9F=98=89

Nevertheless I think, we should merge it soon into the trunk and provide =
later some documentation or updates.

We may wait a little bit more time (until next week or end of month?) to =
get some more considerations =F0=9F=98=89=20

Have a nice weekend!

Best regards, Georg

-----Urspr=C3=BCngliche Nachricht-----
Von: Max Philipp Wriedt <[email protected]>=20
Gesendet: Mittwoch, 15. Oktober 2025 21:52
An: [email protected]
Betreff: Thread-safe record mapper speed-ups

Hi,

after initially reporting a n^2 problem in the processRow method of =
RecordMappers in TORQUE-364, fixing it - only to then find our suspected =
concurrency troubles to be confirmed in TORQUE-372 - we can (hopefully) =
report a far more robust solution.

Looking into the SQL result stack we would propose to re-introduce a =
slightly modified MappingStrategy. The key insight to fixing the =
concurrent modification issue lies in doing so at the =
ResultsetSpliterator level. This ensures that every query gets its own =
MappingStrategy.

Doing this would also require two new methods for every RecordMapper to =
generate a fitting MappingStrategy and to process a row with a potential =
strategy. To keep backwards compatibility both would be defaulted in the =
interface to do nothing and forward to the old method respectively.

We have already implemented a test of this locally and can see similar =
performance to the old, but flawed, version and are sharing the patch =
here. (Hopefully this actually works...)

However, because the patch changes the methods the ResultsetSpliterator =
expects a RecordMapper to have (by calling a generateStrategy method to =
either do just that or return null) this would break backwards =
compatibility with old RecordMappers and we wanted to a feedback cycle =
early.

Best regards,
Max & Rene

------=_NextPart_000_0024_01DC3F62.582EA8B0
Content-Type: application/pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"

MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIX8zCCBDIw
ggMaoAMCAQICAQEwDQYJKoZIhvcNAQEFBQAwezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0
ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0
ZWQxITAfBgNVBAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0y
ODEyMzEyMzU5NTlaMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIx
EDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhB
QUEgQ2VydGlmaWNhdGUgU2VydmljZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+
QJ30buHqdoccTUVEjr5GyIMGncEq/hgfjuQC+vOrXVCKFjELmgbQxXAizUktVGPMtm5oRgtT6stM
JMC8ck7q8RWu9FSaEgrDerIzYOLaiVXzIljz3tzP74OGooyUT59o8piQRoQnx3a/48w1LIteB2Rl
gsBIsKiR+WGfdiBQqJHHZrXreGIDVvCKGhPqMaMeoJn9OPb2JzJYbwf1a7j7FCuvt6rM1mNfc4za
BZmoOKjLF3g2UazpnvR4Oo3PD9lC4pgMqy+fDgHe75+ZSfEt36x0TRuYtUfF5SnR+ZAYx2KcvoPH
Jns+iiXHwN2d5jVoECCdj9je0sOEnA1e6C/JAgMBAAGjgcAwgb0wHQYDVR0OBBYEFKARCiM+lvEH
7OKvKe+CpX/QMKS0MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MHsGA1UdHwR0MHIw
OKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0FBQUNlcnRpZmljYXRlU2VydmljZXMuY3Js
MDagNKAyhjBodHRwOi8vY3JsLmNvbW9kby5uZXQvQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww
DQYJKoZIhvcNAQEFBQADggEBAAhW/ALwm+j/pPrWe8ZEgM5PxMX2AFjMpra8FEloBHbo5u5d7AIP
YNaNUBhPJk4B4+awpe6/vHRUQb/9/BK4x09a9IlgBX9gtwVK8/bxwr/EuXSGti19a8zS80bdL8bg
asPDNAMsfZbdWsIOpwqZwQWLqwwv81w6z2w3VQmH3lNAbFjv/LarZW4E9hvcPOBaFcae2fFZSDAh
ZQNs7Okhc+ybA6HgN62gFRiP+roCzqcsqRATLNTlCCarIpdg+JBedNSimlO98qlo4KJuwtdssaMP
nr/raOdW8q7y4ys4OgmBtWuF174t7T8at7Jj4vViLILUagBBUPE5g5+V6TaWmG4wggWBMIIEaaAD
AgECAhA5ckQ6+SK3UdfTbBDdMTWVMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYD
VQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9k
byBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2VydmljZXMwHhcNMTkwMzEy
MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJz
ZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsx
LjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqG
SIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzO
iZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/Fp0YvVGONaan
ZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2VN3I5xI6Ta5MirdcmrS3ID3K
fyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVn
i+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB
1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b
/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+
/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYo
CAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo4HyMIHvMB8GA1UdIwQYMBaAFKARCiM+lvEH7OKv
Ke+CpX/QMKS0MB0GA1UdDgQWBBRTeb9aqitKz1SA4dibwJ3ysgNmyzAOBgNVHQ8BAf8EBAMCAYYw
DwYDVR0TAQH/BAUwAwEB/zARBgNVHSAECjAIMAYGBFUdIAAwQwYDVR0fBDwwOjA4oDagNIYyaHR0
cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUH
AQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEM
BQADggEBABiHUdx0IT2ciuAntzPQLszs8ObLXhHeIm+bdY6ecv7k1v6qH5yWLe8DSn6u9I1vcjxD
O8A/67jfXKqpxq7y/Njuo3tD9oY2fBTgzfT3P/7euLSK8JGW/v1DZH79zNIBoX19+BkZyUIrE79Y
i7qkomYEdoiRTgyJFM6iTckys7roFBq8cfFb8EELmAAKIgMQ5Qyx+c2SNxntO/HkOrb5RRMmda+7
qu8/e3c70sQCkT0ZANMXXDnbP3sYDUXNk4WWL13fWRZPP1G91UUYP+1KjugGYXQjFrUNUHMnREd/
EF2JKmuFMRTE6KlqTIC8anjPuH+OdnKZDJ3+15EIFqGjX5UwggbmMIIEzqADAgECAhAxAnDUNb6b
JJr4VtDh4oVJMA0GCSqGSIb3DQEBDAUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEpl
cnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29y
azEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0yMDAy
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
TlRQZXJzb25hbENBNC5jcmwweAYIKwYBBQUHAQEEbDBqMD0GCCsGAQUFBzAChjFodHRwOi8vR0VB
TlQuY3J0LnNlY3RpZ28uY29tL0dFQU5UUGVyc29uYWxDQTQuY3J0MCkGCCsGAQUFBzABhh1odHRw
Oi8vR0VBTlQub2NzcC5zZWN0aWdvLmNvbTAmBgNVHREEHzAdgRtnZW9yZy5rYWxsaWRpc0BmdS1i
ZXJsaW4uZGUwDQYJKoZIhvcNAQEMBQADggIBAE72vlTXl3kC+SnvpWr1tNsNCU0yVkLFyT682BrH
+j/pl84irJ6y4U0sG4NG+T4tT3FqhH8ZFhjuvdpRtTXy8pVtIa7bn4FwPzerGQu28LOOkr6jYclw
sLle/+yo4XrtqYmhK0beXBVvhAEaKOt+InCu/iph8C2sdK8aItMqifSlQFL57zbUJUMWhdhPlj4P
kWGg7uT9CpRF/G4qNCHdCXxrRL4ivd0qMyUpB8wy77FEuWakhVmp1O5ebzDA9NFAHDUgDrDs4tWu
4aIFgY7B/yTl6TpNR2CogGIGdOrz4AMOQim5Wuz7t+CbgJ2X8qDM8meDFVtoqYzcN6BwNoa6v35z
f++U2QDNmb4lTlAYVX9KT5hNpfHHQO6DXrjHeGwz316sAPHPb2Vg9XQVaBiMINMDKUvXYNpjzHZX
8EyE63y5bjQA9sNTzE9XlEUlQ7MZfnd0okFN8QNGNwSrUrY6chuDheSDZ7DDwHsI2r9egJX1LPWn
ZK4igs5F8cuc2I6alAEwwmoyxtci7fGI6KFqd0QOpvK3RsYwYE7ReApbCdfVCZ7dTVLqUbLYgTHV
wy6jgD/UDJ9S7Afb1TWp41JTmlxz+J0jol9b5LcnVOu1RI3tV3PJn0psuCo0xE2aLZb2FOb/73vr
/tqSZA8RZ7asdOQKKUHhW5sisj5p3P5MfAM/MYIEUzCCBE8CAQEwWzBGMQswCQYDVQQGEwJOTDEZ
MBcGA1UEChMQR0VBTlQgVmVyZW5pZ2luZzEcMBoGA1UEAxMTR0VBTlQgUGVyc29uYWwgQ0EgNAIR
AKz9jDg8z8qU6813veR1DOYwCQYFKw4DAhoFAKCCAc0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEH
ATAcBgkqhkiG9w0BCQUxDxcNMjUxMDE3MTAzNDEzWjAjBgkqhkiG9w0BCQQxFgQUqgGB3SPIsbv9
yEi+WvL8ky5o238wagYJKwYBBAGCNxAEMV0wWzBGMQswCQYDVQQGEwJOTDEZMBcGA1UEChMQR0VB
TlQgVmVyZW5pZ2luZzEcMBoGA1UEAxMTR0VBTlQgUGVyc29uYWwgQ0EgNAIRAKz9jDg8z8qU6813
veR1DOYwbAYLKoZIhvcNAQkQAgsxXaBbMEYxCzAJBgNVBAYTAk5MMRkwFwYDVQQKExBHRUFOVCBW
ZXJlbmlnaW5nMRwwGgYDVQQDExNHRUFOVCBQZXJzb25hbCBDQSA0AhEArP2MODzPypTrzXe95HUM
5jCBkwYJKoZIhvcNAQkPMYGFMIGCMAsGCWCGSAFlAwQBKjALBglghkgBZQMEARYwCgYIKoZIhvcN
AwcwCwYJYIZIAWUDBAECMA4GCCqGSIb3DQMCAgIAgDANBggqhkiG9w0DAgIBQDAHBgUrDgMCGjAL
BglghkgBZQMEAgMwCwYJYIZIAWUDBAICMAsGCWCGSAFlAwQCATANBgkqhkiG9w0BAQEFAASCAgDY
bN+naEMffeADxVkz6mPMiE5/xB57d0gFh19adOqRHltoPiMDj7GbaZ7PJEP+Szhuijm4q/MVSOyo
nKQWyW/5D/dKQCUVzzaOPoc+dQldW2d3tsVuV2YIeFL83dqSolIC9hQoec+rtPmi4/WkSUoWKShw
bPnLsHcGZTGb7Fk9hNTvN2P+TjrrSMvzbaY8N934L5IBGWI3YZu/XBAHwXYVEhbiUmp8fV2eOmfN
ARXErdBdJw1HHHdCCxBYn/PhUPo2m4KuF4iqLijWWOmBtjLRBOhDEikeDpAyjL5A101v+JcvzegN
YjPoNHCiEBGaopgiM85oyY47YOilK5aDlRRPnqdwB5wlZifk8vyWsW6WPh19AFKFqmn/sx1AR4e9
qb/6zWA/WF5NJDw0Nw+irENuAjV+39LZOea5BSaZ/dDtSc1XyWqV0/SJp01hWqPBMa4XkTnPl6PS
czCfDCpMaTNppjmdIan1OqAxz8lBkSmlwhUokkK+X+x2cLiyNEDMapB68bJCAxUrx/H1bbjRWMQD
O9i77JP9TvURoQ9DVP0pB+eMr6nH6DMUcY5uUrTVtRy0zVorcdbOKFipLSgh6+5y40PGJDgDcmnl
ZbZmewT0ynpGCdHVZVt1Kef/y1PeyEZPbbji6Vvh/cEFm8nW5C4+lRP87rfUKhkb10H/Z+c4lAAA
AAAAAA==

------=_NextPart_000_0024_01DC3F62.582EA8B0--