{"thread":{"id":"14087","subject":"Shrink the git binary a bit by avoiding unnecessary inline functions","startedAt":"2008-06-22T19:19:25Z","lastAt":"2008-06-23T05:26:04Z","messageCount":7,"participants":["Linus Torvalds","Christian MICHON","Matthieu Moy"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"80637","messageId":"alpine.LFD.1.10.0806221159140.2926@woody.linux-foundation.org","threadId":"14087","inReplyTo":null,"subject":"Shrink the git binary a bit by avoiding unnecessary inline functions","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2008-06-22T19:19:25Z","receivedAt":"2008-06-22T19:19:25Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nSo I was looking at the disgusting size of the git binary, and even with \nthe debugging removed, and using -Os instead of -O2, the size of the text \nsection was pretty high. In this day and age I guess almost a megabyte of \ntext isn't really all that surprising, but it still doesn't exactly make \nme think \"lean and mean\".\n\nWith -Os, a surprising amount of text space is wasted on inline functions \nthat end up just being replicated multiple times, and where performance \nreally isn't a valid reason to inline them. In particular, the trivial \nwrapper functions like \"xmalloc()\" are used _everywhere_, and making them \ninline just duplicates the text (and the string we use to 'die()' on \nfailure) unnecessarily.\n\nSo this just moves them into a \"wrapper.c\" file, getting rid of a tiny bit \nof unnecessary bloat. The following numbers are both with \"CFLAGS=-Os\":\n\nBefore:\n\t[torvalds@woody git]$ size git\n\t   text\t   data\t    bss\t    dec\t    hex\tfilename\n\t 700460\t  15160\t 292184\t1007804\t  f60bc\tgit\n\nAfter:\n\t[torvalds@woody git]$ size git\n\t   text\t   data\t    bss\t    dec\t    hex\tfilename\n\t 670540\t  15160\t 292184\t 977884\t  eebdc\tgit\n\nso it saves almost 30k of text-space (it actually saves more than that \nwith the default -O2, but I don't think that's necessarily a very relevant \nnumber from a \"try to shrink git\" standpoint).\n\nIt might conceivably have a performance impact, but none of this should be \n_that_ performance critical. The real cost is not generally in the wrapper \nanyway, but in the code it wraps (ie the cost of \"xread()\" is all in the \nread itself, not in the trivial wrapping of it).\n\nSigned-off-by: Linus Torvalds <torvalds@linux-foundation.org>\n---\n\nThere are probably other things we should do, but this was the obvious \nlow-hanging fruit.\n\nNOTE! When looking at the actual size of the binary on-disk, all the size \nissues are dwarfed by the cost of teh debug information, so don't be \nfooled by doing an \"ls -l\" unless you strip it first, or remove the \"-g\". \n\nIf you just do a \"ls -l git\" with the default CFLAGS options, you'll think \nthat the git binary is 3+MB in size:\n\n\t$ ls -lh git\n\t-rwxrwxr-x 88 torvalds torvalds 3.4M 2008-06-22 12:14 git\n\nbut that's mostly debug and symbol info:\n\n\t$ strip git\n\t$ ls -lh git\n\t-rwxrwxr-x 88 torvalds torvalds 811K 2008-06-22 12:15 git\n\nso it's not wuite *that* scary. With -Os (this patch applied in all \ncases), it shrinks to\n\n\t$ ls -lh git\n\t-rwxrwxr-x 88 torvalds torvalds 2.9M 2008-06-22 12:17 git\n\n\t$ strip git\n\t$ ls -lh git\n\t-rwxrwxr-x 88 torvalds torvalds 680K 2008-06-22 12:18 git\n\nrespectively.\n\n Makefile          |    1 +\n git-compat-util.h |  167 ++++-------------------------------------------------\n wrapper.c         |  160 ++++++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 173 insertions(+), 155 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 6a31c9f..408ec33 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -467,6 +467,7 @@ LIB_OBJS += unpack-trees.o\n LIB_OBJS += usage.o\n LIB_OBJS += utf8.o\n LIB_OBJS += walker.o\n+LIB_OBJS += wrapper.o\n LIB_OBJS += write_or_die.o\n LIB_OBJS += ws.o\n LIB_OBJS += wt-status.o\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex c04e8ba..6f94a81 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -240,161 +240,18 @@ static inline char *gitstrchrnul(const char *s, int c)\n \n extern void release_pack_memory(size_t, int);\n \n-static inline char* xstrdup(const char *str)\n-{\n-\tchar *ret = strdup(str);\n-\tif (!ret) {\n-\t\trelease_pack_memory(strlen(str) + 1, -1);\n-\t\tret = strdup(str);\n-\t\tif (!ret)\n-\t\t\tdie(\"Out of memory, strdup failed\");\n-\t}\n-\treturn ret;\n-}\n-\n-static inline void *xmalloc(size_t size)\n-{\n-\tvoid *ret = malloc(size);\n-\tif (!ret && !size)\n-\t\tret = malloc(1);\n-\tif (!ret) {\n-\t\trelease_pack_memory(size, -1);\n-\t\tret = malloc(size);\n-\t\tif (!ret && !size)\n-\t\t\tret = malloc(1);\n-\t\tif (!ret)\n-\t\t\tdie(\"Out of memory, malloc failed\");\n-\t}\n-#ifdef XMALLOC_POISON\n-\tmemset(ret, 0xA5, size);\n-#endif\n-\treturn ret;\n-}\n-\n-/*\n- * xmemdupz() allocates (len + 1) bytes of memory, duplicates \"len\" bytes of\n- * \"data\" to the allocated memory, zero terminates the allocated memory,\n- * and returns a pointer to the allocated memory. If the allocation fails,\n- * the program dies.\n- */\n-static inline void *xmemdupz(const void *data, size_t len)\n-{\n-\tchar *p = xmalloc(len + 1);\n-\tmemcpy(p, data, len);\n-\tp[len] = '\\0';\n-\treturn p;\n-}\n-\n-static inline char *xstrndup(const char *str, size_t len)\n-{\n-\tchar *p = memchr(str, '\\0', len);\n-\treturn xmemdupz(str, p ? p - str : len);\n-}\n-\n-static inline void *xrealloc(void *ptr, size_t size)\n-{\n-\tvoid *ret = realloc(ptr, size);\n-\tif (!ret && !size)\n-\t\tret = realloc(ptr, 1);\n-\tif (!ret) {\n-\t\trelease_pack_memory(size, -1);\n-\t\tret = realloc(ptr, size);\n-\t\tif (!ret && !size)\n-\t\t\tret = realloc(ptr, 1);\n-\t\tif (!ret)\n-\t\t\tdie(\"Out of memory, realloc failed\");\n-\t}\n-\treturn ret;\n-}\n-\n-static inline void *xcalloc(size_t nmemb, size_t size)\n-{\n-\tvoid *ret = calloc(nmemb, size);\n-\tif (!ret && (!nmemb || !size))\n-\t\tret = calloc(1, 1);\n-\tif (!ret) {\n-\t\trelease_pack_memory(nmemb * size, -1);\n-\t\tret = calloc(nmemb, size);\n-\t\tif (!ret && (!nmemb || !size))\n-\t\t\tret = calloc(1, 1);\n-\t\tif (!ret)\n-\t\t\tdie(\"Out of memory, calloc failed\");\n-\t}\n-\treturn ret;\n-}\n-\n-static inline void *xmmap(void *start, size_t length,\n-\tint prot, int flags, int fd, off_t offset)\n-{\n-\tvoid *ret = mmap(start, length, prot, flags, fd, offset);\n-\tif (ret == MAP_FAILED) {\n-\t\tif (!length)\n-\t\t\treturn NULL;\n-\t\trelease_pack_memory(length, fd);\n-\t\tret = mmap(start, length, prot, flags, fd, offset);\n-\t\tif (ret == MAP_FAILED)\n-\t\t\tdie(\"Out of memory? mmap failed: %s\", strerror(errno));\n-\t}\n-\treturn ret;\n-}\n-\n-/*\n- * xread() is the same a read(), but it automatically restarts read()\n- * operations with a recoverable error (EAGAIN and EINTR). xread()\n- * DOES NOT GUARANTEE that \"len\" bytes is read even if the data is available.\n- */\n-static inline ssize_t xread(int fd, void *buf, size_t len)\n-{\n-\tssize_t nr;\n-\twhile (1) {\n-\t\tnr = read(fd, buf, len);\n-\t\tif ((nr < 0) && (errno == EAGAIN || errno == EINTR))\n-\t\t\tcontinue;\n-\t\treturn nr;\n-\t}\n-}\n-\n-/*\n- * xwrite() is the same a write(), but it automatically restarts write()\n- * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT\n- * GUARANTEE that \"len\" bytes is written even if the operation is successful.\n- */\n-static inline ssize_t xwrite(int fd, const void *buf, size_t len)\n-{\n-\tssize_t nr;\n-\twhile (1) {\n-\t\tnr = write(fd, buf, len);\n-\t\tif ((nr < 0) && (errno == EAGAIN || errno == EINTR))\n-\t\t\tcontinue;\n-\t\treturn nr;\n-\t}\n-}\n-\n-static inline int xdup(int fd)\n-{\n-\tint ret = dup(fd);\n-\tif (ret < 0)\n-\t\tdie(\"dup failed: %s\", strerror(errno));\n-\treturn ret;\n-}\n-\n-static inline FILE *xfdopen(int fd, const char *mode)\n-{\n-\tFILE *stream = fdopen(fd, mode);\n-\tif (stream == NULL)\n-\t\tdie(\"Out of memory? fdopen failed: %s\", strerror(errno));\n-\treturn stream;\n-}\n-\n-static inline int xmkstemp(char *template)\n-{\n-\tint fd;\n-\n-\tfd = mkstemp(template);\n-\tif (fd < 0)\n-\t\tdie(\"Unable to create temporary file: %s\", strerror(errno));\n-\treturn fd;\n-}\n+extern char *xstrdup(const char *str);\n+extern void *xmalloc(size_t size);\n+extern void *xmemdupz(const void *data, size_t len);\n+extern char *xstrndup(const char *str, size_t len);\n+extern void *xrealloc(void *ptr, size_t size);\n+extern void *xcalloc(size_t nmemb, size_t size);\n+extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);\n+extern ssize_t xread(int fd, void *buf, size_t len);\n+extern ssize_t xwrite(int fd, const void *buf, size_t len);\n+extern int xdup(int fd);\n+extern FILE *xfdopen(int fd, const char *mode);\n+extern int xmkstemp(char *template);\n \n static inline size_t xsize_t(off_t len)\n {\ndiff --git a/wrapper.c b/wrapper.c\nnew file mode 100644\nindex 0000000..4e04f76\n--- /dev/null\n+++ b/wrapper.c\n@@ -0,0 +1,160 @@\n+/*\n+ * Various trivial helper wrappers around standard functions\n+ */\n+#include \"cache.h\"\n+\n+char *xstrdup(const char *str)\n+{\n+\tchar *ret = strdup(str);\n+\tif (!ret) {\n+\t\trelease_pack_memory(strlen(str) + 1, -1);\n+\t\tret = strdup(str);\n+\t\tif (!ret)\n+\t\t\tdie(\"Out of memory, strdup failed\");\n+\t}\n+\treturn ret;\n+}\n+\n+void *xmalloc(size_t size)\n+{\n+\tvoid *ret = malloc(size);\n+\tif (!ret && !size)\n+\t\tret = malloc(1);\n+\tif (!ret) {\n+\t\trelease_pack_memory(size, -1);\n+\t\tret = malloc(size);\n+\t\tif (!ret && !size)\n+\t\t\tret = malloc(1);\n+\t\tif (!ret)\n+\t\t\tdie(\"Out of memory, malloc failed\");\n+\t}\n+#ifdef XMALLOC_POISON\n+\tmemset(ret, 0xA5, size);\n+#endif\n+\treturn ret;\n+}\n+\n+/*\n+ * xmemdupz() allocates (len + 1) bytes of memory, duplicates \"len\" bytes of\n+ * \"data\" to the allocated memory, zero terminates the allocated memory,\n+ * and returns a pointer to the allocated memory. If the allocation fails,\n+ * the program dies.\n+ */\n+void *xmemdupz(const void *data, size_t len)\n+{\n+\tchar *p = xmalloc(len + 1);\n+\tmemcpy(p, data, len);\n+\tp[len] = '\\0';\n+\treturn p;\n+}\n+\n+char *xstrndup(const char *str, size_t len)\n+{\n+\tchar *p = memchr(str, '\\0', len);\n+\treturn xmemdupz(str, p ? p - str : len);\n+}\n+\n+void *xrealloc(void *ptr, size_t size)\n+{\n+\tvoid *ret = realloc(ptr, size);\n+\tif (!ret && !size)\n+\t\tret = realloc(ptr, 1);\n+\tif (!ret) {\n+\t\trelease_pack_memory(size, -1);\n+\t\tret = realloc(ptr, size);\n+\t\tif (!ret && !size)\n+\t\t\tret = realloc(ptr, 1);\n+\t\tif (!ret)\n+\t\t\tdie(\"Out of memory, realloc failed\");\n+\t}\n+\treturn ret;\n+}\n+\n+void *xcalloc(size_t nmemb, size_t size)\n+{\n+\tvoid *ret = calloc(nmemb, size);\n+\tif (!ret && (!nmemb || !size))\n+\t\tret = calloc(1, 1);\n+\tif (!ret) {\n+\t\trelease_pack_memory(nmemb * size, -1);\n+\t\tret = calloc(nmemb, size);\n+\t\tif (!ret && (!nmemb || !size))\n+\t\t\tret = calloc(1, 1);\n+\t\tif (!ret)\n+\t\t\tdie(\"Out of memory, calloc failed\");\n+\t}\n+\treturn ret;\n+}\n+\n+void *xmmap(void *start, size_t length,\n+\tint prot, int flags, int fd, off_t offset)\n+{\n+\tvoid *ret = mmap(start, length, prot, flags, fd, offset);\n+\tif (ret == MAP_FAILED) {\n+\t\tif (!length)\n+\t\t\treturn NULL;\n+\t\trelease_pack_memory(length, fd);\n+\t\tret = mmap(start, length, prot, flags, fd, offset);\n+\t\tif (ret == MAP_FAILED)\n+\t\t\tdie(\"Out of memory? mmap failed: %s\", strerror(errno));\n+\t}\n+\treturn ret;\n+}\n+\n+/*\n+ * xread() is the same a read(), but it automatically restarts read()\n+ * operations with a recoverable error (EAGAIN and EINTR). xread()\n+ * DOES NOT GUARANTEE that \"len\" bytes is read even if the data is available.\n+ */\n+ssize_t xread(int fd, void *buf, size_t len)\n+{\n+\tssize_t nr;\n+\twhile (1) {\n+\t\tnr = read(fd, buf, len);\n+\t\tif ((nr < 0) && (errno == EAGAIN || errno == EINTR))\n+\t\t\tcontinue;\n+\t\treturn nr;\n+\t}\n+}\n+\n+/*\n+ * xwrite() is the same a write(), but it automatically restarts write()\n+ * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT\n+ * GUARANTEE that \"len\" bytes is written even if the operation is successful.\n+ */\n+ssize_t xwrite(int fd, const void *buf, size_t len)\n+{\n+\tssize_t nr;\n+\twhile (1) {\n+\t\tnr = write(fd, buf, len);\n+\t\tif ((nr < 0) && (errno == EAGAIN || errno == EINTR))\n+\t\t\tcontinue;\n+\t\treturn nr;\n+\t}\n+}\n+\n+int xdup(int fd)\n+{\n+\tint ret = dup(fd);\n+\tif (ret < 0)\n+\t\tdie(\"dup failed: %s\", strerror(errno));\n+\treturn ret;\n+}\n+\n+FILE *xfdopen(int fd, const char *mode)\n+{\n+\tFILE *stream = fdopen(fd, mode);\n+\tif (stream == NULL)\n+\t\tdie(\"Out of memory? fdopen failed: %s\", strerror(errno));\n+\treturn stream;\n+}\n+\n+int xmkstemp(char *template)\n+{\n+\tint fd;\n+\n+\tfd = mkstemp(template);\n+\tif (fd < 0)\n+\t\tdie(\"Unable to create temporary file: %s\", strerror(errno));\n+\treturn fd;\n+}\n"},{"id":"80644","messageId":"46d6db660806221432m6a6e2f3egf78faa1510f8d643@mail.gmail.com","threadId":"14087","inReplyTo":"alpine.LFD.1.10.0806221159140.2926@woody.linux-foundation.org","subject":"Re: Shrink the git binary a bit by avoiding unnecessary inline functions","fromName":"Christian MICHON","fromEmail":"christian.michon@gmail.com","sentAt":"2008-06-22T21:32:49Z","receivedAt":"2008-06-22T21:32:49Z","isPatch":false,"sender":{"key":"christian.michon@gmail.com","avatar":"https://gravatar.com/avatar/8a7c327b21187fbcab5c27640a49450eec72e0355dc292501197f27a5a744ec4?d=mp&s=160"},"body":"On Sun, Jun 22, 2008 at 9:19 PM, Linus Torvalds\n<torvalds@linux-foundation.org> wrote:\n>\n> So I was looking at the disgusting size of the git binary, and even with\n> the debugging removed, and using -Os instead of -O2, the size of the text\n> section was pretty high. In this day and age I guess almost a megabyte of\n> text isn't really all that surprising, but it still doesn't exactly make\n> me think \"lean and mean\".\n\nusing gcc-3.4.6 and uclibc-0.9.29 (not exactly everyone's\nconfiguration of course...)\nI get different numbers with CFLAGS=-Os and NO_CURL, NO_ICONV on plain\ngit-1.5.6:\n\nsh-3.2# ls -lh git\n-rwxr-xr-x    3 root     root       699.7k Jun 22 23:26 git\n\nsh-3.2# size git\n   text    data     bss     dec     hex filename\n 616544   10960  272272  899776   dbac0 git\n\nafter I use your patch, it goes to:\n\nsh-3.2# ls -lh git\n-rwxr-xr-x    1 root     root       652.6k Jun 22 23:30 git\n\nsh-3.2# size git\n   text    data     bss     dec     hex filename\n 568124   10960  272272  851356   cfd9c git\n\nSo your patch obviously works here too but I get quite smaller figures too.\n\ncurl and iconv are not available on my distro detaolb, maybe it's a\nbig difference too...\n\nCould your figures come from recent gcc/glibc versions ?\n\n-- \nChristian\n--\nhttp://detaolb.sourceforge.net/, a linux distribution for Qemu with Git inside !\n"},{"id":"80650","messageId":"vpqej6p9ko2.fsf@bauges.imag.fr","threadId":"14087","inReplyTo":"alpine.LFD.1.10.0806221159140.2926@woody.linux-foundation.org","subject":"Re: Shrink the git binary a bit by avoiding unnecessary inline functions","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2008-06-22T22:20:13Z","receivedAt":"2008-06-22T22:20:13Z","isPatch":false,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"Linus Torvalds <torvalds@linux-foundation.org> writes:\n\n> -static inline char* xstrdup(const char *str)\n> -{\n> -\tchar *ret = strdup(str);\n> -\tif (!ret) {\n> -\t\trelease_pack_memory(strlen(str) + 1, -1);\n> -\t\tret = strdup(str);\n> -\t\tif (!ret)\n> -\t\t\tdie(\"Out of memory, strdup failed\");\n> -\t}\n> -\treturn ret;\n> -}\n\nWouldn't it be better to split that kind of function into two parts:\n\n- inline the short common case\n- put the special case apart\n\nlike\n\nstatic inline char* xstrdup(const char *str)\n{\n\tchar *ret = strdup(str);\n\tif (!ret)\n\t\treturn xstrdup_failed(str);\n\telse\n\t\treturn ret;\n}\n\n(with xstrdup_failed not being inline.)\n\n?\n\n-- \nMatthieu\n"},{"id":"80652","messageId":"alpine.LFD.1.10.0806221532560.2926@woody.linux-foundation.org","threadId":"14087","inReplyTo":"vpqej6p9ko2.fsf@bauges.imag.fr","subject":"Re: Shrink the git binary a bit by avoiding unnecessary inline functions","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2008-06-22T22:40:30Z","receivedAt":"2008-06-22T22:40:30Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 23 Jun 2008, Matthieu Moy wrote:\n> \n> Wouldn't it be better to split that kind of function into two parts:\n> \n> - inline the short common case\n> - put the special case apart\n\nIt's almost certainly not worth it. These things really aren't big \noptimization wins, and the *big* wins from doing inlines are if it allows \nthe call-site to do more optimizations (eg conditionals or calculations \nthat just go away if inlined with constant arguments, for example), or if \nthe lack of any function call at all allows the caller to do better \nregister allocation around it.\n\nSince these inlines contain a real call regardless, the second case never \nhappens.\n\nThe first case can happen with things like \"strlen()\" being optimized away \nfor constant-sized arguments, but for the one user where that was \n(xstrdup()) it really wasn't an issue. And while a constant size argument \nto \"xmalloc()\" is not unlikely, and would allow the compiler to optimize \nthe\n\n\tif (!ret && !size)\n\t\tret = malloc(1);\n\naway statically as an inline, it's really not a big win.\n\n\t\tLinus\n"},{"id":"80661","messageId":"46d6db660806221801j7207e6b0sdf91c2243fad5349@mail.gmail.com","threadId":"14087","inReplyTo":"46d6db660806221432m6a6e2f3egf78faa1510f8d643@mail.gmail.com","subject":"Re: Shrink the git binary a bit by avoiding unnecessary inline functions","fromName":"Christian MICHON","fromEmail":"christian.michon@gmail.com","sentAt":"2008-06-23T01:01:46Z","receivedAt":"2008-06-23T01:01:46Z","isPatch":false,"sender":{"key":"christian.michon@gmail.com","avatar":"https://gravatar.com/avatar/8a7c327b21187fbcab5c27640a49450eec72e0355dc292501197f27a5a744ec4?d=mp&s=160"},"body":"On Sun, Jun 22, 2008 at 9:32 PM, Christian MICHON\n<christian.michon@gmail.com> wrote:\n> using gcc-3.4.6 and uclibc-0.9.29 (not exactly everyone's\n> configuration of course...)\n> I get different numbers with CFLAGS=-Os and NO_CURL, NO_ICONV on plain\n> git-1.5.6:\n>\n> sh-3.2# ls -lh git\n> -rwxr-xr-x    3 root     root       699.7k Jun 22 23:26 git\n>\n> sh-3.2# size git\n>   text    data     bss     dec     hex filename\n>  616544   10960  272272  899776   dbac0 git\n>\n> after I use your patch, it goes to:\n>\n> sh-3.2# ls -lh git\n> -rwxr-xr-x    1 root     root       652.6k Jun 22 23:30 git\n>\n> sh-3.2# size git\n>   text    data     bss     dec     hex filename\n>  568124   10960  272272  851356   cfd9c git\n>\n> So your patch obviously works here too but I get quite smaller figures too.\n>\n> curl and iconv are not available on my distro detaolb, maybe it's a\n> big difference too...\n>\n> Could your figures come from recent gcc/glibc versions ?\n>\n\nLinus,\n\nI've put my hands on a usb stick with ubuntu (gcc-4.2.3 and\nglibc-2.7), containing all packages needed for a pristine compilation\nof git-1.5.6.\n\nI only changed CFLAGS to -Os, no debug info compiled.\n\nubuntu@ubuntu:~/Desktop/git-1.5.6$ ls -lh git\n-rwxr-xr-x 1 ubuntu ubuntu 718K 2008-06-23 00:47 git\n\nubuntu@ubuntu:~/Desktop/git-1.5.6$ size git\n   text\t   data\t    bss\t    dec\t    hex\tfilename\n 616606\t   9876\t 270812\t 897294\t  db10e\tgit\n\nThere's more than 80k difference with your figures (I have not even\napplied your patch yet).\nMay I ask which version of gcc you're using ? The numbers you provided\nwere really with -Os ?\n\nOnce your patch is applied, these are the final figures:\n\nubuntu@ubuntu:~/Desktop/git-1.5.6$ ls -lh git\n-rwxr-xr-x 1 ubuntu ubuntu 692K 2008-06-23 00:59 git\n\nubuntu@ubuntu:~/Desktop/git-1.5.6$ size git\n   text\t   data\t    bss\t    dec\t    hex\tfilename\n 591554\t   9876\t 270812\t 872242\t  d4f32\tgit\n\n-- \nChristian\n--\nhttp://detaolb.sourceforge.net/, a linux distribution for Qemu with Git inside !\n"},{"id":"80672","messageId":"alpine.LFD.1.10.0806222150180.2926@woody.linux-foundation.org","threadId":"14087","inReplyTo":"46d6db660806221801j7207e6b0sdf91c2243fad5349@mail.gmail.com","subject":"Re: Shrink the git binary a bit by avoiding unnecessary inline functions","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2008-06-23T04:54:02Z","receivedAt":"2008-06-23T04:54:02Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 23 Jun 2008, Christian MICHON wrote:\n> \n> There's more than 80k difference with your figures (I have not even\n> applied your patch yet).\n> May I ask which version of gcc you're using ? The numbers you provided\n> were really with -Os ?\n\ngcc version 4.3.0 20080428 (Red Hat 4.3.0-8) (GCC) \n\nAlso notice that this is x86-64, maybe you're 32-bit? \n\nYou also have much smaller size difference (616606 -> 591554 is just over \n16kB), but if my version of gcc bloats things up more, then I'm not \nsurprised that the difference is bigger too.\n\n\t\t\tLinus\n"},{"id":"80674","messageId":"46d6db660806222226k73a2e66kd83c5d28b957c61d@mail.gmail.com","threadId":"14087","inReplyTo":"alpine.LFD.1.10.0806222150180.2926@woody.linux-foundation.org","subject":"Re: Shrink the git binary a bit by avoiding unnecessary inline functions","fromName":"Christian MICHON","fromEmail":"christian.michon@gmail.com","sentAt":"2008-06-23T05:26:04Z","receivedAt":"2008-06-23T05:26:04Z","isPatch":false,"sender":{"key":"christian.michon@gmail.com","avatar":"https://gravatar.com/avatar/8a7c327b21187fbcab5c27640a49450eec72e0355dc292501197f27a5a744ec4?d=mp&s=160"},"body":"On Mon, Jun 23, 2008 at 6:54 AM, Linus Torvalds\n<torvalds@linux-foundation.org> wrote:\n> gcc version 4.3.0 20080428 (Red Hat 4.3.0-8) (GCC)\n>\n> Also notice that this is x86-64, maybe you're 32-bit?\n\nit is an AMD 64, but the ubuntu and detaolb are indeed 32 bits distros.\n\n>\n> You also have much smaller size difference (616606 -> 591554 is just over\n> 16kB), but if my version of gcc bloats things up more, then I'm not\n> surprised that the difference is bigger too.\n>\n\nI guess I should compare results between compiler versions too...\n\nThanks for the explainations.\n\n-- \nChristian\n--\nhttp://detaolb.sourceforge.net/, a linux distribution for Qemu with Git inside !\n"}]}