diff options
| author | Dmitry Antipov | 2013-10-08 10:40:09 +0400 |
|---|---|---|
| committer | Dmitry Antipov | 2013-10-08 10:40:09 +0400 |
| commit | f8498081911e4c1381c4bed5ac3b664ceca57d64 (patch) | |
| tree | d96b7bf86daef23ecae0f9239ef79bff81500490 /src | |
| parent | b7d5bd823c239a8ee3613abcc4e24fe290a673d0 (diff) | |
| download | emacs-f8498081911e4c1381c4bed5ac3b664ceca57d64.tar.gz emacs-f8498081911e4c1381c4bed5ac3b664ceca57d64.zip | |
Do not allocate huge temporary memory areas and objects while encoding
for file I/O, thus reducing an enormous memory usage for large buffers.
See http://lists.gnu.org/archive/html/emacs-devel/2013-10/msg00180.html.
* coding.h (struct coding_system): New member raw_destination.
* coding.c (setup_coding_system): Initialize it to zero.
(encode_coding_object): If raw_destination is set, do not create
dst_object. Add comment.
* fileio.c (toplevel): New constant E_WRITE_MAX.
(e_write): Do not encode more than E_WRITE_MAX characters per one loop
iteration. Use raw_destination if E_WRITE_MAX characters is encoded.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 13 | ||||
| -rw-r--r-- | src/coding.c | 6 | ||||
| -rw-r--r-- | src/coding.h | 4 | ||||
| -rw-r--r-- | src/fileio.c | 42 |
4 files changed, 57 insertions, 8 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 217a8b3d269..06733a2455f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,16 @@ | |||
| 1 | 2013-10-08 Dmitry Antipov <dmantipov@yandex.ru> | ||
| 2 | |||
| 3 | Do not allocate huge temporary memory areas and objects while encoding | ||
| 4 | for file I/O, thus reducing an enormous memory usage for large buffers. | ||
| 5 | See http://lists.gnu.org/archive/html/emacs-devel/2013-10/msg00180.html. | ||
| 6 | * coding.h (struct coding_system): New member raw_destination. | ||
| 7 | * coding.c (setup_coding_system): Initialize it to zero. | ||
| 8 | (encode_coding_object): If raw_destination is set, do not create | ||
| 9 | dst_object. Add comment. | ||
| 10 | * fileio.c (toplevel): New constant E_WRITE_MAX. | ||
| 11 | (e_write): Do not encode more than E_WRITE_MAX characters per one loop | ||
| 12 | iteration. Use raw_destination if E_WRITE_MAX characters is encoded. | ||
| 13 | |||
| 1 | 2013-10-08 Jan Djärv <jan.h.d@swipnet.se> | 14 | 2013-10-08 Jan Djärv <jan.h.d@swipnet.se> |
| 2 | 15 | ||
| 3 | * nsterm.m (windowDidExitFullScreen:): | 16 | * nsterm.m (windowDidExitFullScreen:): |
diff --git a/src/coding.c b/src/coding.c index c10fb375672..ac828a48683 100644 --- a/src/coding.c +++ b/src/coding.c | |||
| @@ -5761,6 +5761,7 @@ setup_coding_system (Lisp_Object coding_system, struct coding_system *coding) | |||
| 5761 | coding->safe_charsets = SDATA (val); | 5761 | coding->safe_charsets = SDATA (val); |
| 5762 | coding->default_char = XINT (CODING_ATTR_DEFAULT_CHAR (attrs)); | 5762 | coding->default_char = XINT (CODING_ATTR_DEFAULT_CHAR (attrs)); |
| 5763 | coding->carryover_bytes = 0; | 5763 | coding->carryover_bytes = 0; |
| 5764 | coding->raw_destination = 0; | ||
| 5764 | 5765 | ||
| 5765 | coding_type = CODING_ATTR_TYPE (attrs); | 5766 | coding_type = CODING_ATTR_TYPE (attrs); |
| 5766 | if (EQ (coding_type, Qundecided)) | 5767 | if (EQ (coding_type, Qundecided)) |
| @@ -8352,6 +8353,11 @@ encode_coding_object (struct coding_system *coding, | |||
| 8352 | { | 8353 | { |
| 8353 | if (BUFFERP (coding->dst_object)) | 8354 | if (BUFFERP (coding->dst_object)) |
| 8354 | coding->dst_object = Fbuffer_string (); | 8355 | coding->dst_object = Fbuffer_string (); |
| 8356 | else if (coding->raw_destination) | ||
| 8357 | /* This is used to avoid creating huge Lisp string. | ||
| 8358 | NOTE: caller who sets `raw_destination' is also | ||
| 8359 | responsible for freeing `destination' buffer. */ | ||
| 8360 | coding->dst_object = Qnil; | ||
| 8355 | else | 8361 | else |
| 8356 | { | 8362 | { |
| 8357 | coding->dst_object | 8363 | coding->dst_object |
diff --git a/src/coding.h b/src/coding.h index 2c01a05d197..0472bec99de 100644 --- a/src/coding.h +++ b/src/coding.h | |||
| @@ -512,6 +512,10 @@ struct coding_system | |||
| 512 | `charbuf', but at `src_object'. */ | 512 | `charbuf', but at `src_object'. */ |
| 513 | unsigned chars_at_source : 1; | 513 | unsigned chars_at_source : 1; |
| 514 | 514 | ||
| 515 | /* Nonzero if the result of conversion is in `destination' | ||
| 516 | buffer rather than in `dst_object'. */ | ||
| 517 | unsigned raw_destination : 1; | ||
| 518 | |||
| 515 | /* Set to 1 if charbuf contains an annotation. */ | 519 | /* Set to 1 if charbuf contains an annotation. */ |
| 516 | unsigned annotated : 1; | 520 | unsigned annotated : 1; |
| 517 | 521 | ||
diff --git a/src/fileio.c b/src/fileio.c index 1a2bdfa237c..c7125534e63 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -5263,6 +5263,10 @@ a_write (int desc, Lisp_Object string, ptrdiff_t pos, | |||
| 5263 | return 1; | 5263 | return 1; |
| 5264 | } | 5264 | } |
| 5265 | 5265 | ||
| 5266 | /* Maximum number of characters that the next | ||
| 5267 | function encodes per one loop iteration. */ | ||
| 5268 | |||
| 5269 | enum { E_WRITE_MAX = 8 * 1024 * 1024 }; | ||
| 5266 | 5270 | ||
| 5267 | /* Write text in the range START and END into descriptor DESC, | 5271 | /* Write text in the range START and END into descriptor DESC, |
| 5268 | encoding them with coding system CODING. If STRING is nil, START | 5272 | encoding them with coding system CODING. If STRING is nil, START |
| @@ -5289,9 +5293,16 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end, | |||
| 5289 | coding->src_multibyte = SCHARS (string) < SBYTES (string); | 5293 | coding->src_multibyte = SCHARS (string) < SBYTES (string); |
| 5290 | if (CODING_REQUIRE_ENCODING (coding)) | 5294 | if (CODING_REQUIRE_ENCODING (coding)) |
| 5291 | { | 5295 | { |
| 5292 | encode_coding_object (coding, string, | 5296 | ptrdiff_t nchars = min (end - start, E_WRITE_MAX); |
| 5293 | start, string_char_to_byte (string, start), | 5297 | |
| 5294 | end, string_char_to_byte (string, end), Qt); | 5298 | /* Avoid creating huge Lisp string in encode_coding_object. */ |
| 5299 | if (nchars == E_WRITE_MAX) | ||
| 5300 | coding->raw_destination = 1; | ||
| 5301 | |||
| 5302 | encode_coding_object | ||
| 5303 | (coding, string, start, string_char_to_byte (string, start), | ||
| 5304 | start + nchars, string_char_to_byte (string, start + nchars), | ||
| 5305 | Qt); | ||
| 5295 | } | 5306 | } |
| 5296 | else | 5307 | else |
| 5297 | { | 5308 | { |
| @@ -5308,8 +5319,15 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end, | |||
| 5308 | coding->src_multibyte = (end - start) < (end_byte - start_byte); | 5319 | coding->src_multibyte = (end - start) < (end_byte - start_byte); |
| 5309 | if (CODING_REQUIRE_ENCODING (coding)) | 5320 | if (CODING_REQUIRE_ENCODING (coding)) |
| 5310 | { | 5321 | { |
| 5311 | encode_coding_object (coding, Fcurrent_buffer (), | 5322 | ptrdiff_t nchars = min (end - start, E_WRITE_MAX); |
| 5312 | start, start_byte, end, end_byte, Qt); | 5323 | |
| 5324 | /* Likewise. */ | ||
| 5325 | if (nchars == E_WRITE_MAX) | ||
| 5326 | coding->raw_destination = 1; | ||
| 5327 | |||
| 5328 | encode_coding_object | ||
| 5329 | (coding, Fcurrent_buffer (), start, start_byte, | ||
| 5330 | start + nchars, CHAR_TO_BYTE (start + nchars), Qt); | ||
| 5313 | } | 5331 | } |
| 5314 | else | 5332 | else |
| 5315 | { | 5333 | { |
| @@ -5330,11 +5348,19 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end, | |||
| 5330 | 5348 | ||
| 5331 | if (coding->produced > 0) | 5349 | if (coding->produced > 0) |
| 5332 | { | 5350 | { |
| 5333 | char *buf = (STRINGP (coding->dst_object) | 5351 | char *buf = (coding->raw_destination ? (char *) coding->destination |
| 5334 | ? SSDATA (coding->dst_object) | 5352 | : (STRINGP (coding->dst_object) |
| 5335 | : (char *) BYTE_POS_ADDR (coding->dst_pos_byte)); | 5353 | ? SSDATA (coding->dst_object) |
| 5354 | : (char *) BYTE_POS_ADDR (coding->dst_pos_byte))); | ||
| 5336 | coding->produced -= emacs_write_sig (desc, buf, coding->produced); | 5355 | coding->produced -= emacs_write_sig (desc, buf, coding->produced); |
| 5337 | 5356 | ||
| 5357 | if (coding->raw_destination) | ||
| 5358 | { | ||
| 5359 | /* We're responsible for freeing this, see | ||
| 5360 | encode_coding_object to check why. */ | ||
| 5361 | xfree (coding->destination); | ||
| 5362 | coding->raw_destination = 0; | ||
| 5363 | } | ||
| 5338 | if (coding->produced) | 5364 | if (coding->produced) |
| 5339 | return 0; | 5365 | return 0; |
| 5340 | } | 5366 | } |