查询mongoDB时,dotnet会分配大量内存
我的应用程序使用了很多内存,因为我经常查询数据库。我正在发布我的C#代码,希望有人能告诉我我在做什么错。我还使用Google GO语言创建了相同的程序,以比较内存使用量。 C#上的同一程序使用超过1 GB的内存,并且GO仅使用100MB。 C#在堆上创建了数千个分配,只有少数几个。最后,C#花了3秒钟的时间来编译发布模式,并且仅进行毫秒。
C#代码:
var mongoDb = new MongoClient("mongodb://localhost:27017").GetDatabase("MyTestDb");
var collection = mongoDb.GetCollection<Account>("Accounts");
// find all items on collection named Accounts
var items = collection.Find("{}").ToEnumerable();
int counter = 0;
foreach (var a in items)
counter++;
Console.WriteLine(ctr2);
// I am naming my properties incorrectly just to make the code shorter and avoid having a converter
[BsonIgnoreExtraElements]
public class Account
{
public string _id { get; set; }
public string dateCreated{ get; set; }
public string dateDeleted{ get; set; }
public string dateUpdated{ get; set; }
public string idCloudServicePbxFailover{ get; set; }
public string idCloudServiceWebApp{ get; set; }
public bool hasGrantedSupportAccess{ get; set; }
}
如果我使用profiler运行此代码,例如valgrind
我会得到此结果:
==132531== HEAP SUMMARY:
==132531== in use at exit: 96,284,945 bytes in 14,388 blocks
==132531== total heap usage: 105,120 allocs, 90,732 frees, 177,448,116 bytes allocated
==132531==
==132531== LEAK SUMMARY:
==132531== definitely lost: 200 bytes in 8 blocks
==132531== indirectly lost: 0 bytes in 0 blocks
==132531== possibly lost: 42,416 bytes in 145 blocks
==132531== still reachable: 96,242,329 bytes in 14,235 blocks
==132531== of which reachable via heuristic:
==132531== stdstring : 41,313 bytes in 52 blocks
==132531== newarray : 48 bytes in 1 blocks
==132531== suppressed: 0 bytes in 0 blocks
==132531== Rerun with --leak-check=full to see details of leaked memory
如果我使用linux的time
命令,我会得到此结果:
./bin/Release/net6.0/MyTestApp 7.48s user 0.88s system 71% cpu 11.645 total
avg shared (code): 0 KB
avg unshared (data/stack): 0 KB
total (sum): 0 KB
max memory: 1867 MB
page faults from disk: 1
other page faults: 470073
最后,如果我运行<代码> HTOP 在Linux上我看到我的内存上升超过1 GB。
我无法将我的帐户
类更改为struct
,因为Mongo不支持结构。我希望做出这一更改,以减少内存分配。
无论如何,如果我运行了与Google一起使用相同操作的相同程序,这是结果:
GO代码:
package main
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
// "go.mongodb.org/mongo-driver/mongo/options"
// "go.mongodb.org/mongo-driver/x/mongo/driver/mongocryp"
)
type Account struct {
ID string `json:"_id,omitempty" bson:"_id,omitempty"`
DateCreated string `json:"dateCreated,omitempty" bson:"dateCreated,omitempty"`
DateDeleted string `json:"dateDeleted,omitempty" bson:"dateDeleted,omitempty"`
DateUpdated string `json:"dateUpdated,omitempty" bson:"dateUpdated,omitempty"`
IdCloudServicePbxFailover string `json:"idCloudServicePbxFailover,omitempty" bson:"idCloudServicePbxFailover,omitempty"`
IdCloudServiceWebApp string `json:"idCloudServiceWebApp,omitempty" bson:"idCloudServiceWebApp,omitempty"`
CompanyName string `json:"CompanyName,omitempty" bson:"CompanyName,omitempty"`
HasGrantedSupportAccess bool `json:"hasGrantedSupportAccess,omitempty" bson:"hasGrantedSupportAccess,omitempty"`
}
var client *mongo.Client
const conString = "mongodb://localhost:27017"
const dbName = "MyTestDb"
const colName = "Accounts"
var collection *mongo.Collection
func main() {
fmt.Println("Testing mongo")
clientOption := options.Client().ApplyURI(conString)
client, err := mongo.Connect(context.Background(), clientOption)
if err != nil {
log.Fatal(err)
}
fmt.Println("MongoDB connected")
if client == nil {
fmt.Println("foooo")
}
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
// cursor, err := client.Database(dbName).Collection(colName).Find(ctx, bson.D{{"dateCreated", bson.D{{"$gt", "2020"}}}})
cursor, err := client.Database(dbName).Collection(colName).Find(ctx, bson.M{})
if err != nil {
log.Fatal(err)
}
defer cursor.Close(ctx)
ctr := 0
for cursor.Next(ctx) {
ctr++
var acc Account
cursor.Decode(&acc)
// if acc.ID == "96e0a7f6-5b6d-4a10-9b3d-c5d8275fdb1f" {
// break
// }
}
fmt.Println(ctr)
}
这是valgrim
输出:
==135050== HEAP SUMMARY:
==135050== in use at exit: 2,016 bytes in 7 blocks
==135050== total heap usage: 15 allocs, 8 frees, 2,240 bytes allocated
==135050==
==135050== LEAK SUMMARY:
==135050== definitely lost: 0 bytes in 0 blocks
==135050== indirectly lost: 0 bytes in 0 blocks
==135050== possibly lost: 2,016 bytes in 7 blocks
==135050== still reachable: 0 bytes in 0 blocks
==135050== suppressed: 0 bytes in 0 blocks
==135050== Rerun with --leak-check=full to see details of leaked memory
这是time ./mongodb--去
:
./mongodb-go 4.99s user 0.44s system 72% cpu 7.463 total
avg shared (code): 0 KB
avg unshared (data/stack): 0 KB
total (sum): 0 KB
max memory: 100 MB
page faults from disk: 0
other page faults: 21916
My application is using a lot of memory because I am querying my database a lot. I am posting my C# code hoping someone can tell me what am I doing wrong. I have also created the same program using Google Go language in order to compare memory usage. The same program on C# uses over 1 GB of memory and Go only uses 100MB. C# creates thousands of allocations on the heap and Go only a few. Lastly C# took 3 seconds to compile on release mode and Go only milliseconds.
C# code:
var mongoDb = new MongoClient("mongodb://localhost:27017").GetDatabase("MyTestDb");
var collection = mongoDb.GetCollection<Account>("Accounts");
// find all items on collection named Accounts
var items = collection.Find("{}").ToEnumerable();
int counter = 0;
foreach (var a in items)
counter++;
Console.WriteLine(ctr2);
// I am naming my properties incorrectly just to make the code shorter and avoid having a converter
[BsonIgnoreExtraElements]
public class Account
{
public string _id { get; set; }
public string dateCreated{ get; set; }
public string dateDeleted{ get; set; }
public string dateUpdated{ get; set; }
public string idCloudServicePbxFailover{ get; set; }
public string idCloudServiceWebApp{ get; set; }
public bool hasGrantedSupportAccess{ get; set; }
}
If I run this code with a profiler like valgrind
I get this result:
==132531== HEAP SUMMARY:
==132531== in use at exit: 96,284,945 bytes in 14,388 blocks
==132531== total heap usage: 105,120 allocs, 90,732 frees, 177,448,116 bytes allocated
==132531==
==132531== LEAK SUMMARY:
==132531== definitely lost: 200 bytes in 8 blocks
==132531== indirectly lost: 0 bytes in 0 blocks
==132531== possibly lost: 42,416 bytes in 145 blocks
==132531== still reachable: 96,242,329 bytes in 14,235 blocks
==132531== of which reachable via heuristic:
==132531== stdstring : 41,313 bytes in 52 blocks
==132531== newarray : 48 bytes in 1 blocks
==132531== suppressed: 0 bytes in 0 blocks
==132531== Rerun with --leak-check=full to see details of leaked memory
If I use the time
command from Linux I get this result:
./bin/Release/net6.0/MyTestApp 7.48s user 0.88s system 71% cpu 11.645 total
avg shared (code): 0 KB
avg unshared (data/stack): 0 KB
total (sum): 0 KB
max memory: 1867 MB
page faults from disk: 1
other page faults: 470073
Lastly if I run htop
on Linux I see that my memory goes up more than 1 GB.
I cannot change my Account
class to a struct
because Mongo does not support structs. I was hoping to make this change in order to reduce memory allocations.
Anyways if I run the same program that does the same thing with Go from Google this are the results:
Go code:
package main
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
// "go.mongodb.org/mongo-driver/mongo/options"
// "go.mongodb.org/mongo-driver/x/mongo/driver/mongocryp"
)
type Account struct {
ID string `json:"_id,omitempty" bson:"_id,omitempty"`
DateCreated string `json:"dateCreated,omitempty" bson:"dateCreated,omitempty"`
DateDeleted string `json:"dateDeleted,omitempty" bson:"dateDeleted,omitempty"`
DateUpdated string `json:"dateUpdated,omitempty" bson:"dateUpdated,omitempty"`
IdCloudServicePbxFailover string `json:"idCloudServicePbxFailover,omitempty" bson:"idCloudServicePbxFailover,omitempty"`
IdCloudServiceWebApp string `json:"idCloudServiceWebApp,omitempty" bson:"idCloudServiceWebApp,omitempty"`
CompanyName string `json:"CompanyName,omitempty" bson:"CompanyName,omitempty"`
HasGrantedSupportAccess bool `json:"hasGrantedSupportAccess,omitempty" bson:"hasGrantedSupportAccess,omitempty"`
}
var client *mongo.Client
const conString = "mongodb://localhost:27017"
const dbName = "MyTestDb"
const colName = "Accounts"
var collection *mongo.Collection
func main() {
fmt.Println("Testing mongo")
clientOption := options.Client().ApplyURI(conString)
client, err := mongo.Connect(context.Background(), clientOption)
if err != nil {
log.Fatal(err)
}
fmt.Println("MongoDB connected")
if client == nil {
fmt.Println("foooo")
}
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
// cursor, err := client.Database(dbName).Collection(colName).Find(ctx, bson.D{{"dateCreated", bson.D{{"$gt", "2020"}}}})
cursor, err := client.Database(dbName).Collection(colName).Find(ctx, bson.M{})
if err != nil {
log.Fatal(err)
}
defer cursor.Close(ctx)
ctr := 0
for cursor.Next(ctx) {
ctr++
var acc Account
cursor.Decode(&acc)
// if acc.ID == "96e0a7f6-5b6d-4a10-9b3d-c5d8275fdb1f" {
// break
// }
}
fmt.Println(ctr)
}
This is valgrim
output:
==135050== HEAP SUMMARY:
==135050== in use at exit: 2,016 bytes in 7 blocks
==135050== total heap usage: 15 allocs, 8 frees, 2,240 bytes allocated
==135050==
==135050== LEAK SUMMARY:
==135050== definitely lost: 0 bytes in 0 blocks
==135050== indirectly lost: 0 bytes in 0 blocks
==135050== possibly lost: 2,016 bytes in 7 blocks
==135050== still reachable: 0 bytes in 0 blocks
==135050== suppressed: 0 bytes in 0 blocks
==135050== Rerun with --leak-check=full to see details of leaked memory
and here is the output of time ./mongodb-go
:
./mongodb-go 4.99s user 0.44s system 72% cpu 7.463 total
avg shared (code): 0 KB
avg unshared (data/stack): 0 KB
total (sum): 0 KB
max memory: 100 MB
page faults from disk: 0
other page faults: 21916
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论