Re: TDE: Benchmarking WAL encryption approaches
Re: TDE: Benchmarking WAL encryption approaches
От:
Zsolt Parragi <zsolt.parragi@percona.com>
Дата:
> You did share a benchmark result for the normal transactions, but these > approaches can also affect the recovery time and replication, right? Might be > better to do as well. I didn't share them in my previous email because for two reasons: * I didn't run any read tests before writing that email * my expectation was that I'll have to do some optimizations before I get good read results, and I didn't want to delay sharing my initial benchmarks because of that. I've been only trying to measure reads for a few days now, so I do not want to say that I have final proper results, but based on what I see so far: that assumption was wrong, recovery/replication performance in quite good. My test approach is to: * generate a large amount of WAL without checkpoints * kill the server * take a snapshot, measure recovery speed, restore snapshot, repeat And then I do the same thing with replica catchup time, and I also tried to measure if I see any difference in replication lag. In all time measurements, I also logged user/sys times separately. This makes it clear that in some scenarios the overall time remains the same, but the user/sys ratio shifts. I repeated this with three workloads, one using bulk records (e.g. huge INSERT/COPY commands), another focusing on many small wal records (small OLTP writes) and a third one inserting mostly full page writes. All with the usual benchmarking precautions (dropping caches, setting cpu governor and other settings. without dropping caches I only see noise). Replication shows increased user CPU usage, which is more significant in the perpage version where the current implementantion decrypts on the primary/encrypts again on the replica. In the perrecord version, it only has to decrypt the wal records to apply them. But this doesn't show up in replication performance, I didn't see any increased replication lag compared to master in any of my tests so far. Replica catchup shows a ~20% increased user CPU time across all workloads, and the time impact varies across workloads, but there's no significant difference between perrecord and perpage. Full page writes are the worst with ~12% slower catchup time, bulk writes need 5% more time and for OLTP encryption is invisible. Recovery shows the same 20% CPU time, just with different overall additional time numbers: FP 13%, bulk 12%, OLTP same as not encrypted, only the USR CPU difference is there.
TDE: Benchmarking WAL encryption approaches
От:
Zsolt Parragi <zsolt.parragi@percona.com>
Дата:
Hello! During the TDE discussions at pgconf.dev, I promised some benchmarks about performance characteristics regarding different WAL encryption options, to provide solid data before deciding on an approach. I ended up benchmarking and optimizing different variants more than I initially planned, but now I have some conclusions that I think are interesting to share. I will only focus on two variants that make sense from a performance perspective, per page or per record AES-CTR-256. Other encryption modes / integrations all result in significantly decreased performance (or no visible benefit for added complexity). For example AES-GCM can be implemented in both versions, but because GCM is slower, the end result will be slower. I can also share numbers about GCM/XTS and other possibilities if people are interested, but for a "simple implementation in the core", I think it should be safe to assume that we want to go with CTR. So the two approaches are: 1. ctr_pagelevel: when we flush or read a wal page, we encrypt/decrypt it. This is simple, encrypts absolutely everything, but does everything in the critical section holding the WAL lock. 2. ctr_perrecord: encryption happens when we write a WAL record. Each record has to hold an additional IV, since at this point we can't rely on the LSN. It parallelizes encryption at the cost of increased complexity in the backend. Only the record data is encrypted, headers stay plaintext, which slightly simplifies command-line tools. I attached (one version) of both patches. All patches I used for testing are minimal: encryption is hardcoded, uses a hardcoded key baked into the source, there are no options to disable it or change settings, only the minimum required for performance testing and validation (making sure that we indeed encrypt the WAL). The naive implementation of perrecord is clearly slower than plaintext/pagelevel, however, after optimizing both versions, we can see the advantages of it: pagelevel performance degrades in scenarios with many clients and high WAL throughput, as the lock contention increases. In my tests, I focused on write performance. Read performance (recovery, replication) is a different topic, and my implementations for both could be optimized better - I didn't try to measure and improve them yet. I used 3 test scenarios: * sysbench oltp_read_write * sysbench oltp_write_only * A scenario in which each session repeats the following: 1. select 100 random IDs (locally, no SQL queries, as ids are serial and continuous) 2. execute an UPDATE SET c=c+1 WHERE id IN (id list); For testing, I used an AMD Threadripper 3970X (32 cores) and an Intel Optane P5800X for storage, which doesn't have the same throttling limitations as consumer SSDs, the tests weren't limited by IO. In the read_write scenario, there's no difference between the 2 encryption implementation and unencrypted master at all. There's some noise, but we can't notice the effect of encryption at all. In the write_only scenario, there's still no difference between master and ctr_perrecord, but ctr_pagelevel starts to fall behind at 32/64 threads. The difference disappears at 128 threads, as at that point master performance also degrades in my test setup. In the update_inlist scenario which increases WAL throughput more quickly, it already falls behind the other two at 8 threads, and remains there for all following runs: everywhere except in the single threaded case we can see a clear 20% performance drop. Similarly to the write_only scenario, there's no measurable difference between master and ctr_perrecord. This is in line with my earlier observations during less detailed benchmarking, that if we want to guarantee good WAL encryption performance, we have to go with per record encryption. The results also depend on the exact hardware used for the tests, scenario, and so on, but I think the general point of it is clear: the more work we do in the critical section, the worse the performance loss can be in certain configurations. Going with a choice that adds no additional workload there seems like a generally safer choice to me. Please share any feedback / improvement ideas for the patches, or different approaches we could test, I can continue benchmarking more scenarios / prototypes if anybody has ideas. Unless there's a different conclusion, I'll proceed with sharing a first prototype of a TDE proposal using the per record approach in the following weeks. I also attached the actual results of a comparison run as a CSV file.Hello! During the TDE discussions at pgconf.dev, I promised some benchmarks about performance characteristics regarding different WAL encryption options, to provide solid data before deciding on an approach. I ended up benchmarking and optimizing different variants a lot more than I initially planned, but now I have some conclusions that I think are interesting to share. I will only focus on two variants that make sense from a performance perspective, per page or per record AES-CTR-256. Other encryption modes / integrations all result in significantly decreased performance (or no visible benefit for added complexity). For example AES-GCM can be implemented in both versions, but because GCM is slower, the end result will be slower. I can also share numbers about GCM/XTR and other possibilities if people are interested, but for a "simple implementation in the core", I think it should be safe to assume that we want to go with CTR. So the two approaches are: 1. ctr_pagelevel: when we flush or read a wal page, we encrypt/decrypt it. This is simple, encrypts absolutely everything, but does everything in the critical section holding the WAL lock. 2. ctr_perrecord: encryption happens when we write a WAL record. Each record has to hold an additional IV, since at this point we can't rely on the LSN. Parallelizes encryption, at the cost of increasing complexity. Only the record data is encrypted, headers stay plaintext. I attached (one version) of both patches. All patches I used for testing are minimal: encryption is hardcoded, uses a hardcoded key baked into the source, there are no options to disable it or change settings, only the minimum required for performance testing and validation (making sure that we indeed encrypt the WAL). The naive implementation of perrecord is clearly slower than plaintext/pagelevel, however, after optimizing both versions, we can see the advantages of it: pagelevel performance degrades in scenarios with many clients and high WAL throughput, as the lock contention increases. In my tests, I focused on write performance. Read performance (recovery, replication) is a different topic, and my implementations for both could be optimized better - I didn't try to measure and improve them yet. I used 3 test scenarios: * sysbench oltp_read_write * sysbench oltp_write_only * A scenario in which each session repeats the following: 1. select 100 random IDs (locally, no SQL queries, as ids are serial and continuous) 2. execute an UPDATE SET c=c+1 WHERE id IN (id list); For testing, I used an AMD Threadripper 3970X (32 cores) and an Intel Optane P5800X for storage, which doesn't have the same throttling limitations as consumer SSDs, the tests weren't limited by IO. In the read_write scenario, there's no difference between the 2 encryption implementation and unencrypted master at all. There's some noise, but we can't notice the effect of encryption at all. In the write_only scenario, there's still no difference between master and ctr_perrecord, but ctr_pagelevel starts to fall behind at 32/64 threads. The difference disappears at 128 threads, as at that point master performance also degrades in my test setup. In the update_inlist scenario which increases WAL throughput more quickly, it already falls behind the other two at 8 threads, and remains there for all following runs: everywhere except in the single threaded case we can see a clear 20% performance drop. Similarly to the write_only scenario, there's no measurable difference between master and ctr_perrecord. This is in line with my earlier observations during less detailed benchmarking, that if we want to guarantee good WAL encryption performance, we have to go with per record encryption. The results also depend on the exact hardware used for the tests, scenario, and so on, but I think the general point of it is clear: the more work we do in the critical section, the worse the performance loss can be in certain configurations. Going with a choice that adds no additional workload there seems like a generally safer choice to me. Please share any feedback / improvement ideas for the patches, or different approaches we could test, I can continue benchmarking more scenarios / prototypes if anybody has ideas. Unless there's a different conclusion, I'll proceed with sharing a first prototype of a TDE proposal using the per record approach in the following weeks. I also attached the actual results of a comparison run as a CSV file.
RE: TDE: Benchmarking WAL encryption approaches
От:
"Hayato Kuroda (Fujitsu)" <kuroda.hayato@fujitsu.com>
Дата:
Dear Zsolt, Thanks for sharing the good benchmark! > Please share any feedback / improvement ideas for the patches, or > different approaches we could test, I can continue benchmarking more > scenarios / prototypes if anybody has ideas. Unless there's a > different conclusion, I'll proceed with sharing a first prototype of a > TDE proposal using the per record approach in the following weeks. You did share a benchmark result for the normal transactions, but these approaches can also affect the recovery time and replication, right? Might be better to do as well. Best regards, Hayato Kuroda FUJITSU LIMITED