payload icon indicating copy to clipboard operation
payload copied to clipboard

Tsx folder in temp directory filled with a lot of files

Open mobeigi opened this issue 1 year ago • 2 comments

Link to reproduction

No response

Environment Info

$ cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload info

Binaries:      
  Node: 20.16.0
  npm: N/A
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  payload: 3.0.0-beta.97
  next: 15.0.0-canary.138
  @payloadcms/db-postgres: 3.0.0-beta.97
  @payloadcms/email-nodemailer: 3.0.0-beta.97
  @payloadcms/graphql: 3.0.0-beta.97
  @payloadcms/next/utilities: 3.0.0-beta.97
  @payloadcms/plugin-cloud: 3.0.0-beta.97
  @payloadcms/plugin-nested-docs: 3.0.0-beta.97
  @payloadcms/plugin-seo: 3.0.0-beta.97
  @payloadcms/richtext-lexical: 3.0.0-beta.97
  @payloadcms/translations: 3.0.0-beta.97
  @payloadcms/ui/shared: 3.0.0-beta.97
  react: 19.0.0-rc-e56f4ae3-20240830
  react-dom: 19.0.0-rc-e56f4ae3-20240830
Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 10 Pro
  Available memory (MB): 65459
  Available CPU cores: 24

Describe the Bug

I am working with Payload V3 in development mode. I am on Windows.

After some days of development I noticed my Windows login speed getting slower and slower. It took my login speed from 1 second to 30 seconds to 2 minutes!

After some research this is caused by a huge number of files in my %TMP% directory. It turns out Payload is creating an insane amount of files in the %TMP% directory as you work with it in dev mode.

I have 900k files created by payload in a directory called tsx-Mo where Mo is my user profile name. All files are a few kb in size each but add up to be gigabytes in total file size due to sheer number of files.

Example of files created:

File name

Looks like: 17258-32e4dc7dfab8b9325c327612393a49ed992d5e71.txt

Example 1

{"code":"(()=>{\nvar __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __name=(target,value)=>__defProp(target,\"name\",{value,configurable:true});var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var getCollectionIDFieldTypes_exports={};__export(getCollectionIDFieldTypes_exports,{getCollectionIDFieldTypes:()=>getCollectionIDFieldTypes});module.exports=__toCommonJS(getCollectionIDFieldTypes_exports);function getCollectionIDFieldTypes({config,defaultIDType}){return config.collections.reduce((acc,collection)=>{const customCollectionIdField=collection.fields.find(field=>\"name\"in field&&field.name===\"id\");acc[collection.slug]=defaultIDType===\"text\"?\"string\":\"number\";if(customCollectionIdField){acc[collection.slug]=customCollectionIdField.type===\"number\"?\"number\":\"string\"}return acc},{})}__name(getCollectionIDFieldTypes,\"getCollectionIDFieldTypes\");0&&(module.exports={getCollectionIDFieldTypes});\n})()\n","warnings":[],"map":{"version":3,"mappings":";suBAAA,8MAIW,SAAS,0BAA0B,CAAE,OAAQ,aAAc,EAAG,CACrE,OAAO,OAAO,YAAY,OAAO,CAAC,IAAK,aAAa,CAChD,MAAM,wBAA0B,WAAW,OAAO,KAAM,OAAQ,SAAU,OAAS,MAAM,OAAS,IAAI,EACtG,IAAI,WAAW,IAAI,EAAI,gBAAkB,OAAS,SAAW,SAC7D,GAAI,wBAAyB,CACzB,IAAI,WAAW,IAAI,EAAI,wBAAwB,OAAS,SAAW,SAAW,QAClF,CACA,OAAO,GACX,EAAG,CAAC,CAAC,CACT,CAToB","names":[],"ignoreList":[],"sources":["C:\\Git\\mobeigi.com\\app\\node_modules\\payload\\dist\\utilities\\getCollectionIDFieldTypes.js"],"sourcesContent":[null]}}

Example 2

{"code":"(()=>{\nvar __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __name=(target,value)=>__defProp(target,\"name\",{value,configurable:true});var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from===\"object\"||typeof from===\"function\"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toCommonJS=mod=>__copyProps(__defProp({},\"__esModule\",{value:true}),mod);var populateBreadcrumbs_exports={};__export(populateBreadcrumbs_exports,{populateBreadcrumbs:()=>populateBreadcrumbs});module.exports=__toCommonJS(populateBreadcrumbs_exports);var import_formatBreadcrumb=require(\"./formatBreadcrumb.js\");var import_getParents=require(\"./getParents.js\");const populateBreadcrumbs=__name(async(req,pluginConfig,collection,data,originalDoc)=>{const newData=data;const breadcrumbDocs=[...await(0,import_getParents.getParents)(req,pluginConfig,collection,{...originalDoc,...data})];const currentDocBreadcrumb={...originalDoc,...data};if(originalDoc?.id){currentDocBreadcrumb.id=originalDoc?.id}breadcrumbDocs.push(currentDocBreadcrumb);const breadcrumbs=breadcrumbDocs.map((_,i)=>(0,import_formatBreadcrumb.formatBreadcrumb)(pluginConfig,collection,breadcrumbDocs.slice(0,i+1)));return{...newData,[pluginConfig?.breadcrumbsFieldSlug||\"breadcrumbs\"]:breadcrumbs}},\"populateBreadcrumbs\");0&&(module.exports={populateBreadcrumbs});\n})()\n","warnings":[],"map":{"version":3,"mappings":";suBAAA,4MAAiC,iCACjC,sBAA2B,2BACpB,MAAM,oBAAsB,aAAO,IAAK,aAAc,WAAY,KAAM,cAAc,CACzF,MAAM,QAAU,KAChB,MAAM,eAAiB,CACnB,GAAG,QAAM,8BAAW,IAAK,aAAc,WAAY,CAC/C,GAAG,YACH,GAAG,IACP,CAAC,CACL,EACA,MAAM,qBAAuB,CACzB,GAAG,YACH,GAAG,IACP,EACA,GAAI,aAAa,GAAI,CACjB,qBAAqB,GAAK,aAAa,EAC3C,CACA,eAAe,KAAK,oBAAoB,EACxC,MAAM,YAAc,eAAe,IAAI,CAAC,EAAG,OAAI,0CAAiB,aAAc,WAAY,eAAe,MAAM,EAAG,EAAI,CAAC,CAAC,CAAC,EACzH,MAAO,CACH,GAAG,QACH,CAAC,cAAc,sBAAwB,aAAa,EAAG,WAC3D,CACJ,EArBmC","names":[],"ignoreList":[],"sources":["C:\\Git\\mobeigi.com\\app\\node_modules\\@payloadcms\\plugin-nested-docs\\dist\\utilities\\populateBreadcrumbs.js"],"sourcesContent":[null]}}

Reproduction Steps

  1. Setup Payload v3 project
  2. Start dev mode yarn dev and work with it for some itme
  3. Notice the build up of files in %TMP%
  4. Windows login process will become slower and slower as the files build up.

Adapters and Plugins

No response

mobeigi avatar Sep 11 '24 05:09 mobeigi

I've run into this issue as well, and managed to narrow down the source of the problem.

I've started working with Payload 3 two weeks ago. Since then, over time, I've noticed Windows boot time was getting progressively longer, up to four minutes long. I've ran Windows Performance Recorder on boot and analyzed the trace.

I found out svchost was maxing out the CPU while processing one directory - C:/Users/[username]/AppData/Local/Temp/tsx-[username].

Directory contained over a milion of small (few KB each) files, with filenames like 17335-0a5134d8a3380f018513b12d4ac11a8c7f5f3dfa Clearing out the directory solved the long boot time issue.

In VSCode I've opened Process Explorer, then opened my Payload project and started dev mode npm run dev. When saving any of the project files, Process Explorer shows a bin.js file being called at [payloadprojectname]\node_modules\payload\bin.js path, and at the same time the amount of files in temp directory grows by a few hundred.

I've opened the bin.js file, commented out everything in it, and now no files are being generated in temp directory after saving a project file.

I'm entirely new to Node, React, Next and Payload, so I don't have necessary knowledge to understand what exactly bin.js is doing, but something in it is responsible for this behavior.

Im running:

Windows 10
VSCode: 1.95.3
Node.js: 20.18.0
Next: 15.0.3
Payload: 3.4.0
React: 19.0.0-rc-66855b96-20241106

pan-czlowiek avatar Dec 07 '24 14:12 pan-czlowiek

I've found code responsible for this behavior, and a workaround for this.

When Payload's generate:types is executed (either automatically on file save, or manually from the terminal) it invokes \payload\bin.js, this part specifically:

if (!useSwc) {
  const start = async () => {
    // Use tsx
    let tsImport = (await import('tsx/esm/api')).tsImport

    const { bin } = await tsImport('./dist/bin/index.js', url)
    await bin()
  }
  void start()
(...)
}

It utilizes Type Script Execute which creates a temp folder using Windows user name as an id and, on Windows, it doesn't clean up after itself. It's not a bug, it's like that by design. This is a Windows specific issue.

Workaround

TSX temp folder path is generated by \node_modules\.pnpm\node_modules\tsx\dist\temporary-directory-CwHp0_NW.mjs file. Path can be overwritten there.

I've set up a RamDisk (I'm using ImDisk) and hardcoded the TSX temp path to it.

It's more of a hack than a solution, but it works fine and my SSD is not getting spammed with thousands of unnecessary write cycles anymore.

pan-czlowiek avatar Dec 19 '24 04:12 pan-czlowiek

@pan-czlowiek Thanks for the investigation work! I haven't worked with Payload in some time, I am now updating everything to the latest and seeing if this issue reoccurs for me again (I was on Windows 10 but am now on Windows 11 but that likely makes no difference).

mobeigi avatar Jan 15 '25 01:01 mobeigi

So it looks like an OS "issue" - Mac cleans up after 3 days.

  • Linux info: https://serverfault.com/questions/377348/when-does-tmp-get-cleared/377349#377349
  • Windows info: https://superuser.com/questions/318497/do-files-in-the-temporary-folders-get-automatically-deleted/1599897#1599897

JarrodMFlesch avatar Jul 14 '25 15:07 JarrodMFlesch

This issue has been automatically locked. Please open a new issue if this issue persists with any additional detail.

github-actions[bot] avatar Jul 22 '25 05:07 github-actions[bot]