On Fri, 8 May 2026 19:19:28 GMT, Justin Lu <[email protected]> wrote:

>> Daniel Gredler has updated the pull request incrementally with one 
>> additional commit since the last revision:
>> 
>>   Update three comments which mention vectors
>
> src/java.base/share/classes/java/text/AttributedString.java line 354:
> 
>> 352:      * empty Map.
>> 353:      */
>> 354:     public void addAttributes(Map<? extends Attribute, ?> attributes,
> 
> Since we moved from `Vector` to `Map`, I think this is now susceptible to 
> `ConcurrentModificationException` when called at the same time that the 
> `AttributedCharacterIterator` is iterated. I don't think it matters though 
> since this method isn't specified to be thread safe and 
> `AttributedCharacterIterator` does not define a concurrent modification 
> policy, so I think it's OK.

I also think it's OK, but it does raise an interesting question. Per the 
comments at the top of `AttributedStringIterator`, these classes makes some 
effort to synchronize access to the `AttributedString`. However, there is a gap 
in this protection because 2 of the 3 mutating methods (both named 
`addAttribute`) synchronize by delegating to the private synchronized 
`addAttributeImpl` method, while the third method (`addAttributes`) does not go 
through this private method, and is missing any synchronization. I think it 
might be a good idea to open a separate bug to address this synchronization gap 
in `addAttributes`. Thoughts?

> test/micro/org/openjdk/bench/java/text/AttributedStringBench.java line 29:
> 
>> 27: import java.text.AttributedCharacterIterator;
>> 28: import java.text.AttributedString;
>> 29: import java.util.Map;
> 
> Looks unused.

Thanks, removed.

> test/micro/org/openjdk/bench/java/text/AttributedStringBench.java line 72:
> 
>> 70: 
>> 71:     @Benchmark
>> 72:     public void iterationWithNoAttributes(Blackhole blackhole) {
> 
> All the `iteration` tests are measuring missing key lookups, which is good to 
> measure but is also worst-case. Might be worth adding present key lookups for 
> transparency, so both cases are measured.

I've added two "key present" tests (`iteratePresentWithOneAttribute` and 
`iteratePresentWithThreeAttributes`), but the performance improvement actually 
looks larger than with missing keys.

Before PR changes:


Benchmark                                                                   
Mode  Cnt      Score     Error   Units
AttributedStringBench.createWithNoAttributes                                
avgt   15      0.003 ±   0.001   us/op
AttributedStringBench.createWithNoAttributes:gc.alloc.rate                  
avgt   15  11529.849 ± 397.065  MB/sec
AttributedStringBench.createWithNoAttributes:gc.alloc.rate.norm             
avgt   15     32.000 ±   0.001    B/op
AttributedStringBench.createWithNoAttributes:gc.count                       
avgt   15    224.000            counts
AttributedStringBench.createWithNoAttributes:gc.time                        
avgt   15    185.000                ms
AttributedStringBench.createWithOneAttribute                                
avgt   15      0.045 ±   0.001   us/op
AttributedStringBench.createWithOneAttribute:gc.alloc.rate                  
avgt   15   7993.680 ± 232.021  MB/sec
AttributedStringBench.createWithOneAttribute:gc.alloc.rate.norm             
avgt   15    376.000 ±   0.001    B/op
AttributedStringBench.createWithOneAttribute:gc.count                       
avgt   15    157.000            counts
AttributedStringBench.createWithOneAttribute:gc.time                        
avgt   15    133.000                ms
AttributedStringBench.createWithThreeAttributes                             
avgt   15      0.179 ±   0.001   us/op
AttributedStringBench.createWithThreeAttributes:gc.alloc.rate               
avgt   15   4059.315 ±  32.313  MB/sec
AttributedStringBench.createWithThreeAttributes:gc.alloc.rate.norm          
avgt   15    760.001 ±   0.001    B/op
AttributedStringBench.createWithThreeAttributes:gc.count                    
avgt   15    158.000            counts
AttributedStringBench.createWithThreeAttributes:gc.time                     
avgt   15    115.000                ms
AttributedStringBench.iterateMissingWithNoAttributes                        
avgt   15      0.064 ±   0.001   us/op
AttributedStringBench.iterateMissingWithNoAttributes:gc.alloc.rate          
avgt   15    713.782 ±  13.008  MB/sec
AttributedStringBench.iterateMissingWithNoAttributes:gc.alloc.rate.norm     
avgt   15     48.000 ±   0.001    B/op
AttributedStringBench.iterateMissingWithNoAttributes:gc.count               
avgt   15    113.000            counts
AttributedStringBench.iterateMissingWithNoAttributes:gc.time                
avgt   15     72.000                ms
AttributedStringBench.iterateMissingWithOneAttribute                        
avgt   15      0.309 ±   0.003   us/op
AttributedStringBench.iterateMissingWithOneAttribute:gc.alloc.rate          
avgt   15    148.133 ±   1.549  MB/sec
AttributedStringBench.iterateMissingWithOneAttribute:gc.alloc.rate.norm     
avgt   15     48.002 ±   0.001    B/op
AttributedStringBench.iterateMissingWithOneAttribute:gc.count               
avgt   15     69.000            counts
AttributedStringBench.iterateMissingWithOneAttribute:gc.time                
avgt   15     46.000                ms
AttributedStringBench.iterateMissingWithThreeAttributes                     
avgt   15      0.363 ±   0.002   us/op
AttributedStringBench.iterateMissingWithThreeAttributes:gc.alloc.rate       
avgt   15    125.929 ±   0.678  MB/sec
AttributedStringBench.iterateMissingWithThreeAttributes:gc.alloc.rate.norm  
avgt   15     48.003 ±   0.001    B/op
AttributedStringBench.iterateMissingWithThreeAttributes:gc.count            
avgt   15     60.000            counts
AttributedStringBench.iterateMissingWithThreeAttributes:gc.time             
avgt   15     46.000                ms
AttributedStringBench.iteratePresentWithOneAttribute                        
avgt   15      0.423 ±   0.002   us/op
AttributedStringBench.iteratePresentWithOneAttribute:gc.alloc.rate          
avgt   15    108.245 ±   0.562  MB/sec
AttributedStringBench.iteratePresentWithOneAttribute:gc.alloc.rate.norm     
avgt   15     48.003 ±   0.001    B/op
AttributedStringBench.iteratePresentWithOneAttribute:gc.count               
avgt   15     51.000            counts
AttributedStringBench.iteratePresentWithOneAttribute:gc.time                
avgt   15     40.000                ms
AttributedStringBench.iteratePresentWithThreeAttributes                     
avgt   15      0.452 ±   0.005   us/op
AttributedStringBench.iteratePresentWithThreeAttributes:gc.alloc.rate       
avgt   15    101.156 ±   1.154  MB/sec
AttributedStringBench.iteratePresentWithThreeAttributes:gc.alloc.rate.norm  
avgt   15     48.003 ±   0.001    B/op
AttributedStringBench.iteratePresentWithThreeAttributes:gc.count            
avgt   15     48.000            counts
AttributedStringBench.iteratePresentWithThreeAttributes:gc.time             
avgt   15     35.000                ms


After PR changes:


Benchmark                                                                   
Mode  Cnt      Score     Error   Units
AttributedStringBench.createWithNoAttributes                                
avgt   15      0.003 ±   0.001   us/op
AttributedStringBench.createWithNoAttributes:gc.alloc.rate                  
avgt   15  10291.391 ± 309.539  MB/sec
AttributedStringBench.createWithNoAttributes:gc.alloc.rate.norm             
avgt   15     32.000 ±   0.001    B/op
AttributedStringBench.createWithNoAttributes:gc.count                       
avgt   15    197.000            counts
AttributedStringBench.createWithNoAttributes:gc.time                        
avgt   15    186.000                ms
AttributedStringBench.createWithOneAttribute                                
avgt   15      0.033 ±   0.001   us/op
AttributedStringBench.createWithOneAttribute:gc.alloc.rate                  
avgt   15   8812.068 ± 269.579  MB/sec
AttributedStringBench.createWithOneAttribute:gc.alloc.rate.norm             
avgt   15    304.000 ±   0.001    B/op
AttributedStringBench.createWithOneAttribute:gc.count                       
avgt   15    169.000            counts
AttributedStringBench.createWithOneAttribute:gc.time                        
avgt   15    169.000                ms
AttributedStringBench.createWithThreeAttributes                             
avgt   15      0.147 ±   0.002   us/op
AttributedStringBench.createWithThreeAttributes:gc.alloc.rate               
avgt   15   4888.052 ±  66.603  MB/sec
AttributedStringBench.createWithThreeAttributes:gc.alloc.rate.norm          
avgt   15    752.001 ±   0.001    B/op
AttributedStringBench.createWithThreeAttributes:gc.count                    
avgt   15    151.000            counts
AttributedStringBench.createWithThreeAttributes:gc.time                     
avgt   15    120.000                ms
AttributedStringBench.iterateMissingWithNoAttributes                        
avgt   15      0.063 ±   0.002   us/op
AttributedStringBench.iterateMissingWithNoAttributes:gc.alloc.rate          
avgt   15    732.731 ±  27.288  MB/sec
AttributedStringBench.iterateMissingWithNoAttributes:gc.alloc.rate.norm     
avgt   15     48.000 ±   0.001    B/op
AttributedStringBench.iterateMissingWithNoAttributes:gc.count               
avgt   15    116.000            counts
AttributedStringBench.iterateMissingWithNoAttributes:gc.time                
avgt   15     76.000                ms
AttributedStringBench.iterateMissingWithOneAttribute                        
avgt   15      0.215 ±   0.003   us/op
AttributedStringBench.iterateMissingWithOneAttribute:gc.alloc.rate          
avgt   15    213.145 ±   2.898  MB/sec
AttributedStringBench.iterateMissingWithOneAttribute:gc.alloc.rate.norm     
avgt   15     48.002 ±   0.001    B/op
AttributedStringBench.iterateMissingWithOneAttribute:gc.count               
avgt   15    101.000            counts
AttributedStringBench.iterateMissingWithOneAttribute:gc.time                
avgt   15     61.000                ms
AttributedStringBench.iterateMissingWithThreeAttributes                     
avgt   15      0.229 ±   0.002   us/op
AttributedStringBench.iterateMissingWithThreeAttributes:gc.alloc.rate       
avgt   15    199.575 ±   2.030  MB/sec
AttributedStringBench.iterateMissingWithThreeAttributes:gc.alloc.rate.norm  
avgt   15     48.002 ±   0.001    B/op
AttributedStringBench.iterateMissingWithThreeAttributes:gc.count            
avgt   15     93.000            counts
AttributedStringBench.iterateMissingWithThreeAttributes:gc.time             
avgt   15     59.000                ms
AttributedStringBench.iteratePresentWithOneAttribute                        
avgt   15      0.251 ±   0.010   us/op
AttributedStringBench.iteratePresentWithOneAttribute:gc.alloc.rate          
avgt   15    182.271 ±   7.221  MB/sec
AttributedStringBench.iteratePresentWithOneAttribute:gc.alloc.rate.norm     
avgt   15     48.002 ±   0.001    B/op
AttributedStringBench.iteratePresentWithOneAttribute:gc.count               
avgt   15     85.000            counts
AttributedStringBench.iteratePresentWithOneAttribute:gc.time                
avgt   15     56.000                ms
AttributedStringBench.iteratePresentWithThreeAttributes                     
avgt   15      0.252 ±   0.003   us/op
AttributedStringBench.iteratePresentWithThreeAttributes:gc.alloc.rate       
avgt   15    181.707 ±   1.873  MB/sec
AttributedStringBench.iteratePresentWithThreeAttributes:gc.alloc.rate.norm  
avgt   15     48.002 ±   0.001    B/op
AttributedStringBench.iteratePresentWithThreeAttributes:gc.count            
avgt   15     85.000            counts
AttributedStringBench.iteratePresentWithThreeAttributes:gc.time             
avgt   15     54.000                ms

> test/micro/org/openjdk/bench/java/text/AttributedStringBench.java line 90:
> 
>> 88: 
>> 89:     @Benchmark
>> 90:     public void iterationWithFourAttributes(Blackhole blackhole) {
> 
> This might be better renamed, since `string3` is technically three attribute 
> _keys_.

Thanks, test names have been updated per unique key count.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/30402#discussion_r3220556185
PR Review Comment: https://git.openjdk.org/jdk/pull/30402#discussion_r3220555774
PR Review Comment: https://git.openjdk.org/jdk/pull/30402#discussion_r3220555099
PR Review Comment: https://git.openjdk.org/jdk/pull/30402#discussion_r3220552401

Reply via email to