Skip to content

Commit 92d4479

Browse files
committed
Further improve memory usage for CSV rendering
- Dump sheets to a json var, delete the sheets before rendering. - Delete reader when exception happens - Update error message for TableTooBigError - Update comment and log for garbage collection
1 parent 5838fd6 commit 92d4479

File tree

2 files changed

+14
-8
lines changed

2 files changed

+14
-8
lines changed

mfr/extensions/tabular/libs/stdlib_tools.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ def csv_stdlib(fp):
1919
dialect = csv.excel
2020
else:
2121
_set_dialect_quote_attrs(dialect, data)
22-
2322
del data
23+
2424
reader = csv.DictReader(fp, dialect=dialect)
2525
columns = []
2626
# update the reader field names to avoid duplicate column names when performing row extraction
@@ -41,6 +41,7 @@ def csv_stdlib(fp):
4141
try:
4242
rows = [row for row in reader]
4343
except csv.Error as e:
44+
del reader
4445
if any("field larger than field limit" in errorMsg for errorMsg in e.args):
4546
raise TabularRendererError(
4647
'This file contains a field too large to render. '
@@ -51,10 +52,9 @@ def csv_stdlib(fp):
5152
else:
5253
raise TabularRendererError('csv.Error: {}'.format(e), extension='csv') from e
5354

55+
del reader
5456
if not columns and not rows:
5557
raise EmptyTableError('Table empty or corrupt.', extension='csv')
56-
57-
del reader
5858
return {'Sheet 1': (columns, rows)}
5959

6060

mfr/extensions/tabular/render.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,27 @@ def render(self):
3333
with open(self.file_path, errors='replace') as fp:
3434
sheets, size, nbr_rows, nbr_cols = self._render_grid(fp, self.metadata.ext)
3535

36-
# Force GC
37-
gc.collect()
38-
3936
if sheets and size:
37+
json_sheets = json.dumps(sheets)
38+
del sheets
39+
# Forcing garbage collection accelerates the memory free/release process with a small
40+
# but acceptable cost in performance
41+
nbr_objs = gc.collect()
42+
logger.debug('Number of unreachable objects collected: {}'.format(nbr_objs))
4043
return self.TEMPLATE.render(
4144
base=self.assets_url,
4245
width=settings.TABLE_WIDTH,
4346
height=settings.TABLE_HEIGHT,
44-
sheets=json.dumps(sheets),
47+
sheets=json_sheets,
4548
options=json.dumps(size),
4649
)
4750

51+
nbr_objs = gc.collect()
52+
logger.debug('Number of unreachable objects collected: {}'.format(nbr_objs))
4853
assert nbr_rows and nbr_cols
4954
raise exceptions.TableTooBigError(
50-
'Table is too large to render.',
55+
'Table with more than {} rows or columns are not rendered. Please download the file to '
56+
'view.'.format(settings.MAX_SIZE),
5157
extension=self.metadata.ext,
5258
nbr_cols=nbr_cols,
5359
nbr_rows=nbr_rows

0 commit comments

Comments
 (0)