Page 1 of 1
InsertJSONList() Crashed on bigger Lists
Posted: Sat Apr 06, 2024 4:54 am
by Bisonte
Windows 10 x64 - PB 6.xx x86 !
InsertJSONList() crashed if the list gets bigger.
In my following example, an IMA occurs directly at Max = 200,000 .... at 100,000 not yet.
It doesn't matter whether you use ASM or C-Backend.
With x64 the whole thing is no problem,
it rushes through without an error message, no matter how large the list is.
Code: Select all
Structure s_resultItem
AsString.s
AsNumber.q
EndStructure
Structure s_result
Map Column.s_resultItem()
EndStructure
NewList Row.s_result()
Procedure.i ExportResults(FileName.s, List Row.s_result())
Protected jSon = CreateJSON(#PB_Any, #PB_JSON_NoCase)
Protected Result = #False
If jSon
Debug ListSize(Row())
InsertJSONList(JSONValue(jSon), Row())
Result = SaveJSON(jSon, FileName, #PB_JSON_PrettyPrint)
FreeJSON(jSon)
EndIf
ProcedureReturn Result
EndProcedure
Filename.s = "R:\testfile.json" ; Change it !
Max = 200000 ; IMA at InsertJSONList()
;Max = 100000 ; No Error
For i=1 To Max
AddElement(Row())
For x = 65 To 89
Row()\Column(Chr(x))\AsString = Chr(x) + "a1"
Row()\Column(Chr(x))\AsNumber = Random(200000, 0)
Next x
Next i
ExportResults(Filename, Row())
Re: InsertJSONList() Crashed on bigger Lists
Posted: Sat Apr 06, 2024 9:35 am
by juergenkulow
Code: Select all
; InsertJSONList with 19,000,000 list elements Win x86 ERROR_NOT_ENOUGH_MEMORY
NewList Names.s()
For i=1 To 19000000
AddElement(Names()): Names() = Str(i)
Next
If CreateJSON(0)
InsertJSONList(JSONValue(0), Names())
Debug "Ready"
EndIf
; [09:54:13] Warte auf den Start des Executable...
; [09:54:13] Executable-Typ: Windows - x86 (32bit, Unicode)
; [09:54:13] Executable gestartet.
; [09:54:25] [ERROR] Zeile: 7
; [09:54:25] [ERROR] Ungültiger Speicherzugriff. (Schreibfehler an der Adresse 3)
; 00424EAC | 8848 03 | mov byte ptr ds:[eax+3],cl |
; EAX : 00000000
; EBX : 7EFDE000
; ECX : 77B56300 &L"10597318"
; EDX : 00000016
; EBP : 0018FF2C
; ESP : 0018FF18
; ESI : 4B7DFFB8
; EDI : 003808D8 &"Ô\t8"
; EIP : 00424EAC insertjsonlist.00424EAC
; EFLAGS : 00010246
; ZF : 1 "«««««îþ"
; OF : 0 "««îþîþîþ"
; CF : 0
; PF : 1
; SF : 0
; TF : 0 L'Ā'
; AF : 0 L'Ā'
; DF : 0 "îþ««««««««îþîþîþ"
; If : 1
; LastError : 00000008 (ERROR_NOT_ENOUGH_MEMORY)
; LastStatus : C0000017 (STATUS_NO_MEMORY)
; 0018FF18 2B261984
; 0018FF1C 00424BE1 zurück zu insertjsonlist.00424BE1 von insertjsonlist.00424E8A
; 0018FF20 4B7DFFB8
; 0018FF24 0000000A
; 0018FF28 00000000
; 0018FF2C 4F448684
; 0018FF30 004010FA zurück zu insertjsonlist.004010FA von insertjsonlist.00424BC1
; 0018FF34 4B7DFFB8
; 0018FF38 003808D8 &"Ô\t8"
; 0018FF3C 00000000
; 0018FF40 004021FB zurück zu insertjsonlist.004021FB von insertjsonlist.00401000
; 0018FF44 00400000 insertjsonlist.00400000
; 0018FF48 00000000
; 0018FF4C 008C625F
; 0018FF50 0000000A
; 0018FF54 9C4F5EE8
; 0018FF58 00000000
; 0018FF5C 00000000
; 0018FF60 7EFDE000
; 0018FF64 D7C46F00
; 0018FF68 00000066
; 0018FF6C 0051BFE7
; 0018FF70 0018FF54 "è^Oœ"
; 0018FF74 4B8B31E9 &L"12731659"
; 0018FF78 0018FFC4 Zeiger auf SEH_Record [1]
; 0018FF7C 004181F0 insertjsonlist.004181F0
; 0018FF80 9C136688
; 0018FF84 00000000
; 0018FF88 0018FF94
; 0018FF8C 75F7337A zurück zu kernel32.75F7337A von ???
; or
; 0043CC75 | 66:890A | mov word ptr ds:[edx],cx |
; EAX : 00000000
; EBX : 00000000
; ECX : 00000031 '1'
; EDX : 00000000
; EBP : 0018FEE4
; ESP : 0018FEE0
; ESI : 2C0EC332 L"0668477"
; EDI : 2C0EC330 L"10668477"
; EIP : 0043CC75 insertjsonlist.0043CC75
; EFLAGS : 00010246
; ZF : 1
; OF : 0
; CF : 0 "««««««îþ"
; PF : 1
; SF : 0
; TF : 0 L'Ā'
; AF : 0 L'Ā'
; DF : 0 "îþ««««««««îþîþîþ"
; If : 1
; LastError : 00000008 (ERROR_NOT_ENOUGH_MEMORY)
; LastStatus : C0000017 (STATUS_NO_MEMORY)
; 0018FEE0 77B1FD2C
; 0018FEE4 0018FF0C
; 0018FEE8 00424F21 zurück zu insertjsonlist.00424F21 von insertjsonlist.0043CC61
; 0018FEEC 00000000
; 0018FEF0 2C0EC330 L"10668477"
; 0018FEF4 7EFDE000
; 0018FEF8 003D08D8 &"Ô\t="
; 0018FEFC 2B150E44
; 0018FF00 00424B25 zurück zu insertjsonlist.00424B25 von insertjsonlist.00424ED9
; 0018FF04 77B1FD2C
; 0018FF08 2C0EC330 L"10668477"
; 0018FF0C 0018FF2C
; 0018FF10 00424C14 zurück zu insertjsonlist.00424C14 von insertjsonlist.00424AC8
; 0018FF14 77B1FD2C
; 0018FF18 00000008
; 0018FF1C 0000000C
; 0018FF20 2B150E4C &L"10668477"
; 0018FF24 0000000A
; 0018FF28 00000000
; 0018FF2C 4F338684
; 0018FF30 004010FA zurück zu insertjsonlist.004010FA von insertjsonlist.00424BC1
; 0018FF34 4B6CFFB8
; 0018FF38 003D08D8 &"Ô\t="
; 0018FF3C 00000000
; 0018FF40 004021FB zurück zu insertjsonlist.004021FB von insertjsonlist.00401000
; 0018FF44 00400000 insertjsonlist.00400000
; 0018FF48 00000000
; 0018FF4C 0056625F
; 0018FF50 0000000A
; 0018FF54 89E32058
; 0018FF58 00000000
; 0018FF5C 00000000
; 0018FF60 7EFDE000
; 0018FF64 7FDAAC00
; 0018FF68 00000066
; 0018FF6C 00E3091F
; 0018FF70 0018FF54 "X ã‰"
; 0018FF74 F6398C57
; 0018FF78 0018FFC4 Zeiger auf SEH_Record [1]
; 0018FF7C 004181F0 insertjsonlist.004181F0
; 0018FF80 89BF1838
; 0018FF84 00000000
; 0018FF88 0018FF94
; 0018FF8C 75F7337A zurück zu kernel32.75F7337A von ???
Re: InsertJSONList() Crashed on bigger Lists
Posted: Sat Apr 06, 2024 10:44 am
by infratec
It is definately not a problem of 'not enough memory'
The problem occours only if the map have a structure.
Code: Select all
EnableExplicit
Structure s_resultItem
AsNumber.i
EndStructure
Structure s_result
Map Column.i();s_resultItem()
EndStructure
Procedure ExportResults(List Row.s_result())
Protected.i jSon
jSon = CreateJSON(#PB_Any)
If jSon
Debug ListSize(Row())
Debug JSONValue(jSon)
InsertJSONList(JSONValue(jSon), Row())
FreeJSON(jSon)
EndIf
EndProcedure
#Max = 200000 ; IMA at InsertJSONList()
;Max = 100000 ; No Error
Define i.i, x.i
NewList Row.s_result()
For i=1 To #Max
AddElement(Row())
For x = 65 To 90
;Row()\Column(Chr(x))\AsNumber = Random(200000)
Row()\Column(Chr(x)) = Random(200000)
Next x
Next i
ExportResults(Row())
If you use the structure -> IMA
Re: InsertJSONList() Crashed on bigger Lists
Posted: Sat Apr 06, 2024 10:53 am
by Bisonte
Thanks for the workaround, that will help to export databasetables.
But is this a bug in the x86 Version ?
Because it is in all PB6 x86 versions .... ( I dont tested the versions <6)
Edit :
The Workaround is not working with datas. I tried to make a new list with only a map column.s() and it's the same...
I have at least 220k rows with datas in 18 fields. and in both cases (Map with structure and only map as string)
it crashed....
Re: InsertJSONList() Crashed on bigger Lists
Posted: Wed Apr 10, 2024 2:24 pm
by Fred
Your code needs 8GB or ram to run here on x64, so it crashs on x86 when hitting the 2GB limits. You can see this in the process monitor. This is due to the fact than the internal representation of a JSON is a tree with a lot of pointers for key/values, dynamically allocated maps for the elements handling so it's much bigger than the resulting file (which is already 500MB).
Re: InsertJSONList() Crashed on bigger Lists
Posted: Wed Apr 10, 2024 4:05 pm
by tored
If you are working with large data sets it is better to write one JSON row at a time
Code: Select all
EnableExplicit
DisableDebugger
#MAX = 200000
#FILEPATH = "testfile.json" ; Change it !
Structure s_resultItem
AsString.s
AsNumber.q
EndStructure
NewMap columns.s_resultItem()
Define file = CreateFile(#PB_Any, #FILEPATH, #PB_UTF8)
If Not file
MessageRequester("Error", "Failed creating file " + #FILEPATH, #PB_MessageRequester_Error)
End 1
EndIf
#JSON_ID = 0
If Not CreateJSON(#JSON_ID, #PB_JSON_NoCase)
MessageRequester("Error", "Failed creating JSON", #PB_MessageRequester_Error)
End 1
EndIf
WriteStringN(file, "[")
Define i, x, size, *buffer, bufferSize
For i = 1 To #MAX
For x = 65 To 89
columns(Chr(x))\AsString = Chr(x) + "a1"
columns(Chr(x))\AsNumber = Random(200000, 0)
Next x
InsertJSONMap(JSONValue(#JSON_ID), columns())
size = ExportJSONSize(#JSON_ID)
If size > bufferSize
*buffer = ReAllocateMemory(*buffer, size, #PB_Memory_NoClear)
If Not *buffer
MessageRequester("Error", "Failed allocating memory size " + size, #PB_MessageRequester_Error)
End 1
EndIf
bufferSize = size
EndIf
If Not ExportJSON(#JSON_ID, *buffer, size)
MessageRequester("Error", "Failed exporting JSON to buffer", #PB_MessageRequester_Error)
End 1
EndIf
If Not WriteData(file, *buffer, size)
MessageRequester("Error", "Failed writing JSON buffer to file", #PB_MessageRequester_Error)
End 1
EndIf
If i = #MAX
WriteStringN(file, "")
Else
WriteStringN(file, ",")
EndIf
ClearMap(columns())
ClearJSONMembers(JSONValue(#JSON_ID))
Next i
FreeJSON(#JSON_ID)
FreeMemory(*buffer)
WriteStringN(file, "]")
CloseFile(file)
; Just to verify the JSON file if small enough
;
; If Not CreateJSON(#JSON_ID)
; MessageRequester("Error", "Failed creating JSON", #PB_MessageRequester_Error)
; End 1
; EndIf
; If Not LoadJSON(#JSON_ID, #FILEPATH, #PB_JSON_NoCase)
; MessageRequester("Error", "Failed loading JSON from file " + #FILEPATH, #PB_MessageRequester_Error)
; End 1
; EndIf
; If IsJSON(#JSON_ID)
; MessageRequester("Success", "File has valid JSON", #PB_MessageRequester_Info)
; Else
; MessageRequester("Error", "File has invalid JSON", #PB_MessageRequester_Error)
; EndIf
; FreeJSON(#JSON_ID)
Edit: Small optimization, no need to reallocate buffer if JSON row already fits in buffer, now checks bufferSize