From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Newsgroups: gmane.emacs.bugs Subject: bug#63225: Compiling regexp patterns (and REGEXP_CACHE_SIZE in search.c) Date: Tue, 2 May 2023 16:33:58 +0200 Message-ID: <63882A45-BD02-40D5-92FA-70175267BA3B@acm.org> References: <87ttwvgp4s.fsf@localhost> Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.15\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_ECFA48ED-6129-4805-92CD-2E035048FD18" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="13302"; mail-complaints-to="usenet@ciao.gmane.io" Cc: 63225@debbugs.gnu.org To: Ihor Radchenko Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue May 02 16:35:30 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ptr6H-0003FX-78 for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 02 May 2023 16:35:29 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ptr5z-0001bi-2W; Tue, 02 May 2023 10:35:11 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ptr5u-0001YB-9G for bug-gnu-emacs@gnu.org; Tue, 02 May 2023 10:35:09 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ptr5q-00068J-Nq for bug-gnu-emacs@gnu.org; Tue, 02 May 2023 10:35:05 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1ptr5q-00063r-95 for bug-gnu-emacs@gnu.org; Tue, 02 May 2023 10:35:02 -0400 X-Loop: help-debbugs@gnu.org In-Reply-To: <87ttwvgp4s.fsf@localhost> Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 02 May 2023 14:35:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 63225 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 63225-submit@debbugs.gnu.org id=B63225.168303805523236 (code B ref 63225); Tue, 02 May 2023 14:35:02 +0000 Original-Received: (at 63225) by debbugs.gnu.org; 2 May 2023 14:34:15 +0000 Original-Received: from localhost ([127.0.0.1]:44785 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ptr54-00062i-T6 for submit@debbugs.gnu.org; Tue, 02 May 2023 10:34:15 -0400 Original-Received: from mail1474c50.megamailservers.eu ([91.136.14.74]:36640 helo=mail102c50.megamailservers.eu) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ptr4y-000624-Ki for 63225@debbugs.gnu.org; Tue, 02 May 2023 10:34:13 -0400 X-Authenticated-User: mattiase@bredband.net DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=megamailservers.eu; s=maildub; t=1683038041; bh=lIcDI6tSrqXq9IyTIq4PYfCwpIWit9bhG9xNPUBWWrQ=; h=From:Subject:Date:Cc:To:From; b=FAStFQE+lXH51c7Hd1oFvF2P0uvUQT4Jyfob1jXCRKs749xQLiXihZTLkFRskbyq3 PfDPG3LvlhNzeLXJZ6BHSw0UVZwbb3HDiodWq2IaFOtUCU+km7s5BbYFhWpq7CrFFK dcMDzg3ANEHQaSPiKchudpx9EvqEtZ4KHuVkIqh4= Feedback-ID: mattiase@acm.or Original-Received: from smtpclient.apple (c188-150-165-235.bredband.tele2.se [188.150.165.235]) (authenticated bits=0) by mail102c50.megamailservers.eu (8.14.9/8.13.1) with ESMTP id 342EXwXY006204; Tue, 2 May 2023 14:34:00 +0000 X-Mailer: Apple Mail (2.3654.120.0.1.15) X-VADE-SPAMSTATE: clean X-VADE-SPAMSCORE: 0 X-VADE-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedvhedrfedviedgjeekucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecujffquffvqffrkfetpdfqfgfvpdfgpfggqdevhedtnecuuegrihhlohhuthemuceftddunecunecujfgurhephfgtggfukfffvefvofesmhdtmherhhdtvdenucfhrhhomhepofgrthhtihgrshcugfhnghguvghgnohrugcuoehmrghtthhirghsvgesrggtmhdrohhrgheqnecuggftrfgrthhtvghrnhepgefftedvuddvfeffiefggfeglefhheeiudffueegieetkefgueeiuedvkeeitddunecukfhppedukeekrdduhedtrdduieehrddvfeehnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehinhgvthepudekkedrudehtddrudeihedrvdefhedphhgvlhhopehsmhhtphgtlhhivghnthdrrghpphhlvgdpmhgrihhlfhhrohhmpehmrghtthhirghsvgesrggtmhdrohhrghdpnhgspghrtghpthhtohepvddprhgtphhtthhopeihrghnthgrrhelvdesphhoshhtvghordhnvghtpdhrtghpthhtohepieefvddvheesuggvsggsuhhgshdrghhnuhdrohhrgh X-Origin-Country: SE X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:260932 Archived-At: --Apple-Mail=_ECFA48ED-6129-4805-92CD-2E035048FD18 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii > I was able to get rid of the regex compilation-related slowdown simply > by increasing REGEXP_CACHE_SIZE 10x (see the attached patch). Indeed it sounds like you are suffering from regexp cache thrashing. I'm = attaching two patches: one to measure the cache miss rate, and one that = allows the regexp cache size to be changed at run time. That should let you find the working set size for your application, and = ideally come up with a way to reduce it. Perhaps you could give us an = idea of what these regexps look like and how they are used? > Does anyone know if there are potential side effects of this increase = if > applied across Emacs? Or, alternatively, may Emacs provide an ability = to > store compiled regexp patterns from Elisp (similar to what > `treesit-query-compile' does)? I don't think it's necessarily a good idea to increase the size to 200 = right away because of the linear cache lookup mechanism. Allowing the = size to be changed at run time is probably less controversial (but = arguably just as much of a crutch). Introducing regexp objects that could store compiled regexps and be used = instead of strings would be quite some work but probably worthwhile. --Apple-Mail=_ECFA48ED-6129-4805-92CD-2E035048FD18 Content-Disposition: attachment; filename=0001-Add-regexp-cache-hit-miss-counters.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0001-Add-regexp-cache-hit-miss-counters.patch" Content-Transfer-Encoding: quoted-printable =46rom=20f1246af3cc558bd38527f320964bb0e0a1e74de0=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= =0ADate:=20Sat,=207=20Nov=202020=2017:00:53=20+0100=0A= Subject:=20[PATCH=201/2]=20Add=20regexp=20cache=20hit/miss=20counters=0A=0A= ---=0A=20src/search.c=20|=2013=20++++++++++++-=0A=201=20file=20changed,=20= 12=20insertions(+),=201=20deletion(-)=0A=0Adiff=20--git=20a/src/search.c=20= b/src/search.c=0Aindex=200bb52c03eef..6f71f3d16c1=20100644=0A---=20= a/src/search.c=0A+++=20b/src/search.c=0A@@=20-220,7=20+220,10=20@@=20= compile_pattern=20(Lisp_Object=20pattern,=20struct=20re_registers=20= *regp,=0A=20=09=20=20=20=20=20=20||=20EQ=20(cp->syntax_table,=20BVAR=20= (current_buffer,=20syntax_table)))=0A=20=09=20=20&&=20!NILP=20(Fequal=20= (cp->f_whitespace_regexp,=20Vsearch_spaces_regexp))=0A=20=09=20=20&&=20= cp->buf.charset_unibyte=20=3D=3D=20charset_unibyte)=0A-=09break;=0A+=20=20= =20=20=20=20=20=20{=0A+=20=20=20=20=20=20=20=20=20=20regexp_cache_hit++;=0A= +=20=20=20=20=20=20=20=20=20=20break;=0A+=20=20=20=20=20=20=20=20}=0A=20=0A= =20=20=20=20=20=20=20/*=20If=20we're=20at=20the=20end=20of=20the=20= cache,=20compile=20into=20the=20last=0A=20=09=20(least=20recently=20= used)=20non-busy=20cell=20in=20the=20cache.=20=20*/=0A@@=20-232,6=20= +235,7=20@@=20compile_pattern=20(Lisp_Object=20pattern,=20struct=20= re_registers=20*regp,=0A=20=20=20=20=20=20=20=20=20=20=20cp=20=3D=20= *cpp;=0A=20=09compile_it:=0A=20=20=20=20=20=20=20=20=20=20=20eassert=20= (!cp->busy);=0A+=20=20=20=20=20=20=20=20=20=20regexp_cache_miss++;=0A=20=09= =20=20compile_pattern_1=20(cp,=20pattern,=20translate,=20posix);=0A=20=09= =20=20break;=0A=20=09}=0A@@=20-3431,6=20+3435,13=20@@=20syms_of_search=20= (void)=0A=20is=20to=20bind=20it=20with=20`let'=20around=20a=20small=20= expression.=20=20*/);=0A=20=20=20Vinhibit_changing_match_data=20=3D=20= Qnil;=0A=20=0A+=20=20DEFVAR_INT("regexp-cache-hit",=20regexp_cache_hit,=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20doc:=20/*=20Regexp=20cache=20hit=20= count.=20=20Internal=20use=20only.=20*/);=0A+=20=20regexp_cache_hit=20=3D=20= 0;=0A+=20=20DEFVAR_INT("regexp-cache-miss",=20regexp_cache_miss,=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20doc:=20/*=20Regexp=20cache=20miss=20= count.=20=20Internal=20use=20only.=20*/);=0A+=20=20regexp_cache_miss=20=3D= =200;=0A+=0A=20=20=20defsubr=20(&Slooking_at);=0A=20=20=20defsubr=20= (&Sposix_looking_at);=0A=20=20=20defsubr=20(&Sstring_match);=0A--=20=0A= 2.32.0=20(Apple=20Git-132)=0A=0A= --Apple-Mail=_ECFA48ED-6129-4805-92CD-2E035048FD18 Content-Disposition: attachment; filename=0002-Make-regexp-cache-size-adjustable-at-run-time.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0002-Make-regexp-cache-size-adjustable-at-run-time.patch" Content-Transfer-Encoding: quoted-printable =46rom=2081461c26b7e40e7c27804407571199a5247815d4=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= =0ADate:=20Tue,=202=20May=202023=2016:23:11=20+0200=0A= Subject:=20[PATCH=202/2]=20Make=20regexp=20cache=20size=20adjustable=20= at=20run-time=0A=0A---=0A=20src/alloc.c=20=20|=20=202=20++=0A=20= src/lisp.h=20=20=20|=20=201=20+=0A=20src/search.c=20|=2085=20= +++++++++++++++++++++++++++++++++++++++-------------=0A=203=20files=20= changed,=2067=20insertions(+),=2021=20deletions(-)=0A=0Adiff=20--git=20= a/src/alloc.c=20b/src/alloc.c=0Aindex=20d09fc41dec6..0b11b5469a9=20= 100644=0A---=20a/src/alloc.c=0A+++=20b/src/alloc.c=0A@@=20-6451,6=20= +6451,8=20@@=20garbage_collect=20(void)=0A=20=20=20mark_terminals=20();=0A= =20=20=20mark_kboards=20();=0A=20=20=20mark_threads=20();=0A+=20=20= mark_regexp_cache=20();=0A+=0A=20#ifdef=20HAVE_PGTK=0A=20=20=20= mark_pgtkterm=20();=0A=20#endif=0Adiff=20--git=20a/src/lisp.h=20= b/src/lisp.h=0Aindex=20ab66109d5df..8b2beadefd6=20100644=0A---=20= a/src/lisp.h=0A+++=20b/src/lisp.h=0A@@=20-4745,6=20+4745,7=20@@=20= XMODULE_FUNCTION=20(Lisp_Object=20o)=0A=20extern=20void=20syms_of_fileio=20= (void);=0A=20=0A=20/*=20Defined=20in=20search.c.=20=20*/=0A+extern=20= void=20mark_regexp_cache=20(void);=0A=20extern=20void=20= shrink_regexp_cache=20(void);=0A=20extern=20void=20restore_search_regs=20= (void);=0A=20extern=20void=20update_search_regs=20(ptrdiff_t=20oldstart,=0A= diff=20--git=20a/src/search.c=20b/src/search.c=0Aindex=20= 6f71f3d16c1..c454d5e1ca9=20100644=0A---=20a/src/search.c=0A+++=20= b/src/search.c=0A@@=20-34,7=20+34,7=20@@=20Copyright=20(C)=201985-1987,=20= 1993-1994,=201997-1999,=202001-2023=20Free=20Software=0A=20=0A=20= #include=20"regex-emacs.h"=0A=20=0A-#define=20REGEXP_CACHE_SIZE=2020=0A= +#define=20DEFAULT_REGEXP_CACHE_SIZE=2020=0A=20=0A=20/*=20If=20the=20= regexp=20is=20non-nil,=20then=20the=20buffer=20contains=20the=20compiled=20= form=0A=20=20=20=20of=20that=20regexp,=20suitable=20for=20searching.=20=20= */=0A@@=20-55,7=20+55,9=20@@=20#define=20REGEXP_CACHE_SIZE=2020=0A=20};=0A= =20=0A=20/*=20The=20instances=20of=20that=20struct.=20=20*/=0A-static=20= struct=20regexp_cache=20searchbufs[REGEXP_CACHE_SIZE];=0A+static=20= struct=20regexp_cache=20*searchbufs;=0A+/*=20Allocated=20size=20of=20= searchbufs=20array,=20in=20elements.=20=20*/=0A+static=20int=20= regexp_cache_size=20=3D=200;=0A=20=0A=20/*=20The=20head=20of=20the=20= linked=20list;=20points=20to=20the=20most=20recently=20used=20buffer.=20=20= */=0A=20static=20struct=20regexp_cache=20*searchbuf_head;=0A@@=20-158,7=20= +160,7=20@@=20clear_regexp_cache=20(void)=0A=20{=0A=20=20=20int=20i;=0A=20= =0A-=20=20for=20(i=20=3D=200;=20i=20<=20REGEXP_CACHE_SIZE;=20++i)=0A+=20=20= for=20(i=20=3D=200;=20i=20<=20regexp_cache_size;=20++i)=0A=20=20=20=20=20= /*=20It's=20tempting=20to=20compare=20with=20the=20syntax-table=20we've=20= actually=20changed,=0A=20=20=20=20=20=20=20=20but=20it's=20not=20= sufficient=20because=20char-table=20inheritance=20means=20that=0A=20=20=20= =20=20=20=20=20modifying=20one=20syntax-table=20can=20change=20others=20= at=20the=20same=20time.=20=20*/=0A@@=20-3376,18=20+3378,68=20@@=20DEFUN=20= ("newline-cache-check",=20Fnewline_cache_check,=20Snewline_cache_check,=0A= =20}=0A=20=0C=0A=20=0A-static=20void=20syms_of_search_for_pdumper=20= (void);=0A+static=20void=0A+set_regexp_cache_size=20(int=20n)=0A+{=0A+=20= =20for=20(int=20i=20=3D=200;=20i=20<=20regexp_cache_size;=20i++)=0A+=20=20= =20=20xfree=20(searchbufs[i].buf.buffer);=0A+=0A+=20=20size_t=20bytes=20= =3D=20n=20*=20sizeof=20*searchbufs;=0A+=20=20searchbufs=20=3D=20xrealloc=20= (searchbufs,=20bytes);=0A+=20=20memset=20(searchbufs,=200,=20bytes);=0A+=20= =20regexp_cache_size=20=3D=20n;=0A+=0A+=20=20for=20(int=20i=20=3D=200;=20= i=20<=20n;=20i++)=0A+=20=20=20=20{=0A+=20=20=20=20=20=20= searchbufs[i].buf.allocated=20=3D=20100;=0A+=20=20=20=20=20=20= searchbufs[i].buf.buffer=20=3D=20xmalloc=20(100);=0A+=20=20=20=20=20=20= searchbufs[i].buf.fastmap=20=3D=20searchbufs[i].fastmap;=0A+=20=20=20=20=20= =20searchbufs[i].regexp=20=3D=20Qnil;=0A+=20=20=20=20=20=20= searchbufs[i].f_whitespace_regexp=20=3D=20Qnil;=0A+=20=20=20=20=20=20= searchbufs[i].busy=20=3D=20false;=0A+=20=20=20=20=20=20= searchbufs[i].syntax_table=20=3D=20Qnil;=0A+=20=20=20=20=20=20= searchbufs[i].next=20=3D=20(i=20=3D=3D=20regexp_cache_size-1=20?=200=20:=20= &searchbufs[i+1]);=0A+=20=20=20=20}=0A+=20=20searchbuf_head=20=3D=20= &searchbufs[0];=0A+}=0A+=0A+DEFUN=20("regexp-cache-size",=20= Fregexp_cache_size,=20Sregexp_cache_size,=0A+=20=20=20=20=20=20=200,=20= 0,=200,=0A+=20=20=20=20=20=20=20doc:=20/*=20Current=20regexp=20cache=20= size.=20=20Internal=20use=20only.=20=20*/)=0A+=20=20(void)=0A+{=0A+=20=20= return=20make_int=20(regexp_cache_size);=0A+}=0A+=0A+DEFUN=20= ("set-regexp-cache-size",=20Fset_regexp_cache_size,=20= Sset_regexp_cache_size,=0A+=20=20=20=20=20=20=201,=201,=200,=0A+=20=20=20= =20=20=20=20doc:=20/*=20Set=20the=20regexp=20cache=20size=20to=20N=20= elements.=20=20Internal=20use=20only.=20=20*/)=0A+=20=20(Lisp_Object=20= n)=0A+{=0A+=20=20CHECK_FIXNUM=20(n);=0A+=20=20EMACS_INT=20nelems=20=3D=20= XFIXNUM=20(n);=0A+=20=20if=20(nelems=20<=3D=200)=0A+=20=20=20=20error=20= ("regexp=20cache=20size=20must=20be=20positive");=0A+=20=20= set_regexp_cache_size=20(nelems);=0A+=20=20return=20Qnil;=0A+}=0A=20=0A=20= void=0A-syms_of_search=20(void)=0A+mark_regexp_cache=20(void)=0A=20{=0A-=20= =20for=20(int=20i=20=3D=200;=20i=20<=20REGEXP_CACHE_SIZE;=20++i)=0A+=20=20= for=20(int=20i=20=3D=200;=20i=20<=20regexp_cache_size;=20++i)=0A=20=20=20= =20=20{=0A-=20=20=20=20=20=20staticpro=20(&searchbufs[i].regexp);=0A-=20=20= =20=20=20=20staticpro=20(&searchbufs[i].f_whitespace_regexp);=0A-=20=20=20= =20=20=20staticpro=20(&searchbufs[i].syntax_table);=0A+=20=20=20=20=20=20= mark_object=20(searchbufs[i].regexp);=0A+=20=20=20=20=20=20mark_object=20= (searchbufs[i].f_whitespace_regexp);=0A+=20=20=20=20=20=20mark_object=20= (searchbufs[i].syntax_table);=0A=20=20=20=20=20}=0A+}=0A=20=0A+static=20= void=20syms_of_search_for_pdumper=20(void);=0A+=0A+void=0A= +syms_of_search=20(void)=0A+{=0A=20=20=20/*=20Error=20condition=20used=20= for=20failing=20searches.=20=20*/=0A=20=20=20DEFSYM=20(Qsearch_failed,=20= "search-failed");=0A=20=0A@@=20-3460,6=20+3512,8=20@@=20syms_of_search=20= (void)=0A=20=20=20defsubr=20(&Smatch_data__translate);=0A=20=20=20= defsubr=20(&Sregexp_quote);=0A=20=20=20defsubr=20= (&Snewline_cache_check);=0A+=20=20defsubr=20(&Sregexp_cache_size);=0A+=20= =20defsubr=20(&Sset_regexp_cache_size);=0A=20=0A=20=20=20= pdumper_do_now_and_after_load=20(syms_of_search_for_pdumper);=0A=20}=0A= @@=20-3467,16=20+3521,5=20@@=20syms_of_search=20(void)=0A=20static=20= void=0A=20syms_of_search_for_pdumper=20(void)=0A=20{=0A-=20=20for=20(int=20= i=20=3D=200;=20i=20<=20REGEXP_CACHE_SIZE;=20++i)=0A-=20=20=20=20{=0A-=20=20= =20=20=20=20searchbufs[i].buf.allocated=20=3D=20100;=0A-=20=20=20=20=20=20= searchbufs[i].buf.buffer=20=3D=20xmalloc=20(100);=0A-=20=20=20=20=20=20= searchbufs[i].buf.fastmap=20=3D=20searchbufs[i].fastmap;=0A-=20=20=20=20=20= =20searchbufs[i].regexp=20=3D=20Qnil;=0A-=20=20=20=20=20=20= searchbufs[i].f_whitespace_regexp=20=3D=20Qnil;=0A-=20=20=20=20=20=20= searchbufs[i].busy=20=3D=20false;=0A-=20=20=20=20=20=20= searchbufs[i].syntax_table=20=3D=20Qnil;=0A-=20=20=20=20=20=20= searchbufs[i].next=20=3D=20(i=20=3D=3D=20REGEXP_CACHE_SIZE-1=20?=200=20:=20= &searchbufs[i+1]);=0A-=20=20=20=20}=0A-=20=20searchbuf_head=20=3D=20= &searchbufs[0];=0A+=20=20set_regexp_cache_size=20= (DEFAULT_REGEXP_CACHE_SIZE);=0A=20}=0A--=20=0A2.32.0=20(Apple=20Git-132)=0A= =0A= --Apple-Mail=_ECFA48ED-6129-4805-92CD-2E035048FD18--