-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memory leak in lazy relation #6631
Comments
Did a bit of experimentation & setting up a test case for this.. Does not fail when you're just re-saving the created model over and over. The In the This issue does NOT occur if you set the const problem = new Problem();
problem.problemId = String(i);
(problem as any).__source__ = source;
await repository.save(problem); After changing the test up a bit & timing them separately, both the After doing some profiling - |
Holy wowza, something is causing this to double the number of queries for That's definitely not right.. |
Looks like the initial call in The last parameter is As far as the out of memory.. I think that's a side effect. There's definitely some places where we can improve the GC characteristics but loading millions of the same model seems to be a problem. |
I think I'm seeing a similar problem in Sql.js (which is just sqlite transpiled to web assembly). I'm using it to write tests, and there seems to be an infinite loop of queries after my query returns in my test. The queries all looked like they were loading related columns. Some very hacky debugging got me to this
The entity is iterated over as part of some logic to transform the results into an entity. It looks like by iterating over the entity, more relation queries are kicked off and are attempted to be loaded. I don't really see anything checking whether or not the entity's properties are lazy in that loop like I do in |
@pleerock sorry for the direct @ here. Is there a mechanism in |
Ok, I did some more debugging and I think I found the source of this bug @pleerock. Let me know if you'd like me to open up a separate issue for this. DetailsIt looks like, by default, defining a property doesn't make it visible to
However, for some reason, entities in you can see this entity (Meter) having lazy relations ( and this call to I dug in a little further. I stepped into HOWEVER: look at what That made me wonder if In other words, by defining the keys for a lazy relationship on an entity before the lazy relationship is created, those lazy relations inadvertently get called when hydrating results. I haven't yet figured out why those properties are instantiated to undefined or why this only seems to happen with Sql.js (and not with our production MySQL-flavored database), but this feels like enough digging to identify the issue. If you're curious, click here to see the source for MeterEntityMy MeterEntity looks like this ( @Entity("meter")
export class MeterEntity implements S_Meter {
@PrimaryColumn()
id!: string;
@Column({ name: "is_archived" })
isArchived!: boolean;
@Column("text", { nullable: true })
description!: string | null;
@Column("varchar", { name: "meter_type" })
meterType!: MeterType;
@Column({ name: "is_incremental" })
isIncremental!: boolean;
@Column("varchar", { name: "unit_name", nullable: true })
unitName!: string | null;
@Column("varchar")
name!: string;
@Column("varchar", { name: "display_name" })
displayName!: string;
@CreateDateColumn({ name: "created_at" })
createdAt!: string;
@ManyToOne(() => VendorEntity, (vendor) => vendor.meters)
@JoinColumn({ name: "vendor_id" })
vendor!: Promise<VendorEntity>;
@OneToMany(() => MeteredComponentEntity, (mc) => mc.meter)
meteredComponents!: Promise<MeteredComponentEntity[]>;
} |
In some environments it seems like entity object was created with columns values set to undefined, thus Object.defineProperty uses already defined value for enumerable - true. Which leads to RawSqlResultsToEntityTransformer.transform() run getters on relation fields (as they was enumerable) resolving the promises - running queries which eventually leads to the Free memory exhaustion on the machine :) Closes: typeorm#6631
In some environments it seems like entity object was created with columns values set to undefined, thus Object.defineProperty uses already defined value for enumerable - true. Which leads to RawSqlResultsToEntityTransformer.transform() run getters on relation fields (as they was enumerable) resolving the promises - running queries which eventually leads to the Free memory exhaustion on the machine :) Closes: typeorm#6631
In some environments it seems like entity object was created with columns values set to undefined, thus Object.defineProperty uses already defined value for enumerable - true. Which leads to RawSqlResultsToEntityTransformer.transform() run getters on relation fields (as they was enumerable) resolving the promises - running queries which eventually leads to the Free memory exhaustion on the machine :) Closes: typeorm#6631
Thanks, @imnotjames and @salemhilal for debugging the issue it really helped me to pin it down! const orgObjectDefineProperty = Object.defineProperty;
Object.defineProperty = (obj, property, attributes) => orgObjectDefineProperty(obj, property, {
...attributes,
enumerable: (attributes.enumerable === true)
}); I spend quite some time, trying to replicate the issue by writing a test case for it to fail. |
In some environments it seems like entity object was created with columns values set to undefined, thus Object.defineProperty uses already defined value for enumerable - true. Which leads to RawSqlResultsToEntityTransformer.transform() run getters on relation fields (as they were enumerable) resolving the promises - running queries which eventually leads to the Free memory exhaustion on the machine :) Closes: typeorm#6631
) In some environments it seems like entity object was created with columns values set to undefined, thus Object.defineProperty uses already defined value for enumerable - true. Which leads to RawSqlResultsToEntityTransformer.transform() run getters on relation fields (as they were enumerable) resolving the promises - running queries which eventually leads to the Free memory exhaustion on the machine :) Closes: #6631
Issue type:
[x] bug report
[ ] feature request
[ ] documentation issue
Database system/driver:
[ ]
cordova
[ ]
mongodb
[ ]
mssql
[ ]
mysql
/mariadb
[ ]
oracle
[x]
postgres
[ ]
cockroachdb
[x]
sqlite
[ ]
sqljs
[ ]
react-native
[ ]
expo
TypeORM version:
[x]
latest
[ ]
@next
[ ]
0.x.x
(or put your version here)Steps to reproduce or a small repository showing the problem:
output:
I tried
postgres
andsqlite
, the result is the same. There is a huge performance gap when usingnew
andcreate
.English is not my native language; please excuse typing errors.
The text was updated successfully, but these errors were encountered: