R 中是否有比 readLines 更快的东西 - 或者我如何找出读取连接速度如此慢的原因?

Spa*_*tan 2 c sockets r

我在c(客户端)和R(R充当服务器..使用RStudio)之间有一个套接字连接。C在R中发送一串5个数字。例如:

1 16.29 3.8 0 0
Run Code Online (Sandbox Code Playgroud)

在 RI 中,我使用以下方式接收字符串:

    con <- socketConnection(host="localhost", port = 8080, blocking=TRUE,
                        server=TRUE, open="r+")
Run Code Online (Sandbox Code Playgroud)

下一行是:

helloTall <- readLines(con,1)
Run Code Online (Sandbox Code Playgroud)

这些行读起来很好,但问题是我必须非常频繁地执行此操作(这是一个时间步长耦合练习,因此我必须执行此操作 > 1000 次,在某些情况下超过 500k 次)。

readLines 对于此类工作来说非常慢,而 readChar 也好不到哪儿去。是否有其他(更快)的方法来从连接读取上述短字符串?

我正在使用 R 3.5.2。

更新:鉴于目前还没有回复,这里还有几点。有没有一种快速的方法可以从套接字读取 5 个数字?我的理解是这些是作为字符串出现的。readLines 需要 1 分钟来读取这 5 个数字,因此在我的情况下,如果时间步长超过 5000,我将需要 >5000 分钟!

更新 2:我现在也尝试了“扫描”连接的内容,但速度同样慢:

hello2<-scan(con, sep=" ")
Run Code Online (Sandbox Code Playgroud)

读完这5个数字也需要一分钟。这是否意味着 con 有很多空值或空格或某些会减慢读取其内容的速度?我对人际关系几乎一无所知。

根据其中一条评论的请求,我还发布了本例中作为客户端的 C 代码(请注意,本例中的 C 代码是从 Fortran 程序调用的):

// Client side C/C++ program to demonstrate Socket programming 
#include <stdio.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <stdint.h>
#define PORT 8080 


/*int main(int argc, char const *argv[]) */
void client_(int *nsinc, double *rTairExch, double *rToutExch, double *rTsolExch, double *ResTair) 
{ 
    struct sockaddr_in address; 
    int sock = 0, valread; 
    struct sockaddr_in serv_addr; 
    int itimensinc = *nsinc;
    double NoBitrTairExch=*rTairExch;
    double NoBitrToutExch=*rToutExch;
    double NoBitrTsolExch=*rTsolExch;
    double NoBitResTair=*ResTair;
    double length = snprintf( NULL, 0, \
                   "%d %.4g %.4g %.4g %.4g", itimensinc,NoBitrTairExch,NoBitrToutExch,NoBitrTsolExch,NoBitResTair,"\n");
    char* str = malloc( length + 1 );
    snprintf( str, length + 1,"%d %.4g %.4g %.4g %.4g",itimensinc,NoBitrTairExch,NoBitrToutExch,NoBitrTsolExch,NoBitResTair,"\n");
    char buffer[1024] = {0}; 
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    { 
        printf("\n Socket creation error \n"); 
        return; 
    } 

    memset(&serv_addr, '0', sizeof(serv_addr)); 

    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_port = htons(PORT); 

    // Convert IPv4 and IPv6 addresses from text to binary form 
    if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)  
    { 
        printf("\nInvalid address/ Address not supported \n"); 
        return; 
    } 

    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) 
    { 
        printf("\nConnection Failed \n"); 
        return; 
    } 

    send(sock , str , strlen(str) , 0 ); 
    printf("Hello message sent\n"); 
    valread = read( sock , buffer, 1024); 
    printf("%s\n",buffer ); 

/* Define temporary variables */
    char *eptr;
    double result;
    result = strtod(buffer, &eptr);
    printf("return value\n"); 
    printf("%.2lf",result);
    *ResTair=result;

    return; 
} 
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我现在也将其发布到 R 社区论坛: https: //community.rstudio.com/t/is-there-anything-faster-than-readlines-in-r/23346/5

先感谢您。

PaS*_*STE 5

\n编写的 C 程序不会通过套接字发送换行符 ( )。您的 R 客户端正在等待换行符以完成 或readLinesscan并且它会一直这样做,直到遇到R 网络连接的默认1 分钟超时。

C 代码中有问题的行在这里:

snprintf(str, length + 1,
         "%d %.4g %.4g %.4g %.4g",  /* <-- 5 format specifiers */
         itimensinc,NoBitrTairExch,NoBitrToutExch,NoBitrTsolExch,NoBitResTair,  /* <-- 5 things to format */
         "\n");  /* <-- this is never added to str */
Run Code Online (Sandbox Code Playgroud)

snprintf与该系列的所有函数一样, C 函数printf默默地忽略不适合格式字符串的额外参数。

尝试在格式字符串本身中包含换行符,或者添加字符串或字符格式说明符:

snprintf(str, length + 1,
         "%d %.4g %.4g %.4g %.4g\n",  /* <-- 5 format specifiers and a newline */
         itimensinc,NoBitrTairExch,NoBitrToutExch,NoBitrTsolExch,NoBitResTair);  /* <-- 5 things to format */

/* or */

snprintf(str, length + 1,
         "%d %.4g %.4g %.4g %.4g%c",  /* <-- 6 format specifiers */
         itimensinc,NoBitrTairExch,NoBitrToutExch,NoBitrTsolExch,NoBitResTair,'\n');  /* <-- 6 things to format */
Run Code Online (Sandbox Code Playgroud)