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--