Skip to content

Commit

Permalink
Fix performance regression: cache dostime to time_t conversion results.
Browse files Browse the repository at this point in the history
Closes issue #462
  • Loading branch information
dillof committed Oct 30, 2024
1 parent 46e309f commit c2854be
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 9 deletions.
10 changes: 10 additions & 0 deletions lib/zip_dirent.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ _zip_dirent_init(zip_dirent_t *de) {
de->cloned = 0;

de->crc_valid = true;
de->last_mod_mtime_valid = false;
de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
de->version_needed = 10; /* 1.0 */
de->bitflags = 0;
Expand Down Expand Up @@ -1263,3 +1264,12 @@ zip_dirent_check_consistency(zip_dirent_t *dirent) {
}
return 0;
}

time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
if (!de->last_mod_mtime_valid) {
de->last_mod_mtime = _zip_d2u_time(&de->last_mod);
de->last_mod_mtime_valid = true;
}

return de->last_mod_mtime;
}
20 changes: 15 additions & 5 deletions lib/zip_file_set_mtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@

#include "zipint.h"

ZIP_EXTERN int
zip_file_set_dostime(zip_t *za, zip_uint64_t idx, zip_uint16_t dtime, zip_uint16_t ddate, zip_flags_t flags) {
static int zip_file_set_time(zip_t *za, zip_uint64_t idx, zip_uint16_t dtime, zip_uint16_t ddate, zip_flags_t flags, time_t *mtime) {
zip_entry_t *e;

if (_zip_get_dirent(za, idx, 0, NULL) == NULL) {
Expand Down Expand Up @@ -66,18 +65,29 @@ zip_file_set_dostime(zip_t *za, zip_uint64_t idx, zip_uint16_t dtime, zip_uint16

e->changes->last_mod.time = dtime;
e->changes->last_mod.date = ddate;
if (mtime != NULL) {
e->changes->last_mod_mtime = *mtime;
e->changes->last_mod_mtime_valid = true;
}
else {
e->changes->last_mod_mtime_valid = false;
}
e->changes->changed |= ZIP_DIRENT_LAST_MOD;

return 0;
}

ZIP_EXTERN int
zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags) {
ZIP_EXTERN int zip_file_set_dostime(zip_t *za, zip_uint64_t idx, zip_uint16_t dtime, zip_uint16_t ddate, zip_flags_t flags) {
return zip_file_set_time(za, idx, dtime, ddate, flags, NULL);
}


ZIP_EXTERN int zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags) {
zip_dostime_t dostime;

if (_zip_u2d_time(mtime, &dostime, &za->error) < 0) {
return -1;
}

return zip_file_set_dostime(za, idx, dostime.time, dostime.date, flags);
return zip_file_set_time(za, idx, dostime.time, dostime.date, flags, &mtime);
}
1 change: 1 addition & 0 deletions lib/zip_new.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ _zip_new(zip_error_t *error) {
za->nopen_source = za->nopen_source_alloc = 0;
za->open_source = NULL;
za->progress = NULL;
za->torrent_mtime = 0;

return za;
}
11 changes: 7 additions & 4 deletions lib/zip_stat_index.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st)
}

if (entry->changes != NULL && entry->changes->changed & ZIP_DIRENT_LAST_MOD) {
st->mtime = _zip_d2u_time(&de->last_mod);
st->mtime = zip_dirent_get_last_mod_mtime(de);
st->valid |= ZIP_STAT_MTIME;
}
}
Expand All @@ -86,7 +86,7 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st)

st->crc = de->crc;
st->size = de->uncomp_size;
st->mtime = _zip_d2u_time(&de->last_mod);
st->mtime = zip_dirent_get_last_mod_mtime(de);
st->comp_size = de->comp_size;
st->comp_method = (zip_uint16_t)de->comp_method;
st->encryption_method = de->encryption_method;
Expand All @@ -97,9 +97,12 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st)
}

if ((za->ch_flags & ZIP_AFL_WANT_TORRENTZIP) && (flags & ZIP_FL_UNCHANGED) == 0) {
zip_dostime_t dostime = {0xbc00, 0x2198};
if (za->torrent_mtime == 0) {
zip_dostime_t dostime = {0xbc00, 0x2198};
za->torrent_mtime = _zip_d2u_time(&dostime);
}
st->comp_method = ZIP_CM_DEFLATE;
st->mtime = _zip_d2u_time(&dostime);
st->mtime = za->torrent_mtime;
st->valid |= ZIP_STAT_MTIME | ZIP_STAT_COMP_METHOD;
st->valid &= ~ZIP_STAT_COMP_SIZE;
}
Expand Down
5 changes: 5 additions & 0 deletions lib/zipint.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ struct zip {
zip_progress_t *progress; /* progress callback for zip_close() */

zip_uint32_t* write_crc; /* have _zip_write() compute CRC */
time_t torrent_mtime;
};

/* file in zip archive, part of API */
Expand Down Expand Up @@ -346,6 +347,7 @@ struct zip_dirent {
bool cloned; /* whether this instance is cloned, and thus shares non-changed strings */

bool crc_valid; /* if CRC is valid (sometimes not for encrypted archives) */
bool last_mod_mtime_valid;

zip_uint16_t version_madeby; /* (c) version of creator */
zip_uint16_t version_needed; /* (cl) version needed to extract */
Expand All @@ -366,6 +368,8 @@ struct zip_dirent {
zip_uint32_t compression_level; /* level of compression to use (never valid in orig) */
zip_uint16_t encryption_method; /* encryption method, computed from other fields */
char *password; /* file specific encryption password */

time_t last_mod_mtime; /* cached last_mod in Unix time format */
};

/* zip archive central directory */
Expand Down Expand Up @@ -553,6 +557,7 @@ int zip_dirent_check_consistency(zip_dirent_t *dirent);
zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *);
void _zip_dirent_free(zip_dirent_t *);
void _zip_dirent_finalize(zip_dirent_t *);
time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de);
void _zip_dirent_init(zip_dirent_t *);
bool _zip_dirent_needs_zip64(const zip_dirent_t *, zip_flags_t);
zip_dirent_t *_zip_dirent_new(void);
Expand Down

0 comments on commit c2854be

Please sign in to comment.