René's URL Explorer Experiment


Title: [Bug]: Memory leak from repeated live plotting · Issue #21595 · matplotlib/matplotlib · GitHub

Open Graph Title: [Bug]: Memory leak from repeated live plotting · Issue #21595 · matplotlib/matplotlib

X Title: [Bug]: Memory leak from repeated live plotting · Issue #21595 · matplotlib/matplotlib

Description: Bug summary Memory leak from repeated live plotting: seems to be caused by transform._parents growing continuously over time, as in #11956 and #11972. Code for reproduction import datetime #import tkinter for GUI import tkinter as tk fro...

Open Graph Description: Bug summary Memory leak from repeated live plotting: seems to be caused by transform._parents growing continuously over time, as in #11956 and #11972. Code for reproduction import datetime #import ...

X Description: Bug summary Memory leak from repeated live plotting: seems to be caused by transform._parents growing continuously over time, as in #11956 and #11972. Code for reproduction import datetime #import ...

Opengraph URL: https://github.com/matplotlib/matplotlib/issues/21595

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"[Bug]: Memory leak from repeated live plotting","articleBody":"### Bug summary\r\n\r\nMemory leak from repeated live plotting: seems to be caused by `transform._parents` growing continuously over time, as in #11956 and #11972.\r\n\r\n### Code for reproduction\r\n\r\n```python\r\nimport datetime\r\n#import tkinter for GUI\r\nimport tkinter as tk\r\nfrom tkinter import W, LEFT\r\n#font types\r\nTITLE_FONT = (\"Verdana\", 14, 'bold')\r\nLARGE_FONT = (\"Verdana\", 12)\r\nMEDIUM_FONT = (\"Verdana\", 10)\r\nSMALL_FONT = (\"Verdana\", 8)\r\n#import stuff for graph\r\nimport matplotlib\r\nfrom matplotlib import ticker as mticker\r\nfrom matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk \r\nmatplotlib.use('TkAgg')\r\nfrom matplotlib import figure\r\nfrom matplotlib import dates as mdates\r\n#import animation to make graph live\r\nimport matplotlib.animation as animation\r\nfrom matplotlib import style\r\nstyle.use(\"seaborn-darkgrid\")\r\nimport random as r\r\nnum_contacts = 5\r\n\r\nimport cProfile\r\nimport pstats\r\nimport io\r\n\r\n#create figure for plots and set figure size/layout\r\nf = figure.Figure(figsize=(16.6,15), dpi=100, facecolor='white')\r\nf.subplots_adjust(top=0.993, bottom=0.015, left=0.04, right = 0.96, hspace=0.65)\r\n\r\nparam_dict = {}\r\nparam_list = ['pH', 'TDS (ppm)', 'Rela. Humidity (%)', 'Air Temp (\\N{DEGREE SIGN}C)', 'Water Temp (\\N{DEGREE SIGN}C)', 'Water Level (cm)']\r\nparam_ylim = [(0, 15), (0, 15), (0, 15), (0, 15), (0, 15), (0, 15)]\r\nlive_dict = {}\r\n\r\n\r\nclass Live_Text:\r\n    def __init__(self, label):\r\n        self.label = label\r\n    \r\nclass Sensor_Plot:\r\n    def __init__(self, plot, tList, x_ax, ylim, param, incoming_data, plot_color):\r\n        self.plot = plot\r\n        self.tList = tList\r\n        self.x_ax = x_ax\r\n        self.ylim = ylim\r\n        self.param = param\r\n        self.incoming_data = incoming_data #\u003c- graph is bound by incoming data and Data Summary Table displays most recent value 20 of them\r\n        self.plot_color = plot_color #initially 'b' for all\r\n        \r\n    def make_plot(self):\r\n        self.plot.clear()\r\n        self.plot.set_xlabel('Time')\r\n        self.plot.set_ylabel(self.param)\r\n        self.plot.set_ylim(self.ylim)\r\n\r\n        self.x_ax.xaxis_date()\r\n        self.x_ax.xaxis.set_major_formatter(mdates.DateFormatter('%a %I:%M:%S %p'))\r\n        \r\n        [tk.set_visible(True) for tk in self.x_ax.get_xticklabels()]\r\n        [label.set_rotation(10) for label in self.x_ax.xaxis.get_ticklabels()] #slant the x axis tick labels for extra coolness\r\n\r\n        if len(self.tList) \u003e 4:\r\n            self.x_ax.set_xlim(self.tList[-2], self.tList[0])\r\n        self.x_ax.xaxis.set_major_locator(mticker.MaxNLocator(nbins = 4))\r\n        \r\n        self.plot.fill_between(self.tList, self.incoming_data, #where=(self.incoming_data \u003e [0]*len(self.incoming_data))\r\n                               facecolor=self.plot_color, edgecolor=self.plot_color, alpha=0.5) #blue @initilization\r\n\r\ndef initialize_plots(): #intiailizes plots...\r\n    global initialize_plots\r\n    try:\r\n        most_recent = [(int(round(datetime.datetime.now().timestamp())),) + tuple([r.randint(1,10), r.randint(1,10), r.randint(1,10), r.randint(1,10), r.randint(1,10), r.randint(1,10)])]\r\n        for i, param in enumerate(param_list, 1):\r\n            tList = []\r\n            most_recent_any_size = []\r\n            for j in range(len(most_recent)):\r\n                #time_f = datetime.strptime(most_recent[j][0], \"%m/%d/%Y %H:%M:%S\")\r\n                time_f = datetime.datetime.fromtimestamp(most_recent[j][0])\r\n                tList.append(time_f)\r\n                most_recent_any_size.append(most_recent[j][i])\r\n\r\n            subplot = f.add_subplot(6, 2, i)  # sharex?\r\n            x_ax = f.get_axes()\r\n            \r\n            current_plot = Sensor_Plot(subplot, tList, x_ax[i-1], param_ylim[i-1], param, most_recent_any_size, 'b')\r\n            param_dict[param] = current_plot\r\n            current_plot.make_plot()\r\n                    \r\n    except: #if there is no data points available to plot, initialize the subplots\r\n        for i, param in enumerate(param_list, 1):\r\n            subplot = f.add_subplot(6, 2, i)\r\n            x_ax = f.get_axes()\r\n            current_plot = Sensor_Plot(subplot, [], x_ax[i-1], param_ylim[i-1], param, [], 'b')\r\n            param_dict[param] = current_plot\r\n            #current_plot.make_plot()    \r\n    #reader.commit()\r\n    initialize_plots = _plots_initialized\r\n\r\ndef _plots_initialized(): #ensures plots only intialized once though!\r\n    pass\r\ninitialize_plots()\r\n\r\n\r\n\r\n###ANIMATE FUNCTION, REMOVE LAST ITEM FROM MOST_RECENT_ANY LIST AND INSERT FRESHLY CALLED VALUE TO BE FIRST IN LIST\r\ndef animate(ii):\r\n    profile = cProfile.Profile()\r\n    profile.enable()\r\n\r\n    while True:\r\n        most_recent_time_graphed = param_dict[param_list[0]] #first, pulls up first plot\r\n        #most_recent = reader.query_by_num(table=\"SensorData\", num=1)\r\n        #generate fake sensor data here\r\n        most_recent = [(int(round(datetime.datetime.now().timestamp())),) + tuple([r.randint(1,10), r.randint(1,10), r.randint(1,10), r.randint(1,10), r.randint(1,10), r.randint(1,10)])] #log time in unix as int\r\n        print(most_recent)\r\n        #reader.commit()         #if identical, do not animate\r\n        #then checks that plot's time list\r\n        if  (len(most_recent) == 0):\r\n            break\r\n        \r\n        #time_reader = datetime.strptime(most_recent[0][0], \"%m/%d/%Y %H:%M:%S\")\r\n        time_reader = datetime.datetime.fromtimestamp(most_recent[0][0])\r\n        if (len(most_recent_time_graphed.tList) != 0) and (time_reader == most_recent_time_graphed.tList[0]):\r\n            for i, param in enumerate(param_list, 1):\r\n                current_text = live_dict[param]\r\n                current_text.label.config(text=most_recent[0][i], fg=\"black\", bg=\"white\")\r\n            break #checks if the timestamp is exactly the same as prior, i.e. no new data points have been logged in this frame\r\n        #do I have to add an else?\r\n    \r\n        else:\r\n            for i, key in enumerate(param_dict, 1):\r\n                current_plot = param_dict[key]\r\n                current_param_val = float(most_recent[0][i])\r\n                current_text = live_dict[key] #update to live text data summary\r\n\r\n\r\n                current_text.label.config(text=most_recent[0][i], fg=\"black\", bg=\"white\")\r\n                current_plot.plot_color = 'g'\r\n\r\n                data_stream = current_plot.incoming_data\r\n                time_stream = current_plot.tList\r\n                data_stream.insert(0, most_recent[0][i])\r\n                #time_f = datetime.strptime(most_recent[0][0], \"%m/%d/%Y %H:%M:%S\")\r\n                time_f = datetime.datetime.fromtimestamp(most_recent[0][0])\r\n                time_stream.insert(0, time_f)\r\n                if len(data_stream) \u003c 20: #graph updates, growing to show 20 points\r\n                    current_plot.make_plot()\r\n                else:                      #there are 20 points and more available, so animation occurs\r\n                    data_stream.pop()\r\n                    time_stream.pop()\r\n                    current_plot.make_plot()\r\n            break\r\n    if time_reader.minute == 50 and most_recent_time_graphed.tList[1].minute == 49:\r\n        profile.disable()\r\n        result = io.StringIO()\r\n        pstats.Stats(profile,stream=result).print_stats()\r\n        result=result.getvalue()\r\n        # chop the string into a csv-like buffer\r\n        result='ncalls'+result.split('ncalls')[-1]\r\n        result='\\n'.join([','.join(line.rstrip().split(None,5)) for line in result.split('\\n')])\r\n        # save it to disk\r\n        with open('testing.csv', 'r') as f:\r\n            result = f.read() + 'hour: ' + str(time_reader.hour) + '\\n' + result\r\n        \r\n        with open('testing.csv', 'w+') as f:\r\n            f.write(result)\r\n            f.close()\r\n    else:\r\n        profile.disable()\r\n                           \r\n#initialization\r\nclass AllWindow(tk.Tk):\r\n    def __init__(self, *args, **kwargs):\r\n        tk.Tk.__init__(self, *args, **kwargs)\r\n        #add title\r\n        tk.Tk.wm_title(self, \"Matplotlib Live Plotting\")\r\n        container = tk.Frame(self)\r\n        container.pack(side=\"top\", fill=\"both\", expand=True)\r\n        container.grid_rowconfigure(0, weight=1)\r\n        container.grid_columnconfigure(0, weight=1)\r\n        #show the frames\r\n        self.frames = {}\r\n        #remember to add page to this list when making new ones\r\n        frame = HomePage(container, self)\r\n        #set background color for the pages\r\n        frame.config(bg='white')\r\n        self.frames[HomePage] = frame\r\n        frame.grid(row=0, column=0, sticky=\"nsew\")\r\n        self.show_frame(HomePage)\r\n    def show_frame(self, cont):\r\n        frame = self.frames[cont]\r\n        frame.tkraise()\r\n    #end program fcn triggered by quit button\r\n    def die(self):\r\n        exit()\r\n\r\n#add home page\r\nclass HomePage(tk.Frame):\r\n    def __init__(self, parent, controller):\r\n        tk.Frame.__init__(self,parent)\r\n        canvas = FigureCanvasTkAgg(f, self)\r\n        #background = canvas.copy_from_bbox(f.bbox)\r\n        canvas.draw()\r\n        #embed graph into canvas\r\n        canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand = True)\r\n        #add navigation bar\r\n        toolbar = NavigationToolbar2Tk(canvas, self)\r\n        toolbar.update()\r\n        #data table labels\r\n        for i, param in enumerate(param_list): #tk.Label self refers to Homepage\r\n            param_label = tk.Label(self, text=param, fg=\"black\", bg=\"white\",\r\n                            font = MEDIUM_FONT, borderwidth = 2, relief = \"ridge\",\r\n                            width=16, height=1, anchor=W, justify=LEFT)\r\n            param_label.place(x=5, y=500+22*i)\r\n\r\n        for i, param in enumerate(param_list):\r\n            loading_text = tk.Label(self, text=\"Loading\", fg=\"black\", bg=\"white\",\r\n                    font = MEDIUM_FONT, borderwidth = 2, relief = \"ridge\",\r\n                    width=7, height=1)\r\n            loading_text.place(x=140, y=500+22*i)\r\n            current_text = Live_Text(loading_text)\r\n            live_dict[param] = current_text\r\n    \r\n\r\napp = AllWindow()\r\n#app.geometry('1280x623')\r\napp.geometry('1917x970')\r\n#update animation first\r\nani = animation.FuncAnimation(f, animate, interval=100)\r\n#mainloop\r\napp.mainloop()\r\n```\r\n\r\n### Actual outcome\r\n\r\nThe program eventually crashes after running for several days. Memory usage gradually increases throughout the program runtime. Additionally, profiling the animate function revealed that `_invalidate_internal` in Matplotlib seemed to be growing in its execution time. This is in line with #11956 and #11972, since `_invalidate_internal` is searching through `transform._parents`, which grows over time. However, these issues were resolved, so I am unsure why I am encountering the same problem.\r\n\r\n### Expected outcome\r\n\r\nExpect the program to run continuously and indefinitely without memory usage increasing over time.\r\n\r\n### Operating system\r\n\r\nRaspbian GNU/Linux 10 (buster)\r\n\r\n### Matplotlib Version\r\n\r\n3.4.3\r\n\r\n### Matplotlib Backend\r\n\r\nQt5Agg\r\n\r\n### Python version\r\n\r\n3.9\r\n\r\n### Jupyter version\r\n\r\n_No response_\r\n\r\n### Other libraries\r\n\r\n_No response_\r\n\r\n### Installation\r\n\r\npip\r\n\r\n### Conda channel\r\n\r\n_No response_","author":{"url":"https://github.com/bencaterine","@type":"Person","name":"bencaterine"},"datePublished":"2021-11-11T02:18:21.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":7},"url":"https://github.com/21595/matplotlib/issues/21595"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:52a63231-eeb0-8b97-39ce-cdcfa1337457
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-idC84C:35E4DB:10C0BE2:1788DBE:6A567589
html-safe-nonceea9fb4109ea83a10550d1889fc0a96f8dd928d60d7c50701fb5baa3e72bb6a6f
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDODRDOjM1RTREQjoxMEMwQkUyOjE3ODhEQkU6NkE1Njc1ODkiLCJ2aXNpdG9yX2lkIjoiMzI1NTkwNjQyODQ2MTE1MTYyNSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9
visitor-hmacfbdc8683eff8d3e49950a348200a6ff13d97368dca78fac4f0021120583398d4
hovercard-subject-tagissue:1050502760
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/matplotlib/matplotlib/21595/issue_layout
twitter:imagehttps://opengraph.githubassets.com/141bacc70806923e111b7902851c530bfbd77e77623b6eae26ec3e545fd215e9/matplotlib/matplotlib/issues/21595
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/141bacc70806923e111b7902851c530bfbd77e77623b6eae26ec3e545fd215e9/matplotlib/matplotlib/issues/21595
og:image:altBug summary Memory leak from repeated live plotting: seems to be caused by transform._parents growing continuously over time, as in #11956 and #11972. Code for reproduction import datetime #import ...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernamebencaterine
hostnamegithub.com
expected-hostnamegithub.com
None19b5ee9431dcfce15ab4b001d626e4e3a6ba1acb7be814813a52bbebd9a86ef5
turbo-cache-controlno-preview
go-importgithub.com/matplotlib/matplotlib git https://github.com/matplotlib/matplotlib.git
octolytics-dimension-user_id215947
octolytics-dimension-user_loginmatplotlib
octolytics-dimension-repository_id1385122
octolytics-dimension-repository_nwomatplotlib/matplotlib
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id1385122
octolytics-dimension-repository_network_root_nwomatplotlib/matplotlib
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
releaseafc01ffdb045f4ff81c6122091366ade7b6166b7
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/matplotlib/matplotlib/issues/21595#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmatplotlib%2Fmatplotlib%2Fissues%2F21595
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmatplotlib%2Fmatplotlib%2Fissues%2F21595
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=matplotlib%2Fmatplotlib
Reloadhttps://github.com/matplotlib/matplotlib/issues/21595
Reloadhttps://github.com/matplotlib/matplotlib/issues/21595
Reloadhttps://github.com/matplotlib/matplotlib/issues/21595
Please reload this pagehttps://github.com/matplotlib/matplotlib/issues/21595
matplotlib https://github.com/matplotlib
matplotlibhttps://github.com/matplotlib/matplotlib
Please reload this pagehttps://github.com/matplotlib/matplotlib/issues/21595
Notifications https://github.com/login?return_to=%2Fmatplotlib%2Fmatplotlib
Fork 8.4k https://github.com/login?return_to=%2Fmatplotlib%2Fmatplotlib
Star 23k https://github.com/login?return_to=%2Fmatplotlib%2Fmatplotlib
Code https://github.com/matplotlib/matplotlib
Issues 1.1k https://github.com/matplotlib/matplotlib/issues
Pull requests 409 https://github.com/matplotlib/matplotlib/pulls
Actions https://github.com/matplotlib/matplotlib/actions
Projects https://github.com/matplotlib/matplotlib/projects
Wiki https://github.com/matplotlib/matplotlib/wiki
Security and quality 0 https://github.com/matplotlib/matplotlib/security
Insights https://github.com/matplotlib/matplotlib/pulse
Code https://github.com/matplotlib/matplotlib
Issues https://github.com/matplotlib/matplotlib/issues
Pull requests https://github.com/matplotlib/matplotlib/pulls
Actions https://github.com/matplotlib/matplotlib/actions
Projects https://github.com/matplotlib/matplotlib/projects
Wiki https://github.com/matplotlib/matplotlib/wiki
Security and quality https://github.com/matplotlib/matplotlib/security
Insights https://github.com/matplotlib/matplotlib/pulse
[Bug]: Memory leak from repeated live plottinghttps://github.com/matplotlib/matplotlib/issues/21595#top
status: needs clarificationIssues that need more information to resolve.https://github.com/matplotlib/matplotlib/issues?q=state%3Aopen%20label%3A%22status%3A%20needs%20clarification%22
https://github.com/bencaterine
bencaterinehttps://github.com/bencaterine
on Nov 11, 2021https://github.com/matplotlib/matplotlib/issues/21595#issue-1050502760
#11956https://github.com/matplotlib/matplotlib/issues/11956
#11972https://github.com/matplotlib/matplotlib/pull/11972
#11956https://github.com/matplotlib/matplotlib/issues/11956
#11972https://github.com/matplotlib/matplotlib/pull/11972
status: needs clarificationIssues that need more information to resolve.https://github.com/matplotlib/matplotlib/issues?q=state%3Aopen%20label%3A%22status%3A%20needs%20clarification%22
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.