RFR(S): 8073497: Lazy conversion of ZipEntry time
Claes Redestad
claes.redestad at oracle.com
Thu Feb 26 00:17:39 UTC 2015
On 2015-02-23 16:41, Claes Redestad wrote:
> On 02/22/2015 10:16 PM, Xueming Shen wrote:
>> On 2/21/15 6:11 PM, Claes Redestad wrote:
>>> Hi Sherman,
>>>
>>> On 2015-02-21 19:49, Xueming Shen wrote:
>>>> Hi Claes,
>>>>
>>>> This change basically undo the "fix" for 4759491 [1], for better
>>>> performance ...
>>>>
>>>
>>> my intent was never to break current behavior, but that mistake can
>>> be rectified
>>> without missing out on the startup benefit of laziness:
>>>
>>> http://cr.openjdk.java.net/~redestad/jdk9/8073497/webrev.1/
>>>
>>> The time/mtime getters now use the mtime field if it exists, while
>>> the setters will
>>> update both fields. Since getLastModified already fell back to
>>> converting the
>>> time field rather than null if mtime wasn't set, setting mtime to a
>>> FileTime when
>>> calling setTime seems consistent and a cheap way to preserve the
>>> time precision.
>>>
>>> I guess a range check to skip the FileTime creation in setTime if
>>> the time is within
>>> the DOS time bounds would be a valid optimization, since that will
>>> typically
>>> always be the case.
>>
>>
>> It's a reasonable solution. I would assume we probably need that
>> "range check" optimization
>> to avoid setting the "mtime" field in normal use scenario. ZOS now
>> outputs the more accurate
>> "mtime" to the zip file using "extend timestamp" if it's not null
>> (the entry gets bigger). The
>> assumption now is that we only output the extended timestamp if the
>> time stamps set
>> via the setXYZTime() explicitly.
>>
>> ZOS.java
>>
>> ...
>> 432 int elenEXTT = 0; // info-zip extended
>> timestamp
>> 433 int flagEXTT = 0;
>> 434 if (e.mtime != null) {
>> 435 elenEXTT += 4;
>> 436 flagEXTT |= EXTT_FLAG_LMT;
>> 437 }
>> 438 if (e.atime != null) {
>> 439 elenEXTT += 4;
>> 440 flagEXTT |= EXTT_FLAG_LAT;
>> 441 }
>> 442 if (e.ctime != null) {
>> 443 elenEXTT += 4;
>> 444 flagEXTT |= EXTT_FLAT_CT;
>> 445 }
>> 446 if (flagEXTT != 0)
>> 447 elen += (elenEXTT + 5); // headid(2) + size(2) +
>> flag(1) + data
>> 448 writeShort(elen);
>> ...
>
> Here's my attempt to resolve this:
We could preserve precision by shifting the remaining milliseconds into
the dostime field,
since the DOS time will only use the 4 lower bytes:
http://cr.openjdk.java.net/~redestad/jdk9/8073497/webrev.4/
After I went through more extensive testing and verification I realized
that narrowing
dostime to an int and breaking this remainder hack out into a separate
field would be
possible without affecting ZipEntry footprint; arguably cleaner, but if
this version is
acceptable I would prefer not to.
Going this way preserves precision across the entire input range of
setTime, thus all tests
I could find pass with this version; I've also expanded the
TestExtraTime test to test both
far ancient, far future and near future times to verify precision is
preserved.
I backpedaled on the getLastModifiedTime optimization to set the mtime
field that Peter
suggested since it would have the side-effect that the extra time field
would be written
after a call to this getter, which would be a bit too unexpected.
Thanks!
/Claes
More information about the core-libs-dev
mailing list