Skip to content

Commit c2854be

Browse files
committed
Fix performance regression: cache dostime to time_t conversion results.
Closes issue #462
1 parent 46e309f commit c2854be

File tree

5 files changed

+38
-9
lines changed

5 files changed

+38
-9
lines changed

lib/zip_dirent.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ _zip_dirent_init(zip_dirent_t *de) {
282282
de->cloned = 0;
283283

284284
de->crc_valid = true;
285+
de->last_mod_mtime_valid = false;
285286
de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
286287
de->version_needed = 10; /* 1.0 */
287288
de->bitflags = 0;
@@ -1263,3 +1264,12 @@ zip_dirent_check_consistency(zip_dirent_t *dirent) {
12631264
}
12641265
return 0;
12651266
}
1267+
1268+
time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
1269+
if (!de->last_mod_mtime_valid) {
1270+
de->last_mod_mtime = _zip_d2u_time(&de->last_mod);
1271+
de->last_mod_mtime_valid = true;
1272+
}
1273+
1274+
return de->last_mod_mtime;
1275+
}

lib/zip_file_set_mtime.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@
3333

3434
#include "zipint.h"
3535

36-
ZIP_EXTERN int
37-
zip_file_set_dostime(zip_t *za, zip_uint64_t idx, zip_uint16_t dtime, zip_uint16_t ddate, zip_flags_t flags) {
36+
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) {
3837
zip_entry_t *e;
3938

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

6766
e->changes->last_mod.time = dtime;
6867
e->changes->last_mod.date = ddate;
68+
if (mtime != NULL) {
69+
e->changes->last_mod_mtime = *mtime;
70+
e->changes->last_mod_mtime_valid = true;
71+
}
72+
else {
73+
e->changes->last_mod_mtime_valid = false;
74+
}
6975
e->changes->changed |= ZIP_DIRENT_LAST_MOD;
7076

7177
return 0;
7278
}
7379

74-
ZIP_EXTERN int
75-
zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags) {
80+
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) {
81+
return zip_file_set_time(za, idx, dtime, ddate, flags, NULL);
82+
}
83+
84+
85+
ZIP_EXTERN int zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags) {
7686
zip_dostime_t dostime;
7787

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

82-
return zip_file_set_dostime(za, idx, dostime.time, dostime.date, flags);
92+
return zip_file_set_time(za, idx, dostime.time, dostime.date, flags, &mtime);
8393
}

lib/zip_new.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ _zip_new(zip_error_t *error) {
6868
za->nopen_source = za->nopen_source_alloc = 0;
6969
za->open_source = NULL;
7070
za->progress = NULL;
71+
za->torrent_mtime = 0;
7172

7273
return za;
7374
}

lib/zip_stat_index.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st)
7777
}
7878

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

8787
st->crc = de->crc;
8888
st->size = de->uncomp_size;
89-
st->mtime = _zip_d2u_time(&de->last_mod);
89+
st->mtime = zip_dirent_get_last_mod_mtime(de);
9090
st->comp_size = de->comp_size;
9191
st->comp_method = (zip_uint16_t)de->comp_method;
9292
st->encryption_method = de->encryption_method;
@@ -97,9 +97,12 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st)
9797
}
9898

9999
if ((za->ch_flags & ZIP_AFL_WANT_TORRENTZIP) && (flags & ZIP_FL_UNCHANGED) == 0) {
100-
zip_dostime_t dostime = {0xbc00, 0x2198};
100+
if (za->torrent_mtime == 0) {
101+
zip_dostime_t dostime = {0xbc00, 0x2198};
102+
za->torrent_mtime = _zip_d2u_time(&dostime);
103+
}
101104
st->comp_method = ZIP_CM_DEFLATE;
102-
st->mtime = _zip_d2u_time(&dostime);
105+
st->mtime = za->torrent_mtime;
103106
st->valid |= ZIP_STAT_MTIME | ZIP_STAT_COMP_METHOD;
104107
st->valid &= ~ZIP_STAT_COMP_SIZE;
105108
}

lib/zipint.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ struct zip {
314314
zip_progress_t *progress; /* progress callback for zip_close() */
315315

316316
zip_uint32_t* write_crc; /* have _zip_write() compute CRC */
317+
time_t torrent_mtime;
317318
};
318319

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

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

350352
zip_uint16_t version_madeby; /* (c) version of creator */
351353
zip_uint16_t version_needed; /* (cl) version needed to extract */
@@ -366,6 +368,8 @@ struct zip_dirent {
366368
zip_uint32_t compression_level; /* level of compression to use (never valid in orig) */
367369
zip_uint16_t encryption_method; /* encryption method, computed from other fields */
368370
char *password; /* file specific encryption password */
371+
372+
time_t last_mod_mtime; /* cached last_mod in Unix time format */
369373
};
370374

371375
/* zip archive central directory */
@@ -553,6 +557,7 @@ int zip_dirent_check_consistency(zip_dirent_t *dirent);
553557
zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *);
554558
void _zip_dirent_free(zip_dirent_t *);
555559
void _zip_dirent_finalize(zip_dirent_t *);
560+
time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de);
556561
void _zip_dirent_init(zip_dirent_t *);
557562
bool _zip_dirent_needs_zip64(const zip_dirent_t *, zip_flags_t);
558563
zip_dirent_t *_zip_dirent_new(void);

0 commit comments

Comments
 (0)