{"id":1967,"date":"2022-05-04T11:23:18","date_gmt":"2022-05-04T08:23:18","guid":{"rendered":"http:\/\/52.91.248.125\/java-developers-chase-a-memory-leak-in-python-2\/"},"modified":"2023-02-28T11:53:25","modified_gmt":"2023-02-28T09:53:25","slug":"java-developers-chase-a-memory-leak-in-python-2","status":"publish","type":"post","link":"https:\/\/www.orfium.com\/ja\/news\/java-developers-chase-a-memory-leak-in-python-2\/","title":{"rendered":"Java developers chase a memory leak in python\u00a0"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"http:\/\/52.91.248.125\/wp-content\/uploads\/2023\/02\/mem_leak_header-scaled.jpg\" alt=\"\" class=\"wp-image-1016\"\/><figcaption>Photo by <a href=\"https:\/\/unsplash.com\/@luis_tosta\">Luis Tosta <\/a>on <a href=\"https:\/\/unsplash.com\/photos\/SVeCm5KF_ho\">Unsplash<\/a><\/figcaption><\/figure>\n\n\n\n<p>You take some things for granted when you work in a stack for a long time. For example, you assume that having the proper tools to do whatever it is you need to do is standard, nowadays. The truth is that sometimes you have to appreciate what you have, because you\u2019ll miss it when you find out you don\u2019t have it at your disposal. Like memory usage monitoring.<\/p>\n\n\n\n<p>We\u2019ll use a real-life example of how we troubleshot a memory issue in python, while our background and developers were in java. Our first reaction was to start monitoring the memory with a tool like Visual VM. Surprisingly, a similar tool to monitor memory usage doesn\u2019t exist for python. That seemed a bit unbelievable but we cross-checked it with experienced python developers.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/FERBtYxFwi_lUgF8hBBYwwypc-yozIPlNhr5lO-msOuFNCd2bx5oLsAQab4uKDuuY6WLNY9KwbXJSWUXNtRN3qVcwbITh9nNEW0D_OxGPi7Jjue9Nm-6DPrCL61pMfesu_bUUgGsXu1X62uOIw\" alt=\"\"\/><\/figure>\n\n\n\n<p>Source: <a href=\"https:\/\/visualvm.github.io\/\">https:\/\/visualvm.github.io\/<\/a><\/p>\n\n\n\n<p>So, with the help of our staff engineer, we searched for the right tool to locate the memory leak, whatever the root cause was.<\/p>\n\n\n\n<p>We tried 3 different approaches and used a variety of tools to locate the issue.<\/p>\n\n\n\n<p>Method #1: A simple decorator for execution time<\/p>\n\n\n\n<p>Method #2: Using memory_profiler<\/p>\n\n\n\n<p>Method #3: Calculating objects sizes<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Method #1: A simple decorator for execution time<\/strong><\/h4>\n\n\n\n<p>Decorator functions are used in python widely and they are easy, fast and convenient.<\/p>\n\n\n\n<p><strong>How it works:<\/strong> You can write a simple wrapper that calculates the execution time of a code block. Just take the time at the beginning and the end and calculate the difference. This will result in the duration of the execution in seconds.<\/p>\n\n\n\n<p>Then, you can use the decorator in various functions that you think might be the bottleneck.<\/p>\n\n\n\n<p>First, you create the function:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from functools import wraps\nfrom time import time\n\n\ndef measure_time(f):\n&nbsp;&nbsp;&nbsp;@wraps(f)\n&nbsp;&nbsp;&nbsp;def wrap(*args, **kw):\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ts = time()\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result = f(*args, **kw)\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;te = time()\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f.__name__ + \" %s\" % (te - ts))\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return result\n&nbsp;&nbsp;&nbsp;return wrap<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Then, the usage is really simple (like a java annotation):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from foo import measure_time\n\n@measure_time\ndef test(input):\n&nbsp;&nbsp;&nbsp;# some logic\n&nbsp;&nbsp;&nbsp;# a few lines more\n&nbsp;&nbsp;&nbsp;return output<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Console (function name and execution time):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>test 500.9122574329376<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>This would be the junior\u2019s approach to debug memory issues, kind of like using print to debug. Nonetheless, it proved to be an effective and fast way to get an idea of what\u2019s going on with the code.<\/p>\n\n\n\n<p><strong>Pros:<\/strong><\/p>\n\n\n\n<ul><li>Easy to implement<\/li><li>Easy to understand<\/li><\/ul>\n\n\n\n<p><strong>Cons:<\/strong><\/p>\n\n\n\n<ul><li>Adds useless code that need to be deleted afterwards<\/li><li>If your app is big, you add too many measurements<\/li><li>Works better if you have a hunch about where the issue is located<\/li><li>It doesn\u2019t actually measure memory<\/li><li>The method needs to be executed successfully in order to see result (if it crashes, you won\u2019t have anything)<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Method #2: Using memory_profiler<\/strong><\/h4>\n\n\n\n<p>A more \u201cmemory-focused\u201d approach is <em>memory_profiler<\/em>. It\u2019s an app that can be installed via pip and used as a decorator.<\/p>\n\n\n\n<p>This app will track down memory changes and create a report with measures for each line.<\/p>\n\n\n\n<p>Installation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pip install -U memory_profiler<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Then, the usage is really simple (like java annotation):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@profile\ndef my_func():\n   a = &#91;1] * (10 ** 6)\n   b = &#91;2] * (2 * 10 ** 7)\n   del b\n   return a<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Source: <a href=\"https:\/\/pypi.org\/project\/memory-profiler\/\">https:\/\/pypi.org\/project\/memory-profiler\/<\/a><\/p>\n\n\n\n<p>The profiler output will be something like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> Line #&nbsp; &nbsp; Mem usage&nbsp; &nbsp; Increment&nbsp; Occurrences &nbsp; Line Contents\n============================================================\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3 &nbsp; 38.816 MiB &nbsp; 38.816 MiB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; @profile\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; def my_func():\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5 &nbsp; 46.492 MiB&nbsp; &nbsp; 7.676 MiB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; a = &#91;1] * (10 ** 6)\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp; 199.117 MiB&nbsp; 152.625 MiB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; b = &#91;2] * (2 * 10 ** 7)\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7 &nbsp; 46.629 MiB -152.488 MiB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; del b\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8 &nbsp; 46.629 MiB&nbsp; &nbsp; 0.000 MiB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; return a<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><br><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Source: <a href=\"https:\/\/pypi.org\/project\/memory-profiler\/\">https:\/\/pypi.org\/project\/memory-profiler\/<\/a><\/p>\n\n\n\n<p>A more realistic example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from memory_profiler import profile\n\ndef get_c():\n&nbsp;&nbsp;return (10 ** 6)\n\ndef get_d():\n&nbsp;&nbsp;return (2 * 10 ** 7)\n\ndef calculate_a():\n&nbsp;&nbsp;return &#91;1] * get_c()\n\ndef calculate_b():\n&nbsp;&nbsp;return &#91;2] * get_d()\n\n@profile\ndef test():\n&nbsp;&nbsp;a = calculate_a()\n&nbsp;&nbsp;b = calculate_b()\n&nbsp;&nbsp;output = a + b\n&nbsp;&nbsp;return output<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>The output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Line #&nbsp; &nbsp; Mem usage&nbsp; &nbsp; Increment&nbsp; Occurrences &nbsp; Line Contents\n=============================================================\n&nbsp;&nbsp;&nbsp;&nbsp;38 &nbsp; &nbsp; 20.2 MiB &nbsp; &nbsp; 20.2 MiB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; @profile\n&nbsp;&nbsp;&nbsp;&nbsp;39 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; def test():\n&nbsp;&nbsp;&nbsp;&nbsp;40 &nbsp; &nbsp; 27.7 MiB&nbsp; &nbsp; &nbsp; 7.5 MiB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1&nbsp; &nbsp; &nbsp; a = calculate_a()\n&nbsp;&nbsp;&nbsp;&nbsp;41&nbsp; &nbsp; 180.4 MiB&nbsp; &nbsp; 152.6 MiB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1&nbsp; &nbsp; &nbsp; b = calculate_b()\n&nbsp;&nbsp;&nbsp;&nbsp;42&nbsp; &nbsp; 340.7 MiB&nbsp; &nbsp; 160.4 MiB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1&nbsp; &nbsp; &nbsp; output = a + b\n&nbsp;&nbsp;&nbsp;&nbsp;43&nbsp; &nbsp; 340.7 MiB&nbsp; &nbsp; &nbsp; 0.0 MiB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1&nbsp; &nbsp; &nbsp; return output<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>As you can see, there is no info about methods get_c() and get_d(). That\u2019s an issue when you have a big app with many methods calling each other; you have to add the decorator to each method you think might be causing the problem (just like method #1 for time measurement).<\/p>\n\n\n\n<p>Keep in mind that this method, depending on your app size, may make your code significantly slower. In our case, when we needed to measure the parsing of a big file that was causing the memory leak, <em>memory_profiler<\/em> didn\u2019t finish at all.<\/p>\n\n\n\n<p><strong>Pros:<\/strong><\/p>\n\n\n\n<ul><li>Easy to implement<\/li><li>Understandable<\/li><\/ul>\n\n\n\n<p><strong>Cons:<\/strong><\/p>\n\n\n\n<ul><li>Adds useless code that need to be deleted afterwards<\/li><li>If your app is big, you add too many measurements<\/li><li>Works better if you have a hunch about where the issue is located<\/li><li>Depending on your app size, it can be very slow or unable to measure<\/li><li>If it crashes, you learn nothing about the issue<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Method #3: Calculating objects sizes<\/strong><\/h4>\n\n\n\n<p>If you are storing data into objects, a good approach is to check the objects&#8217; sizes. That way, you can narrow down the suspicious code snippets that might be causing the problem.<\/p>\n\n\n\n<p>One way of doing this is by using sys.getsizeof(obj), which returns the size of an object in bytes.<\/p>\n\n\n\n<p>How to implement:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import sys\n\ndef test():\n&nbsp;&nbsp;a = calculate_a()\n&nbsp;&nbsp;print(f\"Size of object a:tt{sys.getsizeof(a)}\")\n&nbsp;&nbsp;b = calculate_b()\n&nbsp;&nbsp;print(f\"Size of object b:tt{sys.getsizeof(b)}\")\n&nbsp;&nbsp;output = a + b\n&nbsp;&nbsp;print(f\"Size of object output:t{sys.getsizeof(output)}\")\n&nbsp;&nbsp;return output<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>The output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Size of object a: 8000056\nSize of object b: 160000056\nSize of object output: 168000056<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>While working on that approach, we bumped into an article about a similar case of troubleshooting. Check it out: <a href=\"https:\/\/towardsdatascience.com\/the-strange-size-of-python-objects-in-memory-ce87bdfbb97f\">Unexpected Size of Python Objects in Memory<\/a>.<\/p>\n\n\n\n<p>Based on that, since our objects were really complex with many children and a lot of collections and attributes, we decided to take a look at the actual size calculation. This could help us narrow down the culprit.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import sys\nimport gc\n\ndef actualsize(input_obj):\n&nbsp;&nbsp;&nbsp;memory_size = 0\n&nbsp;&nbsp;&nbsp;ids = set()\n&nbsp;&nbsp;&nbsp;objects = &#91;input_obj]\n&nbsp;&nbsp;&nbsp;while objects:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new = &#91;]\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for obj in objects:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if id(obj) not in ids:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ids.add(id(obj))\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memory_size += sys.getsizeof(obj)\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new.append(obj)\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;objects = gc.get_referents(*new)\n&nbsp;&nbsp;&nbsp;return memory_size<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Source: <a href=\"https:\/\/towardsdatascience.com\/the-strange-size-of-python-objects-in-memory-ce87bdfbb97f\">https:\/\/towardsdatascience.com\/the-strange-size-of-python-objects-in-memory-ce87bdfbb97f<\/a><\/p>\n\n\n\n<p>Now we have to alter the code to get the <em>actual size<\/em> like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def test():\n  a = calculate_a()\n  print(f\"Size of object a:tt{actualsize(a)}\")\n  b = calculate_b()\n  print(f\"Size of object b:tt{actualsize(b)}\")\n  output = a + b\n  print(f\"Size of object output:t{actualsize(output)}\")\n  return output<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>This is producing a slightly different output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Size of object a: 8000084\nSize of object b: 160000084\nSize of object output: 168000112<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>As you can see, there is a difference in the output object (168000112 instead of 168000056, 56 bytes more). As I mentioned earlier, our object structure is a bit complicated, with multiple references to the same instances. As a result, the actual size calculation was way off and not that helpful. However, this method really does have potential.<\/p>\n\n\n\n<p><strong>Pros:<\/strong><\/p>\n\n\n\n<ul><li>Easy to implement<\/li><li>Easy understand<\/li><\/ul>\n\n\n\n<p><strong>Cons:<\/strong><\/p>\n\n\n\n<ul><li>Adds useless code that need to be deleted afterwards<\/li><li>If your app is big, you add too many measurements<\/li><li>Works better if you have a hunch about where the issue is located<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h3>\n\n\n\n<p>We spoke about the methods, but how did we solve the problem? Which one of these roads led us to the dreaded memory hog?<br><br>Let\u2019s talk about what the actual problem was. There was a part called copy(obj) creating clones of data. When we\u2019ve had low volume, it wasn\u2019t an issue. The objects that were going to be reused were just few. But when we scaled up, we had an enormous amount of cloned objects and none of them used pointers, even though we had so many identical values.<\/p>\n\n\n\n<p>Did any of these methods solve the problem? Not really. In our case, they didn\u2019t provide enough data or indicators to locate the issue. The value of everything above was that by studying more and more we understood better how python manages memory, the objects, the pointers, etc. This gave us enough knowledge and insights to locate the issue. After all, we were the ones implementing it. There was a hunch of where the issue might be located, but we needed proof. We didn\u2019t get any during the troubleshooting, but after fixing the issue, we used all methods for further performance improvements. They were really helpful in the optimization process.<\/p>\n\n\n\n<p>The biggest mistake we made was that in the early stages of implementation, we didn\u2019t run a benchmark with huge files to check if and how we can scale up. We did it after a couple of months of implementation. Obviously, it was a bit late to consider the design a failure and start over. We had already invested too much time to just scrap it. Thankfully, it wasn\u2019t a design flaw, but a simple bug causing a memory leak. Rookie mistake.<\/p>\n\n\n\n<p><strong>Lesson learned:<\/strong> Even if you are really confident in your design and implementation, perform stress tests and check the scalability of the app as early as possible. It\u2019s the best way to avoid redesign and refactoring.<\/p>\n\n\n\n<div style=\"height:18px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-layout-1 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/52.91.248.125\/wp-content\/uploads\/2023\/02\/IMG_20190924_153839-modified.png\" alt=\"\" class=\"wp-image-1018\" width=\"201\" height=\"201\"\/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p><strong>Dimitris Nikolouzos<\/strong><\/p>\n\n\n\n<p>Engineering Manager | Music Standards @ \u039fRFIUM <\/p>\n\n\n\n<p><a rel=\"noreferrer noopener\" href=\"https:\/\/www.linkedin.com\/in\/dnikolouzos\/\" target=\"_blank\">https:\/\/www.linkedin.com\/in\/dnikolouzos\/<\/a> <\/p>\n\n\n\n<p><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/jnikolouzos\" target=\"_blank\">https:\/\/github.com\/jnikolouzos<\/a><\/p>\n<\/div>\n<\/div>\n\n\n\n<div style=\"height:10px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Contributors<\/strong><\/h4>\n\n\n\n<p><strong>Panagiotis Badredin<\/strong>, Backend Software Engineer @ ORFIUM<\/p>\n\n\n\n<p><a href=\"https:\/\/www.linkedin.com\/in\/panagiotis-badredin-01b0754b\/\">https:\/\/www.linkedin.com\/in\/panagiotis-badredin-01b0754b\/<\/a><\/p>\n\n\n\n<p><strong>Antonis Markoulis<\/strong>, Staff Engineer @ ORFIUM<\/p>\n\n\n\n<p><a href=\"https:\/\/www.linkedin.com\/in\/anmarkoulis\/\">https:\/\/www.linkedin.com\/in\/anmarkoulis\/<\/a><\/p>\n\n\n\n<p><strong>Alexis Monte-Santo<\/strong>, Software Engineer @ ORFIUM<\/p>\n\n\n\n<p><a href=\"https:\/\/www.linkedin.com\/in\/alexis-monte-santo-0277b8116\/\">https:\/\/www.linkedin.com\/in\/alexis-monte-santo-0277b8116\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>You take some things for granted when you work in a stack for a long time. For example, you assume that having [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":1923,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_seopress_robots_primary_cat":"none","_seopress_titles_title":"","_seopress_titles_desc":"","_seopress_robots_index":"","content-type":"","footnotes":""},"categories":[19],"tags":[],"acf":[],"_links":{"self":[{"href":"https:\/\/www.orfium.com\/ja\/wp-json\/wp\/v2\/posts\/1967"}],"collection":[{"href":"https:\/\/www.orfium.com\/ja\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.orfium.com\/ja\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.orfium.com\/ja\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.orfium.com\/ja\/wp-json\/wp\/v2\/comments?post=1967"}],"version-history":[{"count":1,"href":"https:\/\/www.orfium.com\/ja\/wp-json\/wp\/v2\/posts\/1967\/revisions"}],"predecessor-version":[{"id":1968,"href":"https:\/\/www.orfium.com\/ja\/wp-json\/wp\/v2\/posts\/1967\/revisions\/1968"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.orfium.com\/ja\/wp-json\/wp\/v2\/media\/1923"}],"wp:attachment":[{"href":"https:\/\/www.orfium.com\/ja\/wp-json\/wp\/v2\/media?parent=1967"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.orfium.com\/ja\/wp-json\/wp\/v2\/categories?post=1967"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.orfium.com\/ja\/wp-json\/wp\/v2\/tags?post=1967"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}