Indexeddb with datatables table.row.add.draw() slow render

Indexeddb with datatables table.row.add.draw() slow render

edysedys Posts: 7Questions: 2Answers: 0
edited June 2022 in Free community support

Hello i have indexeddb which draw into datatables. a new row add into the tables every 2-3 seconds. but the render performance is slow and show double multiplication from the real data in indexeddb. any advice would be helpful and appreciate. Thanks!

<script>
    var table = $("#example1").DataTable({
        "responsive": true,
        "deferRender": true,
        "orderClasses": false,
        "bDeferRender": true,
        "bProcessing": true,
        "bSortClasses": false,
        "oLanguage": {
                "sSearch": "Pencarian",
                "sLengthMenu": "Tampilkan _MENU_",
                "sLoadingRecords": "Mohon tunggu - sedang mengambil data dari server...",
                "sEmptyTable": "Belum ada data",
                "sInfoEmpty": "Menampilkan 0 - 0 dari 0 data",
                "sInfo": "Menampilkan _START_ - _END_ dari _TOTAL_ data",
                "sInfoFiltered":   "(Dicari dari _MAX_ total data)",
                "sZeroRecords":    "Data yang dicari tidak ada yang sesuai",
                "oPaginate": {                       
                        "sNext": '<i class="fa fa-angle-right" ></i>',
                        "sPrevious": '<i class="fa fa-angle-left"" ></i>'
                },
            },
            "order": [[ 0, "desc" ]],
            "deferRender": true,
            "orderClasses": false,
            "bDeferRender": true,
            "bProcessing": true,
            "bSortClasses": false,
            columnDefs: [{
                    targets: 1,
                    title: 'Berat',
                    render: function(data, type, full, meta) {
                        return data+' Kg';
                    },
                },
                {
                    targets: 0,
                    render: function(data, type, full, meta) {
                        return meta.row + 1;
                    },
                },
                {
                    targets: -1,
                    width:'40px',
                    render: function(data, type, full, meta) {
                        return '<button class="btn btn-danger btn-sm btn-icon" onclick="remove('+data+')"><i class="fa fa-times"></i></button>';
                    },
                }
            ],
    });
</script>
<script type = "text/javascript">
function readAll() {
        nomor=1;
        var bruto=0;
        var objectStore = db.transaction("berat").objectStore("berat");
        table.clear();
        objectStore.openCursor().onsuccess = function(event) {
            var cursor = event.target.result;
            if (cursor) {
                idtemp = cursor.value.id+1;
                if(idtemp>idkeys){
                    idkeys=cursor.value.id+1;
                }
                //alert("Name for id " + cursor.key + " is " + cursor.value.berat + ", Tanggal: " + cursor.value.datetime);
                //table.row.add( [cursor.key,cursor.value.berat,cursor.value.datetime,cursor.value.id] ).draw();
                table.row.add( [cursor.key,cursor.value.berat,cursor.value.datetime,cursor.value.id] ).page('first').draw();
                bruto = parseFloat(bruto) + parseFloat(cursor.value.berat);
                cursor.continue();
                nomor++;
            }
            document.getElementById('bruto').value=bruto.toFixed(2);
            if(bruto.toFixed(2) == '0.00'){
                table.clear().draw();
            }
        };
        document.getElementById('overlay').style.display='none';
        document.getElementById('addbutton_hide').style.display='none';
        document.getElementById('addbutton_show').style.display='block';
    }

function add() {
        document.getElementById('addbutton_show').style.display='none';
        document.getElementById('addbutton_hide').style.display='block';
        setTimeout(function () {
            fetch("http://localhost:8000/httplistener/")
            .then(response => response.json())
            .then(function(data1) {
                //console.log(data1);
                //document.getElementById('berat').value=data1.Berat;
                var cekberat=data1.Berat;
                if(cekberat>0){
                    document.getElementById('berat').value=data1.Berat;
                    var id=idkeys;
                    var bruto = document.getElementById('bruto').value;
                    var weight = document.getElementById('berat').value;
                    var currentdate = new Date(); 
                    var datetimes = currentdate.getFullYear() + "-"+ (currentdate.getMonth()+1)  + "-" + currentdate.getDate() + " "  + currentdate.getHours() + ":" + currentdate.getMinutes() + ":" + currentdate.getSeconds();
                    var request = db.transaction(["berat"], "readwrite").objectStore("berat").add({ berat: weight, datetime: datetimes });
                    request.onsuccess = function(event) {
                        document.getElementById('berat').focus();
                        bruto = parseFloat(bruto) + parseFloat(weight);
                        document.getElementById('bruto').value=bruto.toFixed(2);
                        //readAll();
                        document.getElementById('berat').value=data1.Berat;
                        //document.getElementById('berat').value='';
                    };
                    request.onerror = function(event) {
                        console.log("Unable to add data\r\Data is aready exist in your database! ");
                        document.getElementById('addbutton_hide').style.display='none';
                        document.getElementById('addbutton_show').style.display='block';
                    }
                    if(counter==sample){
                        keysample++;
                        var hitungsample = keysample;
                        document.getElementById('hitungsample').value=hitungsample;
                        playSound();
                        counter=0;
                    } else {
                        playBuzzer();
                    }
                    counter++;
                    nomor++;
                    keycounter++;
                    var hitungtimbang = keycounter;
                    document.getElementById('hitungtimbang').value=hitungtimbang;
                    readAll();
                    //cetak(nomor,weight);
                    //nomor++;
                } else {
                    window.alert("Berat tidak boleh NOL (0) atau Tunggu Timbangan stabil.")
                    document.getElementById('addbutton_hide').style.display='none';
                    document.getElementById('addbutton_show').style.display='block';
                }
            })
            .catch(function(error) {
            // If there is any error you will catch them here
            window.alert(" GAGAL TERHUBUNG KE INDIKATOR TIMBANGAN\r\ Ikuti langkah berikut :\r\r\ 1.) Sambungkan kabel timbangan ke Laptop\r\ 2.) Jalankan aplikasi pendukung\r\ 3.) Setelah aplikasi pendukung berjalan, berikan timbel ke timbangan\r\ 4.) Tunggu 10-20 detik lalu tekan CEK TIMBEL\r\ 5.) Pastikan berat pada jendela CEK TIMBEL sama dengan indikator timbangan")
            document.getElementById('addbutton_hide').style.display='none';
            document.getElementById('addbutton_show').style.display='block';
            });
        }, 500);
    }

Edited by Colin - Syntax highlighting. Details on how to highlight code using markdown can be found in this guide.

Answers

  • colincolin Posts: 15,118Questions: 1Answers: 2,583

    We're happy to take a look, but as per the forum rules, please link to a test case - a test case that replicates the issue will ensure you'll get a quick and accurate response. Information on how to create a test case (if you aren't able to link to the page you are working on) is available here.

    Cheers,

    Colin

  • edysedys Posts: 7Questions: 2Answers: 0

    Thanks for response Sir.
    I trried to paste my code to live datatables but not looks good. sorry i am new in datatables.
    http://live.datatables.net/rifiviwe/1/

  • edysedys Posts: 7Questions: 2Answers: 0

    is there any approach just render last 10 record?

  • kthorngrenkthorngren Posts: 20,144Questions: 26Answers: 4,736

    a new row add into the tables every 2-3 seconds. but the render performance is slow

    There is nothing obvious in the code that would suggest using row.add() to add one row every. 2-3 seconds would be slow. Looks like you start with an empty table then use row.add() to populate the table. Does it start slow or become slow over time? Have you verified the problem is with row.add() and the time it takes to render the new row? Maybe try a timer like this to see how long it takes:

                if (cursor) {
                    idtemp = cursor.value.id+1;
                    if(idtemp>idkeys){
                        idkeys=cursor.value.id+1;
                    }
                    //alert("Name for id " + cursor.key + " is " + cursor.value.berat + ", Tanggal: " + cursor.value.datetime);
                    //table.row.add( [cursor.key,cursor.value.berat,cursor.value.datetime,cursor.value.id] ).draw();
    
                    var startTime = Date.now();
                    table.row.add( [cursor.key,cursor.value.berat,cursor.value.datetime,cursor.value.id] ).page('first').draw();
                    console.log('Time to add row ', Date.now() - startTime + ' milliseconds.');
    
                    bruto = parseFloat(bruto) + parseFloat(cursor.value.berat);
                    cursor.continue();
                    nomor++;
                }
    

    and show double multiplication from the real data in indexeddb

    What is showing double multiplication?

    As Colin said we will need to see a running test case to help debug. We won't be able to debug performance nor calculations by looking at code snippets.

    is there any approach just render last 10 record?

    Datatables renders the rows being displayed. Looks like your table is set to show 10 rows on the page. when the new row is added Datatbles adds it to its data cache then, if sorting and paging dictates, it will render onto the page.

    Kevin

  • edysedys Posts: 7Questions: 2Answers: 0

    Thanks Sir for response, i attach the google drive project URL below. It contains .zip and .sql file in order to offline debug when needed. I also write some explanation and user access in README.txt inside the drive.

    https://drive.google.com/drive/folders/1T1jrEcL0o2zMJEUmdyG5VwQXKmmInSQY?usp=sharing

    i will periodically check the discussion, thanks you.

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    It would be a great help to us, so we can help you, if you could host it somewhere and just give us a link to we can profile the performance.

    Allan

  • edysedys Posts: 7Questions: 2Answers: 0

    Alright Sir, i hosted in the following url https://deployinsandbox.com/trial/uploadscale_old/public

    Please open the README.txt in the drive (link https://drive.google.com/drive/folders/1T1jrEcL0o2zMJEUmdyG5VwQXKmmInSQY?usp=sharing ). There was login access user and password. Really thanks.

  • kthorngrenkthorngren Posts: 20,144Questions: 26Answers: 4,736

    I'm not familiar with the indexeddb but each time the Tambah Data is clicked your code is fetching all the rows. For example the first time clicked one row of data is fetched. The second time two rows, the third three rows. After 50 clicks then 50 rows of data are fetched. You are clearing (table.clear()) the Datatable each time and adding re-adding all the rows. Each of the 50 rows are added using this:

    table.row.add( [cursor.key,cursor.value.berat,cursor.value.datetime,cursor.value.id] ).draw();
    

    This is calling draw() 50 times which will increase the time it takes to populate the table. The draw() API should only be called once after all the rows are added. You could remove it from the row.add() call and call it once all the rows are added. Not sure where this would go in your solution.

    My suggestion is to fetch only the new row(s) each time the button is clicked. Don't clear the table and just add the newly fetched row. This is not a Datatables issue but in how you structure your code to fetch only the new data from indexeddb.

    It looks like you have event handlers in the all() (request.onsuccess) and readAll() (objectStore.openCursor().onsuccess) functions that are called when the DB accessed. These events are called once for each row added. Maybe there is a way with indexeddb to fetch all the rows at once to call the event handlers once and you can use rows.add() to add all.

    Use the indexeddb docs or maybe a site like Stack Overflow to learn how to use indexeddb in a more efficient manner.

    Kevin

  • kthorngrenkthorngren Posts: 20,144Questions: 26Answers: 4,736

    I forgot to mention that you might want to move the event handler creation in all() (request.onsuccess) and readAll() (objectStore.openCursor().onsuccess) outside the functions so they are only created once. This might help top fetch one row instead of all the previous rows too.

    Kevin

  • edysedys Posts: 7Questions: 2Answers: 0

    thanks for reply Sir, few minutes ago i deployed the readAll() without table.clear() after adding and re-adding rows, based on the scenario where working with indexeddb using datatables not showing amount of data properly rendered compared to amount of data in indexeddb. But when by adding table.clear() before adding row gives better render datatables by showing proper amount of data compared to real stored datas. In the other side, there still same issue happened when datatables rendering process still running at the same time adding new row.. the chaos started. I will try to figure it out regarding suggestion moving the event handler outside functions. Thanks!

Sign In or Register to comment.