package com.yef.tools.measure.mongodb;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.bson.UuidRepresentation;
import org.bson.codecs.UuidCodec;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;

import java.util.ArrayList;
import java.util.List;

public class MeasureDocumentInsertion {

    private static final String MONGODB_HOST = "localhost";
    private static final Integer MONGODB_PORT = 27017;
    private static final String DATABASE_NAME = "testDb";
    public static final String COLLECTION_NAME = "testCollection";
    MongoClient mongoClient;
    MongoDatabase database;


    public MeasureDocumentInsertion() {
        mongoClient = new MongoClient(MONGODB_HOST, MONGODB_PORT);
        CodecRegistry codecRegistry =
                CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(new UuidCodec(UuidRepresentation.STANDARD)),
                        MongoClient.getDefaultCodecRegistry());
        MongoClientOptions options = MongoClientOptions.builder()
                .codecRegistry(codecRegistry).build();
        MongoClient client = new MongoClient(new ServerAddress(), options);
        database = client.getDatabase(DATABASE_NAME);
    }

    public static void main(String[] args) {
        MeasureDocumentInsertion main = new MeasureDocumentInsertion();
        main.measureOneByOneInsertion();
        main.measureBulkInsertion();
    }

    private void measureOneByOneInsertion() {
        int num = 100000;
        MongoCollection<Document> collection = database.getCollection(COLLECTION_NAME);
        collection.drop();
        long timeBefore = System.currentTimeMillis();
        for (int i = 0; i < num; i++) {
            collection.insertOne(new Document("key1", "value" + i));
        }
        Document statsAfter = database.runCommand(new Document("collStats", COLLECTION_NAME).append("scale", 1));
        long timeAfter = System.currentTimeMillis();
        printResults(num, statsAfter, timeBefore, timeAfter);
    }

    private void measureBulkInsertion() {
        int num = 1000000;
        MongoCollection<Document> collection = database.getCollection(COLLECTION_NAME);
        collection.drop();
        System.gc();
        Runtime rt = Runtime.getRuntime();
        long memoryBefore = rt.totalMemory() - rt.freeMemory();
        long timeBefore = System.currentTimeMillis();
        List<Document> docs = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            docs.add(new Document("key1", "value" + i));
        }
        collection.insertMany(docs);
        Document statsAfter = database.runCommand(new Document("collStats", COLLECTION_NAME).append("scale", 1));
        long timeAfter = System.currentTimeMillis();
        System.gc();
        long memoryAfter = rt.totalMemory() - rt.freeMemory();
        printResults(num, statsAfter, timeBefore, timeAfter, "JVM memory used for collection: " + (memoryAfter - memoryBefore) + " bytes");
    }

    private void printResults(int num, Document statsAfter, long timeBefore, long timeAfter, String... addition) {
        System.out.println("-----------------------");
        System.out.println("Count of documents in collection '" + COLLECTION_NAME + "': " + num);
        System.out.println("Collection Size: " + statsAfter.get("size") + " bytes");
        System.out.println("Size per document from stats: " + statsAfter.get("avgObjSize") + " bytes");
        System.out.println("Calculated size per document: " + ((double) statsAfter.getInteger("size")) / num + " bytes");
        System.out.println("Total time for insertion " + num + " documents: " + ((double) (timeAfter - timeBefore)) / 1000 + " s");
        System.out.println("Insertion time per document: " + ((double) (timeAfter - timeBefore)) / num + " ms");
        for (String string : addition) System.out.println(string);
        System.out.println("-----------------------");
    }
}

@@ -519,894 +519,98 @@
 ion 
-%7B%0A%0A    private static final String MONGODB_HOST = %22localhost%22;%0A    private static final Integer MONGODB_PORT = 27017;%0A    private static final String DATABASE_NAME = %22testDb%22;%0A    public static final String COLLECTION_NAME = %22testCollection%22;%0A    MongoClient mongoClient;%0A    MongoDatabase database;%0A%0A%0A    public MeasureDocumentInsertion() %7B%0A        mongoClient = new MongoClient(MONGODB_HOST, MONGODB_PORT);%0A        CodecRegistry codecRegistry =%0A                CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(new UuidCodec(UuidRepresentation.STANDARD)),%0A                        MongoClient.getDefaultCodecRegistry());%0A        MongoClientOptions options = MongoClientOptions.builder()%0A                .codecRegistry(codecRegistry).build();%0A        MongoClient client = new MongoClient(new ServerAddress(), options);%0A        database = client.getDatabase(DATABASE_NAME);%0A    %7D
+extends BaseMeasure %7B%0A%0A    private static final String COLLECTION_NAME = %22testCollection%22;
 %0A%0A  
@@ -2366,958 +2366,6 @@
  %7D%0A%0A
-    private void printResults(int num, Document statsAfter, long timeBefore, long timeAfter, String... addition) %7B%0A        System.out.println(%22-----------------------%22);%0A        System.out.println(%22Count of documents in collection '%22 + COLLECTION_NAME + %22': %22 + num);%0A        System.out.println(%22Collection Size: %22 + statsAfter.get(%22size%22) + %22 bytes%22);%0A        System.out.println(%22Size per document from stats: %22 + statsAfter.get(%22avgObjSize%22) + %22 bytes%22);%0A        System.out.println(%22Calculated size per document: %22 + ((double) statsAfter.getInteger(%22size%22)) / num + %22 bytes%22);%0A        System.out.println(%22Total time for insertion %22 + num + %22 documents: %22 + ((double) (timeAfter - timeBefore)) / 1000 + %22 s%22);%0A        System.out.println(%22Insertion time per document: %22 + ((double) (timeAfter - timeBefore)) / num + %22 ms%22);%0A        for (String string : addition) System.out.println(string);%0A        System.out.println(%22-----------------------%22);%0A    %7D%0A
 %7D%0A

Add base class